Changeset 23192 in osm for applications/editors/josm/plugins/OpeningHoursEditor
- Timestamp:
- 2010-09-15T18:59:53+02:00 (15 years ago)
- Location:
- applications/editors/josm/plugins/OpeningHoursEditor/src/org/openstreetmap/josm/plugins/ohe
- Files:
-
- 8 edited
-
OhePlugin.java (modified) (1 diff)
-
OpeningTimeUtils.java (modified) (1 diff)
-
gui/OheDialogPanel.java (modified) (1 diff)
-
gui/OheEditor.java (modified) (1 diff)
-
gui/TimeRect.java (modified) (1 diff)
-
parser/OpeningTimeCompilerTokenManager.java (modified) (2 diffs)
-
parser/SyntaxException.java (modified) (1 diff)
-
parser/TokenMgrError.java (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/OpeningHoursEditor/src/org/openstreetmap/josm/plugins/ohe/OhePlugin.java
r22873 r23192 38 38 public class OhePlugin extends Plugin { 39 39 40 // Strings for choosing which key of an object with given tags should be41 // edited42 // the order is referencing the preference of the keys43 // String[] -> {key, value, to-editing-key} key and value can contain regexp44 private final String[][] TAG_EDIT_STRINGS = new String[][] {45 { "opening_hours", ".*", "opening_hours" },46 { "collection_times", ".*", "collection_times" },47 { "collection_times:local", ".*", "collection_times:local" },48 { "lit", ".*", "lit" },49 { "amenity", "post_box", "collection_times" },50 { "amenity", ".*", "opening_hours" },51 { "shop", ".*", "opening_hours" }, { "highway", ".*", "lit" } };52 53 /**54 * Will be invoked by JOSM to bootstrap the plugin55 * 56 * @param info57 * information about the plugin and its local installation58 */59 public OhePlugin(PluginInformation info) {60 super(info);61 Main.main.menu.toolsMenu.add(new OheMenuAction());62 }63 64 class OheMenuAction extends JosmAction {65 public OheMenuAction() {66 super(67 tr("Edit opening hours"),68 "opening_hours.png",69 tr("Edit time-tag of selected element in a graphical interface"),70 Shortcut.registerShortcut("tools:opening_hourseditor", tr(71 "Tool: {0}", tr("Edit opening hours")),72 KeyEvent.VK_T, Shortcut.GROUP_MENU), false);73 }74 75 @Override76 protected void updateEnabledState() {77 if (getCurrentDataSet() == null) {78 setEnabled(false);79 } else {80 updateEnabledState(getCurrentDataSet().getSelected());81 }82 }83 84 @Override85 protected void updateEnabledState(86 Collection<? extends OsmPrimitive> selection) {87 setEnabled(selection != null && !selection.isEmpty());88 }89 90 public void actionPerformed(ActionEvent evt) {91 // fetch active Layer92 OsmDataLayer osmlayer = Main.main.getEditLayer();93 if (osmlayer != null) {94 Collection<OsmPrimitive> selection = osmlayer.data95 .getSelected();96 if (selection.size() == 1) { // one object selected97 OsmPrimitive object = selection.iterator().next();98 String[] keyValuePair = editTimeTags(object.getKeys());99 if (keyValuePair != null) {100 String key = keyValuePair[0].trim();101 String newkey = keyValuePair[1].trim();102 String value = keyValuePair[2].trim();103 104 if (value.equals("")) {105 value = null; // delete the key106 }107 if (newkey.equals("")) {108 newkey = key;109 value = null; // delete the key instead110 }111 if (key.equals(newkey)112 && tr("<different>").equals(value))113 return;114 if (key.equals(newkey) || value == null) {115 Main.main.undoRedo.add(new ChangePropertyCommand(116 object, newkey, value));117 } else {118 Collection<Command> commands = new Vector<Command>();119 commands.add(new ChangePropertyCommand(object, key,120 null));121 commands.add(new ChangePropertyCommand(object,122 newkey, value));123 Main.main.undoRedo.add(new SequenceCommand(124 tr("Change properties of 1 object"),125 commands));126 }127 }128 } else { // Not possible to edit 0, 2 or more objects129 JOptionPane130 .showMessageDialog(131 Main.parent,132 tr(133 "You have {0} Elements selected. But you can edit only one element!",134 selection.size()),135 "openingHoursEditor Warning",136 JOptionPane.ERROR_MESSAGE);137 }138 }139 }140 }141 142 // opens up dialogs to change one of the key-value-pairs and returns the143 // changed pair144 private String[] editTimeTags(Map<String, String> keyValueMap) {145 String selectedKey = "";146 147 if ((selectedKey = tagChooseDialog(keyValueMap)) == null)148 return null;149 150 final String value = (keyValueMap.containsKey(selectedKey)) ? keyValueMap151 .get(selectedKey)152 : "";153 OheDialogPanel panel = new OheDialogPanel(this, selectedKey, value);154 155 final JOptionPane optionPane = new JOptionPane(panel,156 JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);157 final JDialog dlg = optionPane.createDialog(Main.parent, tr("Edit"));158 159 dlg.setResizable(true);160 dlg.setVisible(true);161 162 Object answer = optionPane.getValue();163 if (!(answer == null || answer == JOptionPane.UNINITIALIZED_VALUE || (answer instanceof Integer && (Integer) answer != JOptionPane.OK_OPTION)))164 return panel.getChangedKeyValuePair();165 166 return null;167 }168 169 // opens a dialog for choosing from a set of tags which can be edited170 // the chosen one is returned171 private String tagChooseDialog(Map<String, String> keyValueMap) {172 String preSelectedKey = getPreSelectedKey(keyValueMap);173 int preSelectedRow = -1;174 175 String[][] rowData = new String[keyValueMap.size()][2];176 int cnt = 0;177 for (Object key : keyValueMap.keySet().toArray()) {178 rowData[cnt][0] = key.toString();179 rowData[cnt][1] = keyValueMap.get(key);180 if (key.toString().equals(preSelectedKey))181 preSelectedRow = cnt;182 cnt++;183 }184 185 final JTable table = new JTable(rowData,186 new String[] { "key", "value" }) {187 public boolean isCellEditable(int rowIndex, int colIndex) {188 return false; // Disallow the editing of any cell189 }190 };191 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);192 JScrollPane sp = new JScrollPane(193 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,194 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);195 sp.setViewportView(table);196 197 final JTextField tf = new JTextField();198 199 ActionListener al = new ActionListener() {200 @Override201 public void actionPerformed(ActionEvent e) {202 if (e.getActionCommand().equals("edit")) {203 table.setEnabled(true);204 tf.setEnabled(false);205 } else if (e.getActionCommand().equals("new")) {206 table.setEnabled(false);207 tf.setEnabled(true);208 }209 }210 };211 212 JRadioButton editButton = new JRadioButton("edit existing tag");213 editButton.setActionCommand("edit");214 editButton.addActionListener(al);215 JRadioButton newButton = new JRadioButton("edit new tag");216 newButton.setActionCommand("new");217 newButton.addActionListener(al);218 ButtonGroup group = new ButtonGroup();219 group.add(newButton);220 group.add(editButton);221 222 if (preSelectedRow != -1) {223 table.setEnabled(true);224 tf.setEnabled(false);225 table.setRowSelectionInterval(preSelectedRow, preSelectedRow);226 editButton.setSelected(true);227 } else {228 table.setEnabled(false);229 tf.setEnabled(true);230 tf.setText(preSelectedKey);231 newButton.setSelected(true);232 }233 234 JPanel dlgPanel = new JPanel(new GridBagLayout());235 dlgPanel.add(editButton, GBC.std().anchor(GBC.CENTER));236 dlgPanel.add(sp, GBC.eol().fill(GBC.BOTH));237 dlgPanel.add(newButton, GBC.std().anchor(GBC.CENTER));238 dlgPanel.add(tf, GBC.eol().fill(GBC.HORIZONTAL));239 240 JOptionPane optionPane = new JOptionPane(dlgPanel,241 JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION);242 JDialog dlg = optionPane.createDialog(Main.parent, tr("Choose key"));243 244 dlg.pack();245 dlg.setResizable(true);246 dlg.setVisible(true);247 248 Object answer = optionPane.getValue();249 if (answer != null250 && answer != JOptionPane.UNINITIALIZED_VALUE251 && (answer instanceof Integer && (Integer) answer == JOptionPane.OK_OPTION))252 if (editButton.isSelected() && table.getSelectedRow() != -1)253 return rowData[table.getSelectedRow()][0];254 else if (newButton.isSelected())255 return tf.getText();256 257 return null;258 }259 260 private String getPreSelectedKey(Map<String, String> keyValueMap) {261 for (String[] pattern : TAG_EDIT_STRINGS) {262 Pattern keyPattern = Pattern.compile(pattern[0]);263 Pattern valuePattern = Pattern.compile(pattern[1]);264 for (Object key : keyValueMap.keySet().toArray()) {265 Matcher keyMatcher = keyPattern.matcher(key.toString());266 if (keyMatcher.matches()) {267 Matcher valueMatcher = valuePattern.matcher(keyValueMap268 .get(key));269 if (valueMatcher.matches()) {270 return pattern[2];271 }272 }273 }274 }275 return "";276 }40 // Strings for choosing which key of an object with given tags should be 41 // edited 42 // the order is referencing the preference of the keys 43 // String[] -> {key, value, to-editing-key} key and value can contain regexp 44 private final String[][] TAG_EDIT_STRINGS = new String[][] { 45 { "opening_hours", ".*", "opening_hours" }, 46 { "collection_times", ".*", "collection_times" }, 47 { "collection_times:local", ".*", "collection_times:local" }, 48 { "lit", ".*", "lit" }, 49 { "amenity", "post_box", "collection_times" }, 50 { "amenity", ".*", "opening_hours" }, 51 { "shop", ".*", "opening_hours" }, { "highway", ".*", "lit" } }; 52 53 /** 54 * Will be invoked by JOSM to bootstrap the plugin 55 * 56 * @param info 57 * information about the plugin and its local installation 58 */ 59 public OhePlugin(PluginInformation info) { 60 super(info); 61 Main.main.menu.toolsMenu.add(new OheMenuAction()); 62 } 63 64 class OheMenuAction extends JosmAction { 65 public OheMenuAction() { 66 super( 67 tr("Edit opening hours"), 68 "opening_hours.png", 69 tr("Edit time-tag of selected element in a graphical interface"), 70 Shortcut.registerShortcut("tools:opening_hourseditor", tr( 71 "Tool: {0}", tr("Edit opening hours")), 72 KeyEvent.VK_T, Shortcut.GROUP_MENU), false); 73 } 74 75 @Override 76 protected void updateEnabledState() { 77 if (getCurrentDataSet() == null) { 78 setEnabled(false); 79 } else { 80 updateEnabledState(getCurrentDataSet().getSelected()); 81 } 82 } 83 84 @Override 85 protected void updateEnabledState( 86 Collection<? extends OsmPrimitive> selection) { 87 setEnabled(selection != null && !selection.isEmpty()); 88 } 89 90 public void actionPerformed(ActionEvent evt) { 91 // fetch active Layer 92 OsmDataLayer osmlayer = Main.main.getEditLayer(); 93 if (osmlayer != null) { 94 Collection<OsmPrimitive> selection = osmlayer.data 95 .getSelected(); 96 if (selection.size() == 1) { // one object selected 97 OsmPrimitive object = selection.iterator().next(); 98 String[] keyValuePair = editTimeTags(object.getKeys()); 99 if (keyValuePair != null) { 100 String key = keyValuePair[0].trim(); 101 String newkey = keyValuePair[1].trim(); 102 String value = keyValuePair[2].trim(); 103 104 if (value.equals("")) { 105 value = null; // delete the key 106 } 107 if (newkey.equals("")) { 108 newkey = key; 109 value = null; // delete the key instead 110 } 111 if (key.equals(newkey) 112 && tr("<different>").equals(value)) 113 return; 114 if (key.equals(newkey) || value == null) { 115 Main.main.undoRedo.add(new ChangePropertyCommand( 116 object, newkey, value)); 117 } else { 118 Collection<Command> commands = new Vector<Command>(); 119 commands.add(new ChangePropertyCommand(object, key, 120 null)); 121 commands.add(new ChangePropertyCommand(object, 122 newkey, value)); 123 Main.main.undoRedo.add(new SequenceCommand( 124 tr("Change properties of 1 object"), 125 commands)); 126 } 127 } 128 } else { // Not possible to edit 0, 2 or more objects 129 JOptionPane 130 .showMessageDialog( 131 Main.parent, 132 tr( 133 "You have {0} Elements selected. But you can edit only one element!", 134 selection.size()), 135 "openingHoursEditor Warning", 136 JOptionPane.ERROR_MESSAGE); 137 } 138 } 139 } 140 } 141 142 // opens up dialogs to change one of the key-value-pairs and returns the 143 // changed pair 144 private String[] editTimeTags(Map<String, String> keyValueMap) { 145 String selectedKey = ""; 146 147 if ((selectedKey = tagChooseDialog(keyValueMap)) == null) 148 return null; 149 150 final String value = (keyValueMap.containsKey(selectedKey)) ? keyValueMap 151 .get(selectedKey) 152 : ""; 153 OheDialogPanel panel = new OheDialogPanel(this, selectedKey, value); 154 155 final JOptionPane optionPane = new JOptionPane(panel, 156 JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); 157 final JDialog dlg = optionPane.createDialog(Main.parent, tr("Edit")); 158 159 dlg.setResizable(true); 160 dlg.setVisible(true); 161 162 Object answer = optionPane.getValue(); 163 if (!(answer == null || answer == JOptionPane.UNINITIALIZED_VALUE || (answer instanceof Integer && (Integer) answer != JOptionPane.OK_OPTION))) 164 return panel.getChangedKeyValuePair(); 165 166 return null; 167 } 168 169 // opens a dialog for choosing from a set of tags which can be edited 170 // the chosen one is returned 171 private String tagChooseDialog(Map<String, String> keyValueMap) { 172 String preSelectedKey = getPreSelectedKey(keyValueMap); 173 int preSelectedRow = -1; 174 175 String[][] rowData = new String[keyValueMap.size()][2]; 176 int cnt = 0; 177 for (Object key : keyValueMap.keySet().toArray()) { 178 rowData[cnt][0] = key.toString(); 179 rowData[cnt][1] = keyValueMap.get(key); 180 if (key.toString().equals(preSelectedKey)) 181 preSelectedRow = cnt; 182 cnt++; 183 } 184 185 final JTable table = new JTable(rowData, 186 new String[] { "key", "value" }) { 187 public boolean isCellEditable(int rowIndex, int colIndex) { 188 return false; // Disallow the editing of any cell 189 } 190 }; 191 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 192 JScrollPane sp = new JScrollPane( 193 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 194 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 195 sp.setViewportView(table); 196 197 final JTextField tf = new JTextField(); 198 199 ActionListener al = new ActionListener() { 200 @Override 201 public void actionPerformed(ActionEvent e) { 202 if (e.getActionCommand().equals("edit")) { 203 table.setEnabled(true); 204 tf.setEnabled(false); 205 } else if (e.getActionCommand().equals("new")) { 206 table.setEnabled(false); 207 tf.setEnabled(true); 208 } 209 } 210 }; 211 212 JRadioButton editButton = new JRadioButton("edit existing tag"); 213 editButton.setActionCommand("edit"); 214 editButton.addActionListener(al); 215 JRadioButton newButton = new JRadioButton("edit new tag"); 216 newButton.setActionCommand("new"); 217 newButton.addActionListener(al); 218 ButtonGroup group = new ButtonGroup(); 219 group.add(newButton); 220 group.add(editButton); 221 222 if (preSelectedRow != -1) { 223 table.setEnabled(true); 224 tf.setEnabled(false); 225 table.setRowSelectionInterval(preSelectedRow, preSelectedRow); 226 editButton.setSelected(true); 227 } else { 228 table.setEnabled(false); 229 tf.setEnabled(true); 230 tf.setText(preSelectedKey); 231 newButton.setSelected(true); 232 } 233 234 JPanel dlgPanel = new JPanel(new GridBagLayout()); 235 dlgPanel.add(editButton, GBC.std().anchor(GBC.CENTER)); 236 dlgPanel.add(sp, GBC.eol().fill(GBC.BOTH)); 237 dlgPanel.add(newButton, GBC.std().anchor(GBC.CENTER)); 238 dlgPanel.add(tf, GBC.eol().fill(GBC.HORIZONTAL)); 239 240 JOptionPane optionPane = new JOptionPane(dlgPanel, 241 JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION); 242 JDialog dlg = optionPane.createDialog(Main.parent, tr("Choose key")); 243 244 dlg.pack(); 245 dlg.setResizable(true); 246 dlg.setVisible(true); 247 248 Object answer = optionPane.getValue(); 249 if (answer != null 250 && answer != JOptionPane.UNINITIALIZED_VALUE 251 && (answer instanceof Integer && (Integer) answer == JOptionPane.OK_OPTION)) 252 if (editButton.isSelected() && table.getSelectedRow() != -1) 253 return rowData[table.getSelectedRow()][0]; 254 else if (newButton.isSelected()) 255 return tf.getText(); 256 257 return null; 258 } 259 260 private String getPreSelectedKey(Map<String, String> keyValueMap) { 261 for (String[] pattern : TAG_EDIT_STRINGS) { 262 Pattern keyPattern = Pattern.compile(pattern[0]); 263 Pattern valuePattern = Pattern.compile(pattern[1]); 264 for (Object key : keyValueMap.keySet().toArray()) { 265 Matcher keyMatcher = keyPattern.matcher(key.toString()); 266 if (keyMatcher.matches()) { 267 Matcher valueMatcher = valuePattern.matcher(keyValueMap 268 .get(key)); 269 if (valueMatcher.matches()) { 270 return pattern[2]; 271 } 272 } 273 } 274 } 275 return ""; 276 } 277 277 } -
applications/editors/josm/plugins/OpeningHoursEditor/src/org/openstreetmap/josm/plugins/ohe/OpeningTimeUtils.java
r22751 r23192 7 7 8 8 public class OpeningTimeUtils { 9 // implements the subtraction of daytimes in spans of days when a day in10 // the list occurs direct afterwards11 public static ArrayList<int[]> convert(ArrayList<DateTime> dateTimes) {12 ArrayList<int[]> ret = new ArrayList<int[]>(); // the list which is13 // returned14 for (int i = 0; i < dateTimes.size(); ++i) { // iterate over every entry15 DateTime dateTime = dateTimes.get(i);16 ArrayList<DateTime> newDateTimes = new ArrayList<DateTime>();17 18 // test if the given entry is a single dayspan19 if (dateTime.daySpans.size() == 120 && dateTime.daySpans.get(0).isSpan()) {21 ArrayList<DaySpan> partDaySpans = new ArrayList<DaySpan>();22 int start_day = dateTime.daySpans.get(0).startDay;23 24 // look in every entry behind25 while (i + 1 < dateTimes.size()) {26 ArrayList<DaySpan> following = dateTimes.get(i + 1).daySpans;27 if (following.size() == 128 && following.get(0).startDay > dateTime.daySpans29 .get(0).startDay30 && following.get(0).endDay < dateTime.daySpans31 .get(0).endDay) {32 partDaySpans.add(new DaySpan(start_day, following33 .get(0).startDay - 1));34 start_day = following.get(0).endDay + 1;35 newDateTimes.add(dateTimes.get(i + 1));36 i++;37 } else38 break;39 }40 41 partDaySpans.add(new DaySpan(start_day, dateTime.daySpans42 .get(0).endDay));43 newDateTimes.add(new DateTime(partDaySpans,44 dateTime.daytimeSpans));45 }46 if (newDateTimes.isEmpty())47 newDateTimes.add(dateTime);48 49 // create the int-array50 for (int j = 0; j < newDateTimes.size(); ++j) {51 DateTime dateTime2 = newDateTimes.get(j);52 for (DaySpan dayspan : dateTime2.daySpans) {53 for (DaytimeSpan timespan : dateTime2.daytimeSpans) {54 if (!timespan.isOff())55 ret.add(new int[] { dayspan.startDay,56 dayspan.endDay, timespan.startMinute,57 timespan.endMinute });58 }59 }60 }61 }62 return ret;63 }64 65 public static class DaySpan {66 public int startDay;67 public int endDay;68 69 public DaySpan(int startDay, int endDay) {70 this.startDay = startDay;71 this.endDay = endDay;72 }73 74 public boolean isSpan() {75 return endDay > startDay;76 }77 78 public boolean isSingleDay() {79 return startDay == endDay;80 }81 }82 83 public static class DaytimeSpan {84 public int startMinute;85 public int endMinute;86 87 public DaytimeSpan(int startMinute, int endMinute) {88 this.startMinute = startMinute;89 this.endMinute = endMinute;90 }91 92 public boolean isOff() {93 return startMinute == -1;94 }95 96 public boolean isSpan() {97 return endMinute > startMinute;98 }99 }100 101 public static class DateTime {102 public ArrayList<DaySpan> daySpans;103 public ArrayList<DaytimeSpan> daytimeSpans;104 105 public DateTime(ArrayList<DaySpan> daySpans,106 ArrayList<DaytimeSpan> daytimeSpans) {107 this.daySpans = daySpans;108 this.daytimeSpans = daytimeSpans;109 }110 }111 112 // returns a String (e.g "Mo-Sa 10:00-20:00; Tu off") representing the113 // TimeRects114 public static String makeStringFromRects(ArrayList<TimeRect> givenTimeRects) {115 // create an array of booleans representing every minute on all the days116 // in a week117 boolean[][] minuteArray = new boolean[7][24 * 60 + 2];118 for (int day = 0; day < 7; ++day)119 for (int minute = 0; minute < 24 * 60 + 2; ++minute)120 minuteArray[day][minute] = false;121 for (TimeRect timeRect : givenTimeRects)122 for (int day = timeRect.getDayStart(); day <= timeRect.getDayEnd(); ++day)123 for (int minute = timeRect.getMinuteStart(); minute <= timeRect124 .getMinuteEnd(); ++minute)125 minuteArray[day][minute] = true;126 127 String ret = "";128 int[] days = new int[7]; // an array representing the status of the days129 // 0 means nothing done with this day yet130 // 8 means the day is off131 // 0<x<8 means the day have the openinghours of day x132 // -8<x<0 means nothing done with this day yet, but it intersects a133 // range of days with same opening_hours134 for (int i = 0; i < 7; ++i) {135 String add = "";136 137 if (isArrayEmpty(minuteArray[i]) && days[i] == 0) {138 days[i] = 8;139 } else if (isArrayEmpty(minuteArray[i]) && days[i] < 0) {140 add = OpeningTimeCompiler.WEEKDAYS[i] + " off";141 days[i] = -8;142 } else if (days[i] <= 0) {143 days[i] = i + 1;144 int lastSameDay = i;145 int sameDayCount = 1;146 for (int j = i + 1; j < 7; ++j) {147 if (arraysEqual(minuteArray[i], minuteArray[j])) {148 days[j] = i + 1;149 lastSameDay = j;150 sameDayCount++;151 }152 }153 if (sameDayCount == 1) {154 // a single Day with this special opening_hours155 add = OpeningTimeCompiler.WEEKDAYS[i] + " "156 + makeStringFromMinuteArray(minuteArray[i]);157 } else if (sameDayCount == 2) {158 // exactly two Days with this special opening_hours159 add = OpeningTimeCompiler.WEEKDAYS[i] + ","160 + OpeningTimeCompiler.WEEKDAYS[lastSameDay] + " "161 + makeStringFromMinuteArray(minuteArray[i]);162 } else if (sameDayCount > 2) {163 // more than two Days with this special opening_hours164 add = OpeningTimeCompiler.WEEKDAYS[i] + "-"165 + OpeningTimeCompiler.WEEKDAYS[lastSameDay] + " "166 + makeStringFromMinuteArray(minuteArray[i]);167 for (int j = i + 1; j < lastSameDay; ++j) {168 if (days[j] == 0)169 days[j] = -i - 1;170 }171 }172 }173 174 if (!add.isEmpty()) {175 if (!ret.isEmpty())176 ret += "; ";177 ret += add;178 }179 }180 return ret;181 }182 183 // returns a String representing the openinghours on one special day (e.g.184 // "10:00-20:00")185 private static String makeStringFromMinuteArray(boolean[] minutes) {186 String ret = "";187 for (int i = 0; i < minutes.length; ++i) {188 if (minutes[i]) {189 int start = i;190 while (i < minutes.length && minutes[i])191 ++i;192 String addString = timeString(start);193 if (i - 1 == 24 * 60 + 1) // open end194 addString += "+";195 else if (start != i - 1) // closing time196 addString += "-" + timeString(i - 1);197 if (!ret.isEmpty())198 ret += ",";199 ret += addString;200 }201 }202 return ret;203 }204 205 public static String timeString(int minutes) {206 int h = minutes / 60;207 int m = minutes % 60;208 return (h < 10 ? "0" : "") + h + ":" + (m < 10 ? "0" : "") + m;209 }210 211 private static boolean isArrayEmpty(boolean[] bs) {212 for (int i = 0; i < bs.length; i++)213 if (bs[i])214 return false;215 return true;216 }217 218 private static boolean arraysEqual(boolean[] bs, boolean[] bs2) {219 boolean ret = true;220 for (int i = 0; i < bs.length; i++)221 ret &= bs[i] == bs2[i];222 return ret;223 }9 // implements the subtraction of daytimes in spans of days when a day in 10 // the list occurs direct afterwards 11 public static ArrayList<int[]> convert(ArrayList<DateTime> dateTimes) { 12 ArrayList<int[]> ret = new ArrayList<int[]>(); // the list which is 13 // returned 14 for (int i = 0; i < dateTimes.size(); ++i) { // iterate over every entry 15 DateTime dateTime = dateTimes.get(i); 16 ArrayList<DateTime> newDateTimes = new ArrayList<DateTime>(); 17 18 // test if the given entry is a single dayspan 19 if (dateTime.daySpans.size() == 1 20 && dateTime.daySpans.get(0).isSpan()) { 21 ArrayList<DaySpan> partDaySpans = new ArrayList<DaySpan>(); 22 int start_day = dateTime.daySpans.get(0).startDay; 23 24 // look in every entry behind 25 while (i + 1 < dateTimes.size()) { 26 ArrayList<DaySpan> following = dateTimes.get(i + 1).daySpans; 27 if (following.size() == 1 28 && following.get(0).startDay > dateTime.daySpans 29 .get(0).startDay 30 && following.get(0).endDay < dateTime.daySpans 31 .get(0).endDay) { 32 partDaySpans.add(new DaySpan(start_day, following 33 .get(0).startDay - 1)); 34 start_day = following.get(0).endDay + 1; 35 newDateTimes.add(dateTimes.get(i + 1)); 36 i++; 37 } else 38 break; 39 } 40 41 partDaySpans.add(new DaySpan(start_day, dateTime.daySpans 42 .get(0).endDay)); 43 newDateTimes.add(new DateTime(partDaySpans, 44 dateTime.daytimeSpans)); 45 } 46 if (newDateTimes.isEmpty()) 47 newDateTimes.add(dateTime); 48 49 // create the int-array 50 for (int j = 0; j < newDateTimes.size(); ++j) { 51 DateTime dateTime2 = newDateTimes.get(j); 52 for (DaySpan dayspan : dateTime2.daySpans) { 53 for (DaytimeSpan timespan : dateTime2.daytimeSpans) { 54 if (!timespan.isOff()) 55 ret.add(new int[] { dayspan.startDay, 56 dayspan.endDay, timespan.startMinute, 57 timespan.endMinute }); 58 } 59 } 60 } 61 } 62 return ret; 63 } 64 65 public static class DaySpan { 66 public int startDay; 67 public int endDay; 68 69 public DaySpan(int startDay, int endDay) { 70 this.startDay = startDay; 71 this.endDay = endDay; 72 } 73 74 public boolean isSpan() { 75 return endDay > startDay; 76 } 77 78 public boolean isSingleDay() { 79 return startDay == endDay; 80 } 81 } 82 83 public static class DaytimeSpan { 84 public int startMinute; 85 public int endMinute; 86 87 public DaytimeSpan(int startMinute, int endMinute) { 88 this.startMinute = startMinute; 89 this.endMinute = endMinute; 90 } 91 92 public boolean isOff() { 93 return startMinute == -1; 94 } 95 96 public boolean isSpan() { 97 return endMinute > startMinute; 98 } 99 } 100 101 public static class DateTime { 102 public ArrayList<DaySpan> daySpans; 103 public ArrayList<DaytimeSpan> daytimeSpans; 104 105 public DateTime(ArrayList<DaySpan> daySpans, 106 ArrayList<DaytimeSpan> daytimeSpans) { 107 this.daySpans = daySpans; 108 this.daytimeSpans = daytimeSpans; 109 } 110 } 111 112 // returns a String (e.g "Mo-Sa 10:00-20:00; Tu off") representing the 113 // TimeRects 114 public static String makeStringFromRects(ArrayList<TimeRect> givenTimeRects) { 115 // create an array of booleans representing every minute on all the days 116 // in a week 117 boolean[][] minuteArray = new boolean[7][24 * 60 + 2]; 118 for (int day = 0; day < 7; ++day) 119 for (int minute = 0; minute < 24 * 60 + 2; ++minute) 120 minuteArray[day][minute] = false; 121 for (TimeRect timeRect : givenTimeRects) 122 for (int day = timeRect.getDayStart(); day <= timeRect.getDayEnd(); ++day) 123 for (int minute = timeRect.getMinuteStart(); minute <= timeRect 124 .getMinuteEnd(); ++minute) 125 minuteArray[day][minute] = true; 126 127 String ret = ""; 128 int[] days = new int[7]; // an array representing the status of the days 129 // 0 means nothing done with this day yet 130 // 8 means the day is off 131 // 0<x<8 means the day have the openinghours of day x 132 // -8<x<0 means nothing done with this day yet, but it intersects a 133 // range of days with same opening_hours 134 for (int i = 0; i < 7; ++i) { 135 String add = ""; 136 137 if (isArrayEmpty(minuteArray[i]) && days[i] == 0) { 138 days[i] = 8; 139 } else if (isArrayEmpty(minuteArray[i]) && days[i] < 0) { 140 add = OpeningTimeCompiler.WEEKDAYS[i] + " off"; 141 days[i] = -8; 142 } else if (days[i] <= 0) { 143 days[i] = i + 1; 144 int lastSameDay = i; 145 int sameDayCount = 1; 146 for (int j = i + 1; j < 7; ++j) { 147 if (arraysEqual(minuteArray[i], minuteArray[j])) { 148 days[j] = i + 1; 149 lastSameDay = j; 150 sameDayCount++; 151 } 152 } 153 if (sameDayCount == 1) { 154 // a single Day with this special opening_hours 155 add = OpeningTimeCompiler.WEEKDAYS[i] + " " 156 + makeStringFromMinuteArray(minuteArray[i]); 157 } else if (sameDayCount == 2) { 158 // exactly two Days with this special opening_hours 159 add = OpeningTimeCompiler.WEEKDAYS[i] + "," 160 + OpeningTimeCompiler.WEEKDAYS[lastSameDay] + " " 161 + makeStringFromMinuteArray(minuteArray[i]); 162 } else if (sameDayCount > 2) { 163 // more than two Days with this special opening_hours 164 add = OpeningTimeCompiler.WEEKDAYS[i] + "-" 165 + OpeningTimeCompiler.WEEKDAYS[lastSameDay] + " " 166 + makeStringFromMinuteArray(minuteArray[i]); 167 for (int j = i + 1; j < lastSameDay; ++j) { 168 if (days[j] == 0) 169 days[j] = -i - 1; 170 } 171 } 172 } 173 174 if (!add.isEmpty()) { 175 if (!ret.isEmpty()) 176 ret += "; "; 177 ret += add; 178 } 179 } 180 return ret; 181 } 182 183 // returns a String representing the openinghours on one special day (e.g. 184 // "10:00-20:00") 185 private static String makeStringFromMinuteArray(boolean[] minutes) { 186 String ret = ""; 187 for (int i = 0; i < minutes.length; ++i) { 188 if (minutes[i]) { 189 int start = i; 190 while (i < minutes.length && minutes[i]) 191 ++i; 192 String addString = timeString(start); 193 if (i - 1 == 24 * 60 + 1) // open end 194 addString += "+"; 195 else if (start != i - 1) // closing time 196 addString += "-" + timeString(i - 1); 197 if (!ret.isEmpty()) 198 ret += ","; 199 ret += addString; 200 } 201 } 202 return ret; 203 } 204 205 public static String timeString(int minutes) { 206 int h = minutes / 60; 207 int m = minutes % 60; 208 return (h < 10 ? "0" : "") + h + ":" + (m < 10 ? "0" : "") + m; 209 } 210 211 private static boolean isArrayEmpty(boolean[] bs) { 212 for (int i = 0; i < bs.length; i++) 213 if (bs[i]) 214 return false; 215 return true; 216 } 217 218 private static boolean arraysEqual(boolean[] bs, boolean[] bs2) { 219 boolean ret = true; 220 for (int i = 0; i < bs.length; i++) 221 ret &= bs[i] == bs2[i]; 222 return ret; 223 } 224 224 } -
applications/editors/josm/plugins/OpeningHoursEditor/src/org/openstreetmap/josm/plugins/ohe/gui/OheDialogPanel.java
r22751 r23192 26 26 public class OheDialogPanel extends JPanel { 27 27 28 private final JTextField keyField;28 private final JTextField keyField; 29 29 30 // The Component for showing the Time as a Text31 private final JTextField valueField;30 // The Component for showing the Time as a Text 31 private final JTextField valueField; 32 32 33 private final JButton twentyfourSevenButton;34 private final JLabel actualPostionLabel;33 private final JButton twentyfourSevenButton; 34 private final JLabel actualPostionLabel; 35 35 36 // The important Panel for showing/editing the Time graphical37 private final OheEditor editorPanel;36 // The important Panel for showing/editing the Time graphical 37 private final OheEditor editorPanel; 38 38 39 private final String oldkey;39 private final String oldkey; 40 40 41 public OheDialogPanel(OhePlugin plugin, String key, String value) {42 oldkey = key;43 keyField = new JTextField(key);41 public OheDialogPanel(OhePlugin plugin, String key, String value) { 42 oldkey = key; 43 keyField = new JTextField(key); 44 44 45 valueField = new JTextField(value);46 valueField.addActionListener(new ActionListener() {47 @Override48 public void actionPerformed(ActionEvent evt) {49 // on every action in the textfield the timeRects are reloaded50 editorPanel.initTimeRects();51 }52 });45 valueField = new JTextField(value); 46 valueField.addActionListener(new ActionListener() { 47 @Override 48 public void actionPerformed(ActionEvent evt) { 49 // on every action in the textfield the timeRects are reloaded 50 editorPanel.initTimeRects(); 51 } 52 }); 53 53 54 twentyfourSevenButton = new JButton(tr("apply {0}", "24/7"));55 twentyfourSevenButton.addActionListener(new ActionListener() {56 @Override57 public void actionPerformed(ActionEvent arg0) {58 valueField.setText("24/7");59 editorPanel.initTimeRects();60 }61 });54 twentyfourSevenButton = new JButton(tr("apply {0}", "24/7")); 55 twentyfourSevenButton.addActionListener(new ActionListener() { 56 @Override 57 public void actionPerformed(ActionEvent arg0) { 58 valueField.setText("24/7"); 59 editorPanel.initTimeRects(); 60 } 61 }); 62 62 63 actualPostionLabel = new JLabel("Mo 00:00");64 JPanel toolsPanel = new JPanel(new GridBagLayout());65 toolsPanel.add(twentyfourSevenButton, GBC.std());66 toolsPanel.add(Box.createGlue(), GBC.std().fill(GBC.HORIZONTAL));67 toolsPanel.add(actualPostionLabel, GBC.eop());63 actualPostionLabel = new JLabel("Mo 00:00"); 64 JPanel toolsPanel = new JPanel(new GridBagLayout()); 65 toolsPanel.add(twentyfourSevenButton, GBC.std()); 66 toolsPanel.add(Box.createGlue(), GBC.std().fill(GBC.HORIZONTAL)); 67 toolsPanel.add(actualPostionLabel, GBC.eop()); 68 68 69 editorPanel = new OheEditor(this);69 editorPanel = new OheEditor(this); 70 70 71 // adding all Components in a Gridbaglayout72 setLayout(new GridBagLayout());73 add(new JLabel(tr("Key")), GBC.std());74 add(Box.createHorizontalStrut(10), GBC.std());75 add(keyField, GBC.eol().fill(GBC.HORIZONTAL));76 add(new JLabel(tr("Value")), GBC.std());77 add(Box.createHorizontalStrut(10), GBC.std());78 add(valueField, GBC.eop().fill(GBC.HORIZONTAL));79 add(toolsPanel, GBC.eol().fill(GBC.HORIZONTAL));80 add(editorPanel, GBC.eol().fill());71 // adding all Components in a Gridbaglayout 72 setLayout(new GridBagLayout()); 73 add(new JLabel(tr("Key")), GBC.std()); 74 add(Box.createHorizontalStrut(10), GBC.std()); 75 add(keyField, GBC.eol().fill(GBC.HORIZONTAL)); 76 add(new JLabel(tr("Value")), GBC.std()); 77 add(Box.createHorizontalStrut(10), GBC.std()); 78 add(valueField, GBC.eop().fill(GBC.HORIZONTAL)); 79 add(toolsPanel, GBC.eol().fill(GBC.HORIZONTAL)); 80 add(editorPanel, GBC.eol().fill()); 81 81 82 valueField.requestFocus();83 setPreferredSize(new Dimension(480, 520));84 }82 valueField.requestFocus(); 83 setPreferredSize(new Dimension(480, 520)); 84 } 85 85 86 public String[] getChangedKeyValuePair() {87 return new String[] { oldkey, keyField.getText(), valueField.getText() };88 }86 public String[] getChangedKeyValuePair() { 87 return new String[] { oldkey, keyField.getText(), valueField.getText() }; 88 } 89 89 90 // returns the compiled Time from the valueField91 public ArrayList<int[]> getTime() throws Exception {92 String value = valueField.getText();93 ArrayList<int[]> time = null;94 if (value.length() > 0) {95 OpeningTimeCompiler compiler = new OpeningTimeCompiler(value);96 try {97 time = OpeningTimeUtils.convert(compiler.startCompile());98 } catch (Throwable t) {99 int tColumns[] = null;100 String info = null;90 // returns the compiled Time from the valueField 91 public ArrayList<int[]> getTime() throws Exception { 92 String value = valueField.getText(); 93 ArrayList<int[]> time = null; 94 if (value.length() > 0) { 95 OpeningTimeCompiler compiler = new OpeningTimeCompiler(value); 96 try { 97 time = OpeningTimeUtils.convert(compiler.startCompile()); 98 } catch (Throwable t) { 99 int tColumns[] = null; 100 String info = null; 101 101 102 if (t instanceof ParseException) {103 ParseException parserExc = (ParseException) t;104 tColumns = new int[] {105 parserExc.currentToken.beginColumn - 1,106 parserExc.currentToken.endColumn + 1 };107 } else if (t instanceof SyntaxException) {108 SyntaxException syntaxError = (SyntaxException) t;109 tColumns = new int[] { syntaxError.getStartColumn(),110 syntaxError.getEndColumn() };111 info = syntaxError.getInfo();112 } else if (t instanceof TokenMgrError) {113 TokenMgrError tokenMgrError = (TokenMgrError) t;114 tColumns = new int[] { tokenMgrError.errorColumn - 1,115 tokenMgrError.errorColumn + 1 };116 } else {117 t.printStackTrace();118 }102 if (t instanceof ParseException) { 103 ParseException parserExc = (ParseException) t; 104 tColumns = new int[] { 105 parserExc.currentToken.beginColumn - 1, 106 parserExc.currentToken.endColumn + 1 }; 107 } else if (t instanceof SyntaxException) { 108 SyntaxException syntaxError = (SyntaxException) t; 109 tColumns = new int[] { syntaxError.getStartColumn(), 110 syntaxError.getEndColumn() }; 111 info = syntaxError.getInfo(); 112 } else if (t instanceof TokenMgrError) { 113 TokenMgrError tokenMgrError = (TokenMgrError) t; 114 tColumns = new int[] { tokenMgrError.errorColumn - 1, 115 tokenMgrError.errorColumn + 1 }; 116 } else { 117 t.printStackTrace(); 118 } 119 119 120 // shows a Information Dialog, where the Error occurred121 if (tColumns != null) {122 int first = Math.max(0, tColumns[0]);123 int last = Math.min(value.length(), tColumns[1]);124 String begin = value.substring(0, first);125 String middle = value.substring(first, last);126 String end = value.substring(last);127 String message = "<html>"128 + tr("There is something wrong in the value near:")129 + "<br>" + begin130 + "<span style='background-color:red;'>" + middle131 + "</span>" + end;132 if (info != null)133 message += "<br>" + tr("Info: {0}", tr(info));134 message += "<br>"135 + tr("Correct the value manually and than press Enter.");136 message += "</html>";137 JOptionPane.showMessageDialog(this, message,138 tr("Error in timeformat"),139 JOptionPane.INFORMATION_MESSAGE);140 }120 // shows a Information Dialog, where the Error occurred 121 if (tColumns != null) { 122 int first = Math.max(0, tColumns[0]); 123 int last = Math.min(value.length(), tColumns[1]); 124 String begin = value.substring(0, first); 125 String middle = value.substring(first, last); 126 String end = value.substring(last); 127 String message = "<html>" 128 + tr("There is something wrong in the value near:") 129 + "<br>" + begin 130 + "<span style='background-color:red;'>" + middle 131 + "</span>" + end; 132 if (info != null) 133 message += "<br>" + tr("Info: {0}", tr(info)); 134 message += "<br>" 135 + tr("Correct the value manually and than press Enter."); 136 message += "</html>"; 137 JOptionPane.showMessageDialog(this, message, 138 tr("Error in timeformat"), 139 JOptionPane.INFORMATION_MESSAGE); 140 } 141 141 142 throw new Exception("Error in the TimeValue");143 }144 }142 throw new Exception("Error in the TimeValue"); 143 } 144 } 145 145 146 return time;147 }146 return time; 147 } 148 148 149 // updates the valueField with the given timeRects150 public void updateValueField(ArrayList<TimeRect> timeRects) {151 if (valueField != null && timeRects != null)152 valueField.setText(OpeningTimeUtils.makeStringFromRects(timeRects));153 }149 // updates the valueField with the given timeRects 150 public void updateValueField(ArrayList<TimeRect> timeRects) { 151 if (valueField != null && timeRects != null) 152 valueField.setText(OpeningTimeUtils.makeStringFromRects(timeRects)); 153 } 154 154 155 public void setMousePositionText(String positionText) {156 actualPostionLabel.setText(positionText);157 }155 public void setMousePositionText(String positionText) { 156 actualPostionLabel.setText(positionText); 157 } 158 158 } -
applications/editors/josm/plugins/OpeningHoursEditor/src/org/openstreetmap/josm/plugins/ohe/gui/OheEditor.java
r22751 r23192 20 20 21 21 public class OheEditor extends JPanel implements MouseListener, 22 MouseMotionListener {23 final OheDialogPanel dialog;24 25 final private JScrollPane scrollPane;26 final JPanel contentPanel;27 28 ArrayList<TimeRect> timeRects;29 30 final private int dayAxisHeight = 20;31 final private int timeAxisWidth = 45;32 33 public OheEditor(OheDialogPanel oheDialogPanel) {34 dialog = oheDialogPanel;35 36 // the MainPanel for showing the TimeRects37 contentPanel = new JPanel() {38 @Override39 public void setSize(Dimension d) {40 super.setSize(d);41 repositionTimeRects();42 }43 44 @Override45 public void paintComponent(Graphics g) {46 if (OheEditor.this.isEnabled()) {47 g.setColor(Color.WHITE);48 g.fillRect(0, 0, getWidth(), getHeight());49 50 // horizontal Lines51 for (int i = 1; i < 24; ++i) {52 if (i % 3 == 0)53 g.setColor(Color.BLACK);54 else55 g.setColor(Color.LIGHT_GRAY);56 57 g.drawLine(0, getMinutePosition(i * 60), getWidth(),58 getMinutePosition(i * 60));59 }60 61 // vertical Lines62 g.setColor(Color.BLACK);63 for (int i = 1; i < 7; ++i)64 g.drawLine(getDayPosition(i), 0, getDayPosition(i),65 getHeight());66 67 // if a new Rect is dragged draw it68 if (day0 >= 0) {69 Graphics2D g2D = (Graphics2D) g;70 71 int day2 = Math.min(day0, day1);72 int day3 = Math.max(day0, day1);73 int minute2 = Math.min(minute0, minute1);74 int minute3 = Math.max(minute0, minute1);75 Rectangle bounds = getPanelBoundsForTimeinterval(day2,76 day3 + 1, minute2, minute3);77 78 TimeRect.drawTimeRect(g2D, bounds, minute2 == minute3, false);79 }80 } else {81 g.setColor(Color.LIGHT_GRAY);82 g.fillRect(0, 0, getWidth(), getHeight());83 }84 }85 };86 contentPanel.addMouseListener(this);87 contentPanel.addMouseMotionListener(this);88 contentPanel.setLayout(null);89 contentPanel.setPreferredSize(new Dimension(180, 384));90 91 initTimeRects();92 93 scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,94 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);95 scrollPane.setViewportView(contentPanel);96 97 // the upper Panel for showing Weekdays98 scrollPane.setColumnHeaderView(new JPanel() {99 @Override100 public Dimension getPreferredSize() {101 return new Dimension(contentPanel.getWidth(), dayAxisHeight);102 }103 104 @Override105 public void paintComponent(Graphics g) {106 g.setColor(Color.WHITE);107 g.fillRect(0, 0, getWidth(), getHeight());108 109 g.setColor(Color.BLACK);110 for (int i = 0; i < 7; ++i) {111 if (i > 0)112 g.drawLine(getDayPosition(i) + 1, 0,113 getDayPosition(i) + 1, getHeight());114 115 String text = OpeningTimeCompiler.WEEKDAYS[i];116 g.drawString(text, (int) (getDayPosition(i + 0.5) - g117 .getFontMetrics().stringWidth(text) * 0.5),118 (int) (dayAxisHeight * 0.5 + g.getFontMetrics()119 .getHeight() * 0.35));120 }121 }122 });123 124 // the left Panel for showing the hours125 scrollPane.setRowHeaderView(new JPanel() {126 @Override127 public Dimension getPreferredSize() {128 return new Dimension(timeAxisWidth, contentPanel.getHeight());129 }130 131 @Override132 public void paintComponent(Graphics g) {133 g.setColor(Color.WHITE);134 g.fillRect(0, 0, getWidth(), getHeight());135 136 for (int i = 1; i < 24; ++i) {137 if (i % 3 == 0) {138 g.setColor(Color.BLACK);139 String text = ((i < 10) ? "0" + i : i) + ":00";140 g141 .drawString(text, timeAxisWidth - 10142 - g.getFontMetrics().stringWidth(text),143 getMinutePosition(i * 60)144 + (int) (g.getFontMetrics()145 .getHeight() * 0.35));146 } else147 g.setColor(Color.LIGHT_GRAY);148 149 g.drawLine(getWidth() - 4, getMinutePosition(i * 60) + 1,150 getWidth(), getMinutePosition(i * 60) + 1);151 }152 }153 });154 155 setLayout(new BorderLayout());156 add(scrollPane, BorderLayout.CENTER);157 }158 159 // update all the TimeRects with new Data160 public void initTimeRects() {161 contentPanel.removeAll();162 163 ArrayList<int[]> time;164 try {165 time = dialog.getTime();166 } catch (Exception exc) {167 setEnabled(false);168 return;169 }170 171 setEnabled(true);172 timeRects = new ArrayList<TimeRect>();173 if (time != null) {174 for (int[] timeRectValues : time) {175 int day0 = timeRectValues[0];176 int day1 = timeRectValues[1];177 int minute0 = timeRectValues[2];178 int minute1 = timeRectValues[3];179 TimeRect timeRect = new TimeRect(OheEditor.this, day0, day1,180 minute0, minute1);181 timeRects.add(timeRect);182 contentPanel.add(timeRect);183 }184 }185 186 repositionTimeRects();187 repaint();188 }189 190 protected void repositionTimeRects() {191 if (timeRects != null)192 for (TimeRect timeRect : timeRects)193 timeRect.reposition();194 }195 196 // returns the physical Borders of the TimeRect on the mainPanel197 public Rectangle getPanelBoundsForTimeinterval(int dayStart, int dayEnd,198 int minutesStart, int minutesEnd) {199 int x = getDayPosition(dayStart);200 int y = getMinutePosition(minutesStart);201 int width = getDayPosition(dayEnd) - getDayPosition(dayStart);202 int height = getMinutePosition(minutesEnd)203 - getMinutePosition(minutesStart);204 205 // work around openjdk bug206 if (Main.isOpenjdk) {207 x++;208 y++;209 }210 211 if (minutesStart == minutesEnd)212 return new Rectangle(x, y - 2 - TimeRect.verticalNonDrawedPixels,213 width, height + 5 + 2 * TimeRect.verticalNonDrawedPixels);214 215 return new Rectangle(x, y, width, height + 1);216 }217 218 public double getDayWidth() {219 return (contentPanel.getWidth() - 1) / 7.0;220 }221 222 public int getDayPosition(double d) {223 return (int) (d * getDayWidth());224 }225 226 public double getMinuteHeight() {227 return (contentPanel.getHeight() - 1) / (24.0 * 60);228 }229 230 public int getMinutePosition(int minute) {231 return (int) (minute * getMinuteHeight());232 }233 234 // removes the given timerect from the panel and from the arraylist235 public void removeTimeRect(TimeRect timeRectToRemove) {236 timeRects.remove(timeRectToRemove);237 contentPanel.remove(timeRectToRemove);238 dialog.updateValueField(timeRects);239 repaint();240 }241 242 // drawing a new Rect243 private int day0 = -1;244 private int minute0;245 private int day1;246 private int minute1;247 private int xDragStart;248 private int yDragStart;249 250 @Override251 public void mouseClicked(MouseEvent evt) {252 }253 254 @Override255 public void mouseEntered(MouseEvent evt) {256 }257 258 @Override259 public void mouseExited(MouseEvent evt) {260 }261 262 @Override263 public void mousePressed(MouseEvent evt) {264 day0 = (int) Math.floor(evt.getX() / getDayWidth());265 minute0 = (int) Math.floor(evt.getY()266 / (getMinuteHeight() * TimeRect.minuteResterize))267 * TimeRect.minuteResterize;268 day1 = day0;269 minute1 = minute0;270 xDragStart = evt.getX();271 yDragStart = evt.getY();272 }273 274 @Override275 public void mouseReleased(MouseEvent evt) {276 // mouse must be moved 5px before creating a rect277 if (xDragStart == -1278 || Math.abs(evt.getX() - xDragStart)279 + Math.abs(evt.getY() - yDragStart) > 5) {280 int day2 = Math.min(day0, day1);281 int day3 = Math.max(day0, day1);282 int minute2 = Math.min(minute0, minute1);283 int minute3 = Math.max(minute0, minute1);284 285 TimeRect timeRect = new TimeRect(OheEditor.this, day2, day3,286 minute2, minute3);287 timeRects.add(timeRect);288 contentPanel.add(timeRect);289 timeRect.reposition();290 dialog.updateValueField(timeRects);291 292 day0 = -1;293 repaint();294 }295 }296 297 @Override298 public void mouseDragged(MouseEvent evt) {299 // mouse must be moved 5px before drawing a rect300 if (xDragStart == -1301 || Math.abs(evt.getX() - xDragStart)302 + Math.abs(evt.getY() - yDragStart) > 5) {303 xDragStart = -1;304 day1 = (int) Math.floor(evt.getX() / getDayWidth());305 minute1 = (int) Math.floor(evt.getY()306 / (getMinuteHeight() * TimeRect.minuteResterize))307 * TimeRect.minuteResterize;308 repaint();309 }310 }311 312 @Override313 public void mouseMoved(MouseEvent evt) {314 mousePositionChanged(evt.getX(), evt.getY());315 }316 317 public void mousePositionChanged(int x, int y) {318 int actualDay = (int) Math.floor(x / getDayWidth());319 int minutes = (int) Math.floor(y320 / (getMinuteHeight() * TimeRect.minuteResterize))321 * TimeRect.minuteResterize;322 actualDay = Math.max(0, Math.min(6, actualDay));323 minutes = Math.max(0, Math.min(24 * 60, minutes));324 dialog.setMousePositionText(OpeningTimeCompiler.WEEKDAYS[actualDay]325 + " " + OpeningTimeUtils.timeString(minutes));326 }22 MouseMotionListener { 23 final OheDialogPanel dialog; 24 25 final private JScrollPane scrollPane; 26 final JPanel contentPanel; 27 28 ArrayList<TimeRect> timeRects; 29 30 final private int dayAxisHeight = 20; 31 final private int timeAxisWidth = 45; 32 33 public OheEditor(OheDialogPanel oheDialogPanel) { 34 dialog = oheDialogPanel; 35 36 // the MainPanel for showing the TimeRects 37 contentPanel = new JPanel() { 38 @Override 39 public void setSize(Dimension d) { 40 super.setSize(d); 41 repositionTimeRects(); 42 } 43 44 @Override 45 public void paintComponent(Graphics g) { 46 if (OheEditor.this.isEnabled()) { 47 g.setColor(Color.WHITE); 48 g.fillRect(0, 0, getWidth(), getHeight()); 49 50 // horizontal Lines 51 for (int i = 1; i < 24; ++i) { 52 if (i % 3 == 0) 53 g.setColor(Color.BLACK); 54 else 55 g.setColor(Color.LIGHT_GRAY); 56 57 g.drawLine(0, getMinutePosition(i * 60), getWidth(), 58 getMinutePosition(i * 60)); 59 } 60 61 // vertical Lines 62 g.setColor(Color.BLACK); 63 for (int i = 1; i < 7; ++i) 64 g.drawLine(getDayPosition(i), 0, getDayPosition(i), 65 getHeight()); 66 67 // if a new Rect is dragged draw it 68 if (day0 >= 0) { 69 Graphics2D g2D = (Graphics2D) g; 70 71 int day2 = Math.min(day0, day1); 72 int day3 = Math.max(day0, day1); 73 int minute2 = Math.min(minute0, minute1); 74 int minute3 = Math.max(minute0, minute1); 75 Rectangle bounds = getPanelBoundsForTimeinterval(day2, 76 day3 + 1, minute2, minute3); 77 78 TimeRect.drawTimeRect(g2D, bounds, minute2 == minute3, false); 79 } 80 } else { 81 g.setColor(Color.LIGHT_GRAY); 82 g.fillRect(0, 0, getWidth(), getHeight()); 83 } 84 } 85 }; 86 contentPanel.addMouseListener(this); 87 contentPanel.addMouseMotionListener(this); 88 contentPanel.setLayout(null); 89 contentPanel.setPreferredSize(new Dimension(180, 384)); 90 91 initTimeRects(); 92 93 scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 94 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 95 scrollPane.setViewportView(contentPanel); 96 97 // the upper Panel for showing Weekdays 98 scrollPane.setColumnHeaderView(new JPanel() { 99 @Override 100 public Dimension getPreferredSize() { 101 return new Dimension(contentPanel.getWidth(), dayAxisHeight); 102 } 103 104 @Override 105 public void paintComponent(Graphics g) { 106 g.setColor(Color.WHITE); 107 g.fillRect(0, 0, getWidth(), getHeight()); 108 109 g.setColor(Color.BLACK); 110 for (int i = 0; i < 7; ++i) { 111 if (i > 0) 112 g.drawLine(getDayPosition(i) + 1, 0, 113 getDayPosition(i) + 1, getHeight()); 114 115 String text = OpeningTimeCompiler.WEEKDAYS[i]; 116 g.drawString(text, (int) (getDayPosition(i + 0.5) - g 117 .getFontMetrics().stringWidth(text) * 0.5), 118 (int) (dayAxisHeight * 0.5 + g.getFontMetrics() 119 .getHeight() * 0.35)); 120 } 121 } 122 }); 123 124 // the left Panel for showing the hours 125 scrollPane.setRowHeaderView(new JPanel() { 126 @Override 127 public Dimension getPreferredSize() { 128 return new Dimension(timeAxisWidth, contentPanel.getHeight()); 129 } 130 131 @Override 132 public void paintComponent(Graphics g) { 133 g.setColor(Color.WHITE); 134 g.fillRect(0, 0, getWidth(), getHeight()); 135 136 for (int i = 1; i < 24; ++i) { 137 if (i % 3 == 0) { 138 g.setColor(Color.BLACK); 139 String text = ((i < 10) ? "0" + i : i) + ":00"; 140 g 141 .drawString(text, timeAxisWidth - 10 142 - g.getFontMetrics().stringWidth(text), 143 getMinutePosition(i * 60) 144 + (int) (g.getFontMetrics() 145 .getHeight() * 0.35)); 146 } else 147 g.setColor(Color.LIGHT_GRAY); 148 149 g.drawLine(getWidth() - 4, getMinutePosition(i * 60) + 1, 150 getWidth(), getMinutePosition(i * 60) + 1); 151 } 152 } 153 }); 154 155 setLayout(new BorderLayout()); 156 add(scrollPane, BorderLayout.CENTER); 157 } 158 159 // update all the TimeRects with new Data 160 public void initTimeRects() { 161 contentPanel.removeAll(); 162 163 ArrayList<int[]> time; 164 try { 165 time = dialog.getTime(); 166 } catch (Exception exc) { 167 setEnabled(false); 168 return; 169 } 170 171 setEnabled(true); 172 timeRects = new ArrayList<TimeRect>(); 173 if (time != null) { 174 for (int[] timeRectValues : time) { 175 int day0 = timeRectValues[0]; 176 int day1 = timeRectValues[1]; 177 int minute0 = timeRectValues[2]; 178 int minute1 = timeRectValues[3]; 179 TimeRect timeRect = new TimeRect(OheEditor.this, day0, day1, 180 minute0, minute1); 181 timeRects.add(timeRect); 182 contentPanel.add(timeRect); 183 } 184 } 185 186 repositionTimeRects(); 187 repaint(); 188 } 189 190 protected void repositionTimeRects() { 191 if (timeRects != null) 192 for (TimeRect timeRect : timeRects) 193 timeRect.reposition(); 194 } 195 196 // returns the physical Borders of the TimeRect on the mainPanel 197 public Rectangle getPanelBoundsForTimeinterval(int dayStart, int dayEnd, 198 int minutesStart, int minutesEnd) { 199 int x = getDayPosition(dayStart); 200 int y = getMinutePosition(minutesStart); 201 int width = getDayPosition(dayEnd) - getDayPosition(dayStart); 202 int height = getMinutePosition(minutesEnd) 203 - getMinutePosition(minutesStart); 204 205 // work around openjdk bug 206 if (Main.isOpenjdk) { 207 x++; 208 y++; 209 } 210 211 if (minutesStart == minutesEnd) 212 return new Rectangle(x, y - 2 - TimeRect.verticalNonDrawedPixels, 213 width, height + 5 + 2 * TimeRect.verticalNonDrawedPixels); 214 215 return new Rectangle(x, y, width, height + 1); 216 } 217 218 public double getDayWidth() { 219 return (contentPanel.getWidth() - 1) / 7.0; 220 } 221 222 public int getDayPosition(double d) { 223 return (int) (d * getDayWidth()); 224 } 225 226 public double getMinuteHeight() { 227 return (contentPanel.getHeight() - 1) / (24.0 * 60); 228 } 229 230 public int getMinutePosition(int minute) { 231 return (int) (minute * getMinuteHeight()); 232 } 233 234 // removes the given timerect from the panel and from the arraylist 235 public void removeTimeRect(TimeRect timeRectToRemove) { 236 timeRects.remove(timeRectToRemove); 237 contentPanel.remove(timeRectToRemove); 238 dialog.updateValueField(timeRects); 239 repaint(); 240 } 241 242 // drawing a new Rect 243 private int day0 = -1; 244 private int minute0; 245 private int day1; 246 private int minute1; 247 private int xDragStart; 248 private int yDragStart; 249 250 @Override 251 public void mouseClicked(MouseEvent evt) { 252 } 253 254 @Override 255 public void mouseEntered(MouseEvent evt) { 256 } 257 258 @Override 259 public void mouseExited(MouseEvent evt) { 260 } 261 262 @Override 263 public void mousePressed(MouseEvent evt) { 264 day0 = (int) Math.floor(evt.getX() / getDayWidth()); 265 minute0 = (int) Math.floor(evt.getY() 266 / (getMinuteHeight() * TimeRect.minuteResterize)) 267 * TimeRect.minuteResterize; 268 day1 = day0; 269 minute1 = minute0; 270 xDragStart = evt.getX(); 271 yDragStart = evt.getY(); 272 } 273 274 @Override 275 public void mouseReleased(MouseEvent evt) { 276 // mouse must be moved 5px before creating a rect 277 if (xDragStart == -1 278 || Math.abs(evt.getX() - xDragStart) 279 + Math.abs(evt.getY() - yDragStart) > 5) { 280 int day2 = Math.min(day0, day1); 281 int day3 = Math.max(day0, day1); 282 int minute2 = Math.min(minute0, minute1); 283 int minute3 = Math.max(minute0, minute1); 284 285 TimeRect timeRect = new TimeRect(OheEditor.this, day2, day3, 286 minute2, minute3); 287 timeRects.add(timeRect); 288 contentPanel.add(timeRect); 289 timeRect.reposition(); 290 dialog.updateValueField(timeRects); 291 292 day0 = -1; 293 repaint(); 294 } 295 } 296 297 @Override 298 public void mouseDragged(MouseEvent evt) { 299 // mouse must be moved 5px before drawing a rect 300 if (xDragStart == -1 301 || Math.abs(evt.getX() - xDragStart) 302 + Math.abs(evt.getY() - yDragStart) > 5) { 303 xDragStart = -1; 304 day1 = (int) Math.floor(evt.getX() / getDayWidth()); 305 minute1 = (int) Math.floor(evt.getY() 306 / (getMinuteHeight() * TimeRect.minuteResterize)) 307 * TimeRect.minuteResterize; 308 repaint(); 309 } 310 } 311 312 @Override 313 public void mouseMoved(MouseEvent evt) { 314 mousePositionChanged(evt.getX(), evt.getY()); 315 } 316 317 public void mousePositionChanged(int x, int y) { 318 int actualDay = (int) Math.floor(x / getDayWidth()); 319 int minutes = (int) Math.floor(y 320 / (getMinuteHeight() * TimeRect.minuteResterize)) 321 * TimeRect.minuteResterize; 322 actualDay = Math.max(0, Math.min(6, actualDay)); 323 minutes = Math.max(0, Math.min(24 * 60, minutes)); 324 dialog.setMousePositionText(OpeningTimeCompiler.WEEKDAYS[actualDay] 325 + " " + OpeningTimeUtils.timeString(minutes)); 326 } 327 327 } -
applications/editors/josm/plugins/OpeningHoursEditor/src/org/openstreetmap/josm/plugins/ohe/gui/TimeRect.java
r22751 r23192 20 20 21 21 public class TimeRect extends JPanel implements MouseListener, 22 MouseMotionListener {23 public static final int[] transformCursorTypes = new int[] {24 Cursor.MOVE_CURSOR, Cursor.N_RESIZE_CURSOR,25 Cursor.NE_RESIZE_CURSOR, Cursor.E_RESIZE_CURSOR,26 Cursor.SE_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR,27 Cursor.SW_RESIZE_CURSOR, Cursor.W_RESIZE_CURSOR,28 Cursor.NW_RESIZE_CURSOR };29 30 public static final int minuteResterize = 15;31 public static final int verticalNonDrawedPixels = 5;32 33 public static final boolean[][] transformDirections = new boolean[][] {34 { true, true, true, true }, // Drag35 { true, false, false, false }, // N36 { true, true, false, false }, // NE37 { false, true, false, false }, // E38 { false, true, true, false }, // SE39 { false, false, true, false }, // S40 { false, false, true, true }, // SW41 { false, false, false, true }, // W42 { true, false, false, true }, // NW43 };44 45 public static final int roundCornerSize = 8;46 private final int clickAreaSize = 16;47 48 private OheEditor editor;49 50 private int dayStart;51 private int dayEnd;52 private int minuteStart;53 private int minuteEnd;54 55 public TimeRect(OheEditor editor, int dayStart, int dayEnd,56 int minutesStart, int minutesEnd) {57 this.editor = editor;58 59 this.dayStart = dayStart;60 this.dayEnd = dayEnd;61 this.minuteStart = minutesStart;62 this.minuteEnd = minutesEnd;63 64 transformType = -1;65 66 setOpaque(true);67 68 addMouseListener(this);69 addMouseMotionListener(this);70 }71 72 public int getDayStart() {73 return dayStart;74 }75 76 public int getDayEnd() {77 return dayEnd;78 }79 80 public int getMinuteStart() {81 return minuteStart;82 }83 84 public int getMinuteEnd() {85 return minuteEnd;86 }87 88 public void reposition() {89 setBounds(editor.getPanelBoundsForTimeinterval(dayStart, dayEnd + 1,90 minuteStart, minuteEnd));91 editor.contentPanel.repaint();92 }93 94 private boolean isZeroMinuteInterval() {95 return minuteStart == minuteEnd;96 }97 98 private boolean isOpenEndInterval() {99 return minuteEnd == 24 * 60 + 1;100 }101 102 private void updateTimeInterval(int newDayStart, int newDayEnd,103 int newMinuteStart, int newMinuteEnd) {104 dayStart = newDayStart;105 dayEnd = newDayEnd;106 minuteStart = newMinuteStart;107 minuteEnd = newMinuteEnd;108 109 editor.dialog.updateValueField(editor.timeRects);110 reposition();111 }112 113 @Override114 public void paintComponent(Graphics g) {115 drawTimeRect((Graphics2D) g, new Rectangle(0, 0, getWidth(),116 getHeight()), isZeroMinuteInterval(), isOpenEndInterval());117 }118 119 public static void drawTimeRect(Graphics2D g2D, Rectangle bounds,120 boolean isZeroMinuteInterval, boolean isOpenEndInterval) {121 122 Color innerColor = new Color(135, 135, 234);123 if (isOpenEndInterval)124 innerColor = new Color(234, 135, 135);125 126 int tmpRoundCornerSize = TimeRect.roundCornerSize;127 int verticalNonFilledBorder = 1;128 if (isZeroMinuteInterval) {129 innerColor = new Color(135, 234, 135);130 tmpRoundCornerSize = 0;131 verticalNonFilledBorder = verticalNonDrawedPixels;132 }133 134 g2D.setColor(innerColor);135 g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,136 .6f));137 g2D.fillRoundRect(bounds.x + 1, bounds.y + verticalNonFilledBorder,138 bounds.width - 2, bounds.height - 1 - 2139 * verticalNonFilledBorder, tmpRoundCornerSize,140 tmpRoundCornerSize);141 142 g2D.setColor(new Color(255, 0, 0));143 g2D.setComposite(AlphaComposite144 .getInstance(AlphaComposite.SRC_OVER, 1f));145 g2D.drawRoundRect(bounds.x + 1, bounds.y + verticalNonFilledBorder,146 bounds.width - 2, bounds.height - 1 - 2147 * verticalNonFilledBorder, tmpRoundCornerSize,148 tmpRoundCornerSize);149 150 }151 152 private int actualDayDrag;153 private int actualMinuteDrag;154 private int dragX;155 private int dragY;156 private int transformType;157 158 // Calculate where the Component was clicked and returns the159 // transformtype160 private int getTransformType(MouseEvent evt) {161 int tmpClickAreaWidth = Math.min(clickAreaSize, getWidth() / 3);162 int tmpClickAreaHeight = Math.min(clickAreaSize, getHeight() / 3);163 164 boolean isInNorthernTransformClickArea = evt.getY() < tmpClickAreaHeight;165 boolean isInEasternTransformClickArea = evt.getX() > getWidth()166 - tmpClickAreaWidth;167 boolean isInSouthernTransformClickArea = evt.getY() > getHeight()168 - tmpClickAreaHeight;169 boolean isInWesternTransformClickArea = evt.getX() < tmpClickAreaWidth;170 171 if (isZeroMinuteInterval()) {172 isInNorthernTransformClickArea = false;173 isInSouthernTransformClickArea = false;174 }175 176 int tType = 0;177 for (int i = 1; i < transformDirections.length && tType == 0; i++) {178 if (isInNorthernTransformClickArea == transformDirections[i][0]179 && isInEasternTransformClickArea == transformDirections[i][1]180 && isInSouthernTransformClickArea == transformDirections[i][2]181 && isInWesternTransformClickArea == transformDirections[i][3])182 tType = i;183 }184 185 return tType;186 }187 188 public void showMenu(MouseEvent evt) {189 JPopupMenu menu = new JPopupMenu();190 final JCheckBoxMenuItem cbMenuItem = new JCheckBoxMenuItem(191 tr("open end"), isOpenEndInterval());192 menu.add(cbMenuItem);193 cbMenuItem.addActionListener(new ActionListener() {194 @Override195 public void actionPerformed(ActionEvent e) {196 if (cbMenuItem.isSelected())197 updateTimeInterval(dayStart, dayEnd, minuteStart,198 24 * 60 + 1);199 else200 updateTimeInterval(dayStart, dayEnd, minuteStart, 24 * 60);201 }202 });203 menu.show(this, evt.getX(), evt.getY());204 }205 206 @Override207 public void mouseClicked(MouseEvent evt) {208 }209 210 @Override211 public void mouseEntered(MouseEvent evt) {212 }213 214 @Override215 public void mouseExited(MouseEvent evt) {216 if (transformType < 0)217 setCursor(new Cursor(Cursor.DEFAULT_CURSOR));218 }219 220 @Override221 public void mousePressed(MouseEvent evt) {222 if (evt.isPopupTrigger()) {223 showMenu(evt);224 } else {225 actualDayDrag = 0;226 actualMinuteDrag = 0;227 dragX = evt.getXOnScreen();228 dragY = evt.getYOnScreen();229 transformType = getTransformType(evt);230 }231 }232 233 @Override234 public void mouseReleased(MouseEvent evt) {235 transformType = -1;236 }237 238 @Override239 public void mouseDragged(MouseEvent evt) {240 if (transformType >= 0) {241 int xDiff = evt.getXOnScreen() - dragX;242 int yDiff = evt.getYOnScreen() - dragY;243 244 xDiff = (int) Math.round(xDiff / editor.getDayWidth())245 - actualDayDrag;246 yDiff = (int) Math.round(yDiff247 / (editor.getMinuteHeight() * minuteResterize))248 * minuteResterize - actualMinuteDrag;249 250 if (xDiff != 0) {251 int newDayStart = dayStart;252 int newDayEnd = dayEnd;253 254 if (transformDirections[transformType][3])255 newDayStart += xDiff;256 if (transformDirections[transformType][1])257 newDayEnd += xDiff;258 259 if (newDayStart > newDayEnd) {260 editor.removeTimeRect(this);261 transformType = -1;262 setCursor(new Cursor(Cursor.DEFAULT_CURSOR));263 } else if (newDayStart >= 0 && newDayEnd <= 6) {264 actualDayDrag += xDiff;265 updateTimeInterval(newDayStart, newDayEnd, minuteStart,266 minuteEnd);267 }268 }269 if (yDiff != 0 && transformType >= 0) {270 int newMinutesStart = minuteStart;271 int newMinutesEnd = minuteEnd;272 273 if (transformDirections[transformType][0])274 newMinutesStart = newMinutesStart + yDiff;275 if (transformDirections[transformType][2]276 && !isOpenEndInterval())277 newMinutesEnd = newMinutesEnd + yDiff;278 279 if (newMinutesStart >= 0280 && (newMinutesEnd <= 24 * 60 || isOpenEndInterval())) {281 actualMinuteDrag += yDiff;282 updateTimeInterval(dayStart, dayEnd, newMinutesStart,283 newMinutesEnd);284 }285 }286 }287 editor.mousePositionChanged(evt.getX() + getX(), evt.getY() + getY());288 }289 290 @Override291 public void mouseMoved(MouseEvent evt) {292 if (transformType < 0)293 setCursor(new Cursor(transformCursorTypes[getTransformType(evt)]));294 editor.mousePositionChanged(evt.getX() + getX(), evt.getY() + getY());295 }22 MouseMotionListener { 23 public static final int[] transformCursorTypes = new int[] { 24 Cursor.MOVE_CURSOR, Cursor.N_RESIZE_CURSOR, 25 Cursor.NE_RESIZE_CURSOR, Cursor.E_RESIZE_CURSOR, 26 Cursor.SE_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR, 27 Cursor.SW_RESIZE_CURSOR, Cursor.W_RESIZE_CURSOR, 28 Cursor.NW_RESIZE_CURSOR }; 29 30 public static final int minuteResterize = 15; 31 public static final int verticalNonDrawedPixels = 5; 32 33 public static final boolean[][] transformDirections = new boolean[][] { 34 { true, true, true, true }, // Drag 35 { true, false, false, false }, // N 36 { true, true, false, false }, // NE 37 { false, true, false, false }, // E 38 { false, true, true, false }, // SE 39 { false, false, true, false }, // S 40 { false, false, true, true }, // SW 41 { false, false, false, true }, // W 42 { true, false, false, true }, // NW 43 }; 44 45 public static final int roundCornerSize = 8; 46 private final int clickAreaSize = 16; 47 48 private OheEditor editor; 49 50 private int dayStart; 51 private int dayEnd; 52 private int minuteStart; 53 private int minuteEnd; 54 55 public TimeRect(OheEditor editor, int dayStart, int dayEnd, 56 int minutesStart, int minutesEnd) { 57 this.editor = editor; 58 59 this.dayStart = dayStart; 60 this.dayEnd = dayEnd; 61 this.minuteStart = minutesStart; 62 this.minuteEnd = minutesEnd; 63 64 transformType = -1; 65 66 setOpaque(true); 67 68 addMouseListener(this); 69 addMouseMotionListener(this); 70 } 71 72 public int getDayStart() { 73 return dayStart; 74 } 75 76 public int getDayEnd() { 77 return dayEnd; 78 } 79 80 public int getMinuteStart() { 81 return minuteStart; 82 } 83 84 public int getMinuteEnd() { 85 return minuteEnd; 86 } 87 88 public void reposition() { 89 setBounds(editor.getPanelBoundsForTimeinterval(dayStart, dayEnd + 1, 90 minuteStart, minuteEnd)); 91 editor.contentPanel.repaint(); 92 } 93 94 private boolean isZeroMinuteInterval() { 95 return minuteStart == minuteEnd; 96 } 97 98 private boolean isOpenEndInterval() { 99 return minuteEnd == 24 * 60 + 1; 100 } 101 102 private void updateTimeInterval(int newDayStart, int newDayEnd, 103 int newMinuteStart, int newMinuteEnd) { 104 dayStart = newDayStart; 105 dayEnd = newDayEnd; 106 minuteStart = newMinuteStart; 107 minuteEnd = newMinuteEnd; 108 109 editor.dialog.updateValueField(editor.timeRects); 110 reposition(); 111 } 112 113 @Override 114 public void paintComponent(Graphics g) { 115 drawTimeRect((Graphics2D) g, new Rectangle(0, 0, getWidth(), 116 getHeight()), isZeroMinuteInterval(), isOpenEndInterval()); 117 } 118 119 public static void drawTimeRect(Graphics2D g2D, Rectangle bounds, 120 boolean isZeroMinuteInterval, boolean isOpenEndInterval) { 121 122 Color innerColor = new Color(135, 135, 234); 123 if (isOpenEndInterval) 124 innerColor = new Color(234, 135, 135); 125 126 int tmpRoundCornerSize = TimeRect.roundCornerSize; 127 int verticalNonFilledBorder = 1; 128 if (isZeroMinuteInterval) { 129 innerColor = new Color(135, 234, 135); 130 tmpRoundCornerSize = 0; 131 verticalNonFilledBorder = verticalNonDrawedPixels; 132 } 133 134 g2D.setColor(innerColor); 135 g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 136 .6f)); 137 g2D.fillRoundRect(bounds.x + 1, bounds.y + verticalNonFilledBorder, 138 bounds.width - 2, bounds.height - 1 - 2 139 * verticalNonFilledBorder, tmpRoundCornerSize, 140 tmpRoundCornerSize); 141 142 g2D.setColor(new Color(255, 0, 0)); 143 g2D.setComposite(AlphaComposite 144 .getInstance(AlphaComposite.SRC_OVER, 1f)); 145 g2D.drawRoundRect(bounds.x + 1, bounds.y + verticalNonFilledBorder, 146 bounds.width - 2, bounds.height - 1 - 2 147 * verticalNonFilledBorder, tmpRoundCornerSize, 148 tmpRoundCornerSize); 149 150 } 151 152 private int actualDayDrag; 153 private int actualMinuteDrag; 154 private int dragX; 155 private int dragY; 156 private int transformType; 157 158 // Calculate where the Component was clicked and returns the 159 // transformtype 160 private int getTransformType(MouseEvent evt) { 161 int tmpClickAreaWidth = Math.min(clickAreaSize, getWidth() / 3); 162 int tmpClickAreaHeight = Math.min(clickAreaSize, getHeight() / 3); 163 164 boolean isInNorthernTransformClickArea = evt.getY() < tmpClickAreaHeight; 165 boolean isInEasternTransformClickArea = evt.getX() > getWidth() 166 - tmpClickAreaWidth; 167 boolean isInSouthernTransformClickArea = evt.getY() > getHeight() 168 - tmpClickAreaHeight; 169 boolean isInWesternTransformClickArea = evt.getX() < tmpClickAreaWidth; 170 171 if (isZeroMinuteInterval()) { 172 isInNorthernTransformClickArea = false; 173 isInSouthernTransformClickArea = false; 174 } 175 176 int tType = 0; 177 for (int i = 1; i < transformDirections.length && tType == 0; i++) { 178 if (isInNorthernTransformClickArea == transformDirections[i][0] 179 && isInEasternTransformClickArea == transformDirections[i][1] 180 && isInSouthernTransformClickArea == transformDirections[i][2] 181 && isInWesternTransformClickArea == transformDirections[i][3]) 182 tType = i; 183 } 184 185 return tType; 186 } 187 188 public void showMenu(MouseEvent evt) { 189 JPopupMenu menu = new JPopupMenu(); 190 final JCheckBoxMenuItem cbMenuItem = new JCheckBoxMenuItem( 191 tr("open end"), isOpenEndInterval()); 192 menu.add(cbMenuItem); 193 cbMenuItem.addActionListener(new ActionListener() { 194 @Override 195 public void actionPerformed(ActionEvent e) { 196 if (cbMenuItem.isSelected()) 197 updateTimeInterval(dayStart, dayEnd, minuteStart, 198 24 * 60 + 1); 199 else 200 updateTimeInterval(dayStart, dayEnd, minuteStart, 24 * 60); 201 } 202 }); 203 menu.show(this, evt.getX(), evt.getY()); 204 } 205 206 @Override 207 public void mouseClicked(MouseEvent evt) { 208 } 209 210 @Override 211 public void mouseEntered(MouseEvent evt) { 212 } 213 214 @Override 215 public void mouseExited(MouseEvent evt) { 216 if (transformType < 0) 217 setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 218 } 219 220 @Override 221 public void mousePressed(MouseEvent evt) { 222 if (evt.isPopupTrigger()) { 223 showMenu(evt); 224 } else { 225 actualDayDrag = 0; 226 actualMinuteDrag = 0; 227 dragX = evt.getXOnScreen(); 228 dragY = evt.getYOnScreen(); 229 transformType = getTransformType(evt); 230 } 231 } 232 233 @Override 234 public void mouseReleased(MouseEvent evt) { 235 transformType = -1; 236 } 237 238 @Override 239 public void mouseDragged(MouseEvent evt) { 240 if (transformType >= 0) { 241 int xDiff = evt.getXOnScreen() - dragX; 242 int yDiff = evt.getYOnScreen() - dragY; 243 244 xDiff = (int) Math.round(xDiff / editor.getDayWidth()) 245 - actualDayDrag; 246 yDiff = (int) Math.round(yDiff 247 / (editor.getMinuteHeight() * minuteResterize)) 248 * minuteResterize - actualMinuteDrag; 249 250 if (xDiff != 0) { 251 int newDayStart = dayStart; 252 int newDayEnd = dayEnd; 253 254 if (transformDirections[transformType][3]) 255 newDayStart += xDiff; 256 if (transformDirections[transformType][1]) 257 newDayEnd += xDiff; 258 259 if (newDayStart > newDayEnd) { 260 editor.removeTimeRect(this); 261 transformType = -1; 262 setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 263 } else if (newDayStart >= 0 && newDayEnd <= 6) { 264 actualDayDrag += xDiff; 265 updateTimeInterval(newDayStart, newDayEnd, minuteStart, 266 minuteEnd); 267 } 268 } 269 if (yDiff != 0 && transformType >= 0) { 270 int newMinutesStart = minuteStart; 271 int newMinutesEnd = minuteEnd; 272 273 if (transformDirections[transformType][0]) 274 newMinutesStart = newMinutesStart + yDiff; 275 if (transformDirections[transformType][2] 276 && !isOpenEndInterval()) 277 newMinutesEnd = newMinutesEnd + yDiff; 278 279 if (newMinutesStart >= 0 280 && (newMinutesEnd <= 24 * 60 || isOpenEndInterval())) { 281 actualMinuteDrag += yDiff; 282 updateTimeInterval(dayStart, dayEnd, newMinutesStart, 283 newMinutesEnd); 284 } 285 } 286 } 287 editor.mousePositionChanged(evt.getX() + getX(), evt.getY() + getY()); 288 } 289 290 @Override 291 public void mouseMoved(MouseEvent evt) { 292 if (transformType < 0) 293 setCursor(new Cursor(transformCursorTypes[getTransformType(evt)])); 294 editor.mousePositionChanged(evt.getX() + getX(), evt.getY() + getY()); 295 } 296 296 } -
applications/editors/josm/plugins/OpeningHoursEditor/src/org/openstreetmap/josm/plugins/ohe/parser/OpeningTimeCompilerTokenManager.java
r22751 r23192 274 274 /** Token literal values. */ 275 275 public static final String[] jjstrLiteralImages = { 276 "", null, null, "\53", "\157\146\146", "\62\64\57\67", "\73\40", "\40", "\54", 276 "", null, null, "\53", "\157\146\146", "\62\64\57\67", "\73\40", "\40", "\54", 277 277 "\55", "\72", }; 278 278 … … 362 362 363 363 /** Get the next Token. */ 364 public Token getNextToken() 364 public Token getNextToken() 365 365 { 366 366 Token matchedToken; -
applications/editors/josm/plugins/OpeningHoursEditor/src/org/openstreetmap/josm/plugins/ohe/parser/SyntaxException.java
r22751 r23192 3 3 public class SyntaxException extends Exception { 4 4 5 private int startColumn;6 private int endColumn;7 private String info;5 private int startColumn; 6 private int endColumn; 7 private String info; 8 8 9 public int getStartColumn() {10 return startColumn;11 }9 public int getStartColumn() { 10 return startColumn; 11 } 12 12 13 public int getEndColumn() {14 return endColumn;15 }13 public int getEndColumn() { 14 return endColumn; 15 } 16 16 17 public String getInfo() {18 return info;19 }17 public String getInfo() { 18 return info; 19 } 20 20 21 public SyntaxException(String info, int startColumn, int endColumn) {22 this.startColumn = startColumn;23 this.endColumn = endColumn;24 this.info = info;25 }21 public SyntaxException(String info, int startColumn, int endColumn) { 22 this.startColumn = startColumn; 23 this.endColumn = endColumn; 24 this.info = info; 25 } 26 26 } -
applications/editors/josm/plugins/OpeningHoursEditor/src/org/openstreetmap/josm/plugins/ohe/parser/TokenMgrError.java
r22751 r23192 6 6 public class TokenMgrError extends Error { 7 7 8 /**9 * The version identifier for this Serializable class. Increment only if the10 * <i>serialized</i> form of the class changes.11 */12 private static final long serialVersionUID = 1L;8 /** 9 * The version identifier for this Serializable class. Increment only if the 10 * <i>serialized</i> form of the class changes. 11 */ 12 private static final long serialVersionUID = 1L; 13 13 14 /*15 * Ordinals for various reasons why an Error of this type can be thrown.16 */14 /* 15 * Ordinals for various reasons why an Error of this type can be thrown. 16 */ 17 17 18 /**19 * Lexical error occurred.20 */21 static final int LEXICAL_ERROR = 0;18 /** 19 * Lexical error occurred. 20 */ 21 static final int LEXICAL_ERROR = 0; 22 22 23 /**24 * An attempt was made to create a second instance of a static token25 * manager.26 */27 static final int STATIC_LEXER_ERROR = 1;23 /** 24 * An attempt was made to create a second instance of a static token 25 * manager. 26 */ 27 static final int STATIC_LEXER_ERROR = 1; 28 28 29 /**30 * Tried to change to an invalid lexical state.31 */32 static final int INVALID_LEXICAL_STATE = 2;29 /** 30 * Tried to change to an invalid lexical state. 31 */ 32 static final int INVALID_LEXICAL_STATE = 2; 33 33 34 /**35 * Detected (and bailed out of) an infinite loop in the token manager.36 */37 static final int LOOP_DETECTED = 3;34 /** 35 * Detected (and bailed out of) an infinite loop in the token manager. 36 */ 37 static final int LOOP_DETECTED = 3; 38 38 39 /**40 * Indicates the reason why the exception is thrown. It will have one of the41 * above 4 values.42 */43 int errorCode;39 /** 40 * Indicates the reason why the exception is thrown. It will have one of the 41 * above 4 values. 42 */ 43 int errorCode; 44 44 45 /**46 * Replaces unprintable characters by their escaped (or unicode escaped)47 * equivalents in the given string48 */49 protected static final String addEscapes(String str) {50 StringBuffer retval = new StringBuffer();51 char ch;52 for (int i = 0; i < str.length(); i++) {53 switch (str.charAt(i)) {54 case 0:55 continue;56 case '\b':57 retval.append("\\b");58 continue;59 case '\t':60 retval.append("\\t");61 continue;62 case '\n':63 retval.append("\\n");64 continue;65 case '\f':66 retval.append("\\f");67 continue;68 case '\r':69 retval.append("\\r");70 continue;71 case '\"':72 retval.append("\\\"");73 continue;74 case '\'':75 retval.append("\\\'");76 continue;77 case '\\':78 retval.append("\\\\");79 continue;80 default:81 if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {82 String s = "0000" + Integer.toString(ch, 16);83 retval.append("\\u"84 + s.substring(s.length() - 4, s.length()));85 } else {86 retval.append(ch);87 }88 continue;89 }90 }91 return retval.toString();92 }45 /** 46 * Replaces unprintable characters by their escaped (or unicode escaped) 47 * equivalents in the given string 48 */ 49 protected static final String addEscapes(String str) { 50 StringBuffer retval = new StringBuffer(); 51 char ch; 52 for (int i = 0; i < str.length(); i++) { 53 switch (str.charAt(i)) { 54 case 0: 55 continue; 56 case '\b': 57 retval.append("\\b"); 58 continue; 59 case '\t': 60 retval.append("\\t"); 61 continue; 62 case '\n': 63 retval.append("\\n"); 64 continue; 65 case '\f': 66 retval.append("\\f"); 67 continue; 68 case '\r': 69 retval.append("\\r"); 70 continue; 71 case '\"': 72 retval.append("\\\""); 73 continue; 74 case '\'': 75 retval.append("\\\'"); 76 continue; 77 case '\\': 78 retval.append("\\\\"); 79 continue; 80 default: 81 if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { 82 String s = "0000" + Integer.toString(ch, 16); 83 retval.append("\\u" 84 + s.substring(s.length() - 4, s.length())); 85 } else { 86 retval.append(ch); 87 } 88 continue; 89 } 90 } 91 return retval.toString(); 92 } 93 93 94 /**95 * Returns a detailed message for the Error when it is thrown by the token96 * manager to indicate a lexical error. Parameters : EOFSeen : indicates if97 * EOF caused the lexical error curLexState : lexical state in which this98 * error occurred errorLine : line number when the error occurred99 * errorColumn : column number when the error occurred errorAfter : prefix100 * that was seen before this error occurred curchar : the offending101 * character Note: You can customize the lexical error message by modifying102 * this method.103 */104 protected static String LexicalError(boolean EOFSeen, int lexState,105 int errorLine, int errorColumn, String errorAfter, char curChar) {106 return ("Lexical error at line "107 + errorLine108 + ", column "109 + errorColumn110 + ". Encountered: "111 + (EOFSeen ? "<EOF> " : ("\""112 + addEscapes(String.valueOf(curChar)) + "\"")113 + " (" + (int) curChar + "), ") + "after : \""114 + addEscapes(errorAfter) + "\"");115 }94 /** 95 * Returns a detailed message for the Error when it is thrown by the token 96 * manager to indicate a lexical error. Parameters : EOFSeen : indicates if 97 * EOF caused the lexical error curLexState : lexical state in which this 98 * error occurred errorLine : line number when the error occurred 99 * errorColumn : column number when the error occurred errorAfter : prefix 100 * that was seen before this error occurred curchar : the offending 101 * character Note: You can customize the lexical error message by modifying 102 * this method. 103 */ 104 protected static String LexicalError(boolean EOFSeen, int lexState, 105 int errorLine, int errorColumn, String errorAfter, char curChar) { 106 return ("Lexical error at line " 107 + errorLine 108 + ", column " 109 + errorColumn 110 + ". Encountered: " 111 + (EOFSeen ? "<EOF> " : ("\"" 112 + addEscapes(String.valueOf(curChar)) + "\"") 113 + " (" + (int) curChar + "), ") + "after : \"" 114 + addEscapes(errorAfter) + "\""); 115 } 116 116 117 /**118 * You can also modify the body of this method to customize your error119 * messages. For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE120 * are not of end-users concern, so you can return something like :121 *122 * "Internal Error : Please file a bug report .... "123 *124 * from this method for such cases in the release version of your parser.125 */126 @Override127 public String getMessage() {128 return super.getMessage();129 }117 /** 118 * You can also modify the body of this method to customize your error 119 * messages. For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE 120 * are not of end-users concern, so you can return something like : 121 * 122 * "Internal Error : Please file a bug report .... " 123 * 124 * from this method for such cases in the release version of your parser. 125 */ 126 @Override 127 public String getMessage() { 128 return super.getMessage(); 129 } 130 130 131 /*132 * Constructors of various flavors follow.133 */131 /* 132 * Constructors of various flavors follow. 133 */ 134 134 135 /** No arg constructor. */136 public TokenMgrError() {137 }135 /** No arg constructor. */ 136 public TokenMgrError() { 137 } 138 138 139 /** Constructor with message and reason. */140 public TokenMgrError(String message, int reason) {141 super(message);142 errorCode = reason;143 }139 /** Constructor with message and reason. */ 140 public TokenMgrError(String message, int reason) { 141 super(message); 142 errorCode = reason; 143 } 144 144 145 public boolean EOFSeen;146 public int lexState;147 public int errorLine;148 public int errorColumn;149 public String errorAfter;150 public char curChar;151 public int reason;145 public boolean EOFSeen; 146 public int lexState; 147 public int errorLine; 148 public int errorColumn; 149 public String errorAfter; 150 public char curChar; 151 public int reason; 152 152 153 /** Full Constructor. */154 public TokenMgrError(boolean EOFSeen, int lexState, int errorLine,155 int errorColumn, String errorAfter, char curChar, int reason) {156 this.EOFSeen = EOFSeen;157 this.lexState = lexState;158 this.errorLine = errorLine;159 this.errorColumn = errorColumn;160 this.errorAfter = errorAfter;161 this.curChar = curChar;162 this.reason = reason;163 }153 /** Full Constructor. */ 154 public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, 155 int errorColumn, String errorAfter, char curChar, int reason) { 156 this.EOFSeen = EOFSeen; 157 this.lexState = lexState; 158 this.errorLine = errorLine; 159 this.errorColumn = errorColumn; 160 this.errorAfter = errorAfter; 161 this.curChar = curChar; 162 this.reason = reason; 163 } 164 164 } 165 165 /*
Note:
See TracChangeset
for help on using the changeset viewer.
