fixup i18n
[fanfix.git] / src / jexer / TTableWindow.java
CommitLineData
1dac6b8d
KL
1/*
2 * Jexer - Java Text User Interface
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (C) 2019 Kevin Lamonte
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29package jexer;
30
759cb83e
KL
31import java.io.IOException;
32import java.text.MessageFormat;
1dac6b8d
KL
33import java.util.ResourceBundle;
34
35import jexer.event.TCommandEvent;
36import jexer.event.TKeypressEvent;
f528c340 37import jexer.event.TMenuEvent;
1dac6b8d
KL
38import jexer.event.TMouseEvent;
39import jexer.event.TResizeEvent;
40import jexer.menu.TMenu;
f528c340 41import jexer.menu.TMenuItem;
1dac6b8d
KL
42import static jexer.TCommand.*;
43import static jexer.TKeypress.*;
44
45/**
46 * TTableWindow is used to display and edit regular two-dimensional tables of
47 * cells.
48 */
49public class TTableWindow extends TScrollableWindow {
50
51 /**
52 * Translated strings.
53 */
54 private static final ResourceBundle i18n = ResourceBundle.getBundle(TTableWindow.class.getName());
55
56 // ------------------------------------------------------------------------
57 // Variables --------------------------------------------------------------
58 // ------------------------------------------------------------------------
59
60 /**
61 * The table widget.
62 */
63 private TTableWidget tableField;
64
65 // ------------------------------------------------------------------------
66 // Constructors -----------------------------------------------------------
67 // ------------------------------------------------------------------------
68
69 /**
70 * Public constructor sets window title.
71 *
72 * @param parent the main application
73 * @param title the window title
74 */
75 public TTableWindow(final TApplication parent, final String title) {
76
77 super(parent, title, 0, 0, parent.getScreen().getWidth() / 2,
78 parent.getScreen().getHeight() / 2 - 2, RESIZABLE | CENTERED);
79
382bc294 80 tableField = addTable(0, 0, getWidth() - 2, getHeight() - 2);
1dac6b8d
KL
81 setupAfterTable();
82 }
83
84 // ------------------------------------------------------------------------
85 // Event handlers ---------------------------------------------------------
86 // ------------------------------------------------------------------------
87
88 /**
89 * Called by application.switchWindow() when this window gets the
90 * focus, and also by application.addWindow().
91 */
92 public void onFocus() {
93 // Enable the table menu items.
94 getApplication().enableMenuItem(TMenu.MID_CUT);
2b427404
KL
95 getApplication().enableMenuItem(TMenu.MID_TABLE_RENAME_COLUMN);
96 getApplication().enableMenuItem(TMenu.MID_TABLE_RENAME_ROW);
77961919
KL
97 getApplication().enableMenuItem(TMenu.MID_TABLE_VIEW_ROW_LABELS);
98 getApplication().enableMenuItem(TMenu.MID_TABLE_VIEW_COLUMN_LABELS);
99 getApplication().enableMenuItem(TMenu.MID_TABLE_VIEW_HIGHLIGHT_ROW);
100 getApplication().enableMenuItem(TMenu.MID_TABLE_VIEW_HIGHLIGHT_COLUMN);
1dac6b8d
KL
101 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_NONE);
102 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_ALL);
e9bb3c1e
KL
103 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_CELL_NONE);
104 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_CELL_ALL);
1dac6b8d
KL
105 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_RIGHT);
106 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_LEFT);
107 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_TOP);
108 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_BOTTOM);
109 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_DOUBLE_BOTTOM);
110 getApplication().enableMenuItem(TMenu.MID_TABLE_BORDER_THICK_BOTTOM);
111 getApplication().enableMenuItem(TMenu.MID_TABLE_DELETE_LEFT);
112 getApplication().enableMenuItem(TMenu.MID_TABLE_DELETE_UP);
113 getApplication().enableMenuItem(TMenu.MID_TABLE_DELETE_ROW);
114 getApplication().enableMenuItem(TMenu.MID_TABLE_DELETE_COLUMN);
115 getApplication().enableMenuItem(TMenu.MID_TABLE_INSERT_LEFT);
116 getApplication().enableMenuItem(TMenu.MID_TABLE_INSERT_RIGHT);
117 getApplication().enableMenuItem(TMenu.MID_TABLE_INSERT_ABOVE);
118 getApplication().enableMenuItem(TMenu.MID_TABLE_INSERT_BELOW);
119 getApplication().enableMenuItem(TMenu.MID_TABLE_COLUMN_NARROW);
120 getApplication().enableMenuItem(TMenu.MID_TABLE_COLUMN_WIDEN);
f528c340 121 getApplication().enableMenuItem(TMenu.MID_TABLE_FILE_OPEN_CSV);
1dac6b8d
KL
122 getApplication().enableMenuItem(TMenu.MID_TABLE_FILE_SAVE_CSV);
123 getApplication().enableMenuItem(TMenu.MID_TABLE_FILE_SAVE_TEXT);
f528c340
KL
124
125 if (tableField != null) {
126
127 // Set the menu to match the flags.
128 TMenuItem menuItem = getApplication().getMenuItem(TMenu.MID_TABLE_VIEW_ROW_LABELS);
129 if (menuItem != null) {
130 menuItem.setChecked(tableField.getShowRowLabels());
131 }
132 menuItem = getApplication().getMenuItem(TMenu.MID_TABLE_VIEW_COLUMN_LABELS);
133 if (menuItem != null) {
134 menuItem.setChecked(tableField.getShowColumnLabels());
135 }
136 menuItem = getApplication().getMenuItem(TMenu.MID_TABLE_VIEW_HIGHLIGHT_ROW);
137 if (menuItem != null) {
138 menuItem.setChecked(tableField.getHighlightRow());
139 }
140 menuItem = getApplication().getMenuItem(TMenu.MID_TABLE_VIEW_HIGHLIGHT_COLUMN);
141 if (menuItem != null) {
142 menuItem.setChecked(tableField.getHighlightColumn());
143 }
144 }
1dac6b8d
KL
145 }
146
147 /**
148 * Called by application.switchWindow() when another window gets the
149 * focus.
150 */
151 public void onUnfocus() {
152 // Disable the table menu items.
153 getApplication().disableMenuItem(TMenu.MID_CUT);
2b427404
KL
154 getApplication().disableMenuItem(TMenu.MID_TABLE_RENAME_COLUMN);
155 getApplication().disableMenuItem(TMenu.MID_TABLE_RENAME_ROW);
77961919
KL
156 getApplication().disableMenuItem(TMenu.MID_TABLE_VIEW_ROW_LABELS);
157 getApplication().disableMenuItem(TMenu.MID_TABLE_VIEW_COLUMN_LABELS);
158 getApplication().disableMenuItem(TMenu.MID_TABLE_VIEW_HIGHLIGHT_ROW);
159 getApplication().disableMenuItem(TMenu.MID_TABLE_VIEW_HIGHLIGHT_COLUMN);
1dac6b8d
KL
160 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_NONE);
161 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_ALL);
e9bb3c1e
KL
162 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_CELL_NONE);
163 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_CELL_ALL);
1dac6b8d
KL
164 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_RIGHT);
165 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_LEFT);
166 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_TOP);
167 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_BOTTOM);
168 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_DOUBLE_BOTTOM);
169 getApplication().disableMenuItem(TMenu.MID_TABLE_BORDER_THICK_BOTTOM);
170 getApplication().disableMenuItem(TMenu.MID_TABLE_DELETE_LEFT);
171 getApplication().disableMenuItem(TMenu.MID_TABLE_DELETE_UP);
172 getApplication().disableMenuItem(TMenu.MID_TABLE_DELETE_ROW);
173 getApplication().disableMenuItem(TMenu.MID_TABLE_DELETE_COLUMN);
174 getApplication().disableMenuItem(TMenu.MID_TABLE_INSERT_LEFT);
175 getApplication().disableMenuItem(TMenu.MID_TABLE_INSERT_RIGHT);
176 getApplication().disableMenuItem(TMenu.MID_TABLE_INSERT_ABOVE);
177 getApplication().disableMenuItem(TMenu.MID_TABLE_INSERT_BELOW);
178 getApplication().disableMenuItem(TMenu.MID_TABLE_COLUMN_NARROW);
179 getApplication().disableMenuItem(TMenu.MID_TABLE_COLUMN_WIDEN);
f528c340 180 getApplication().disableMenuItem(TMenu.MID_TABLE_FILE_OPEN_CSV);
1dac6b8d
KL
181 getApplication().disableMenuItem(TMenu.MID_TABLE_FILE_SAVE_CSV);
182 getApplication().disableMenuItem(TMenu.MID_TABLE_FILE_SAVE_TEXT);
183 }
184
185 // ------------------------------------------------------------------------
186 // TWindow ----------------------------------------------------------------
187 // ------------------------------------------------------------------------
188
1dac6b8d
KL
189 /**
190 * Handle mouse press events.
191 *
192 * @param mouse mouse button press event
193 */
194 @Override
195 public void onMouseDown(final TMouseEvent mouse) {
196 // Use TWidget's code to pass the event to the children.
197 super.onMouseDown(mouse);
198
199 if (mouseOnTable(mouse)) {
200 // The table might have changed, update the scollbars.
759cb83e
KL
201 setBottomValue(tableField.getRowCount() - 1);
202 setVerticalValue(tableField.getSelectedRowNumber());
203 setRightValue(tableField.getColumnCount() - 1);
204 setHorizontalValue(tableField.getSelectedColumnNumber());
1dac6b8d
KL
205 }
206 }
207
208 /**
209 * Handle mouse release events.
210 *
211 * @param mouse mouse button release event
212 */
213 @Override
214 public void onMouseUp(final TMouseEvent mouse) {
215 // Use TWidget's code to pass the event to the children.
216 super.onMouseUp(mouse);
217
218 if (mouse.isMouse1() && mouseOnVerticalScroller(mouse)) {
759cb83e
KL
219 // Clicked/dragged on vertical scrollbar.
220 tableField.setSelectedRowNumber(getVerticalValue());
221 }
222 if (mouse.isMouse1() && mouseOnHorizontalScroller(mouse)) {
223 // Clicked/dragged on horizontal scrollbar.
224 tableField.setSelectedColumnNumber(getHorizontalValue());
1dac6b8d 225 }
1dac6b8d
KL
226 }
227
228 /**
229 * Method that subclasses can override to handle mouse movements.
230 *
231 * @param mouse mouse motion event
232 */
233 @Override
234 public void onMouseMotion(final TMouseEvent mouse) {
235 // Use TWidget's code to pass the event to the children.
236 super.onMouseMotion(mouse);
237
238 if (mouseOnTable(mouse) && mouse.isMouse1()) {
759cb83e
KL
239 // The table might have changed, update the scollbars.
240 setBottomValue(tableField.getRowCount() - 1);
241 setVerticalValue(tableField.getSelectedRowNumber());
242 setRightValue(tableField.getColumnCount() - 1);
243 setHorizontalValue(tableField.getSelectedColumnNumber());
1dac6b8d
KL
244 } else {
245 if (mouse.isMouse1() && mouseOnVerticalScroller(mouse)) {
759cb83e
KL
246 // Clicked/dragged on vertical scrollbar.
247 tableField.setSelectedRowNumber(getVerticalValue());
248 }
249 if (mouse.isMouse1() && mouseOnHorizontalScroller(mouse)) {
250 // Clicked/dragged on horizontal scrollbar.
251 tableField.setSelectedColumnNumber(getHorizontalValue());
1dac6b8d 252 }
1dac6b8d
KL
253 }
254
255 }
256
257 /**
258 * Handle keystrokes.
259 *
260 * @param keypress keystroke event
261 */
262 @Override
263 public void onKeypress(final TKeypressEvent keypress) {
264 // Use TWidget's code to pass the event to the children.
265 super.onKeypress(keypress);
266
759cb83e
KL
267 // The table might have changed, update the scollbars.
268 setBottomValue(tableField.getRowCount() - 1);
269 setVerticalValue(tableField.getSelectedRowNumber());
270 setRightValue(tableField.getColumnCount() - 1);
271 setHorizontalValue(tableField.getSelectedColumnNumber());
1dac6b8d
KL
272 }
273
274 /**
275 * Handle window/screen resize events.
276 *
277 * @param event resize event
278 */
279 @Override
280 public void onResize(final TResizeEvent event) {
281 if (event.getType() == TResizeEvent.Type.WIDGET) {
282 // Resize the table
283 TResizeEvent tableSize = new TResizeEvent(TResizeEvent.Type.WIDGET,
284 event.getWidth() - 2, event.getHeight() - 2);
285 tableField.onResize(tableSize);
286
287 // Have TScrollableWindow handle the scrollbars
288 super.onResize(event);
289 return;
290 }
291
292 // Pass to children instead
293 for (TWidget widget: getChildren()) {
294 widget.onResize(event);
295 }
296 }
297
759cb83e
KL
298 /**
299 * Method that subclasses can override to handle posted command events.
300 *
301 * @param command command event
302 */
303 @Override
304 public void onCommand(final TCommandEvent command) {
305 if (command.equals(cmOpen)) {
306 try {
307 String filename = fileOpenBox(".");
308 if (filename != null) {
309 try {
310 // TODO
311 if (false) {
f528c340 312 tableField.saveToCsvFilename(filename);
759cb83e
KL
313 }
314 } catch (IOException e) {
315 messageBox(i18n.getString("errorDialogTitle"),
316 MessageFormat.format(i18n.
317 getString("errorReadingFile"), e.getMessage()));
318 }
319 }
320 } catch (IOException e) {
321 messageBox(i18n.getString("errorDialogTitle"),
322 MessageFormat.format(i18n.
323 getString("errorOpeningFileDialog"), e.getMessage()));
324 }
325 return;
326 }
327
f528c340
KL
328 // Didn't handle it, let children get it instead
329 super.onCommand(command);
330 }
331
332 /**
333 * Handle posted menu events.
334 *
335 * @param menu menu event
336 */
337 @Override
338 public void onMenu(final TMenuEvent menu) {
339 TInputBox inputBox;
340
341 switch (menu.getId()) {
342 case TMenu.MID_TABLE_RENAME_COLUMN:
343 inputBox = inputBox(i18n.getString("renameColumnInputTitle"),
344 i18n.getString("renameColumnInputCaption"),
345 tableField.getColumnLabel(tableField.getSelectedColumnNumber()),
346 TMessageBox.Type.OKCANCEL);
347 if (inputBox.isOk()) {
348 tableField.setColumnLabel(tableField.getSelectedColumnNumber(),
349 inputBox.getText());
759cb83e
KL
350 }
351 return;
f528c340
KL
352 case TMenu.MID_TABLE_RENAME_ROW:
353 inputBox = inputBox(i18n.getString("renameRowInputTitle"),
354 i18n.getString("renameRowInputCaption"),
355 tableField.getRowLabel(tableField.getSelectedRowNumber()),
356 TMessageBox.Type.OKCANCEL);
357 if (inputBox.isOk()) {
358 tableField.setRowLabel(tableField.getSelectedRowNumber(),
359 inputBox.getText());
360 }
361 return;
362 case TMenu.MID_TABLE_VIEW_ROW_LABELS:
363 tableField.setShowRowLabels(getApplication().getMenuItem(
364 menu.getId()).getChecked());
365 return;
366 case TMenu.MID_TABLE_VIEW_COLUMN_LABELS:
367 tableField.setShowColumnLabels(getApplication().getMenuItem(
368 menu.getId()).getChecked());
369 return;
370 case TMenu.MID_TABLE_VIEW_HIGHLIGHT_ROW:
371 tableField.setHighlightRow(getApplication().getMenuItem(
372 menu.getId()).getChecked());
373 return;
374 case TMenu.MID_TABLE_VIEW_HIGHLIGHT_COLUMN:
375 tableField.setHighlightColumn(getApplication().getMenuItem(
376 menu.getId()).getChecked());
377 return;
378 case TMenu.MID_TABLE_BORDER_NONE:
379 tableField.setBorderAllNone();
380 return;
381 case TMenu.MID_TABLE_BORDER_ALL:
382 tableField.setBorderAllSingle();
383 return;
384 case TMenu.MID_TABLE_BORDER_CELL_NONE:
385 tableField.setBorderCellNone();
386 return;
387 case TMenu.MID_TABLE_BORDER_CELL_ALL:
388 tableField.setBorderCellSingle();
389 return;
390 case TMenu.MID_TABLE_BORDER_RIGHT:
391 tableField.setBorderColumnRightSingle();
392 return;
393 case TMenu.MID_TABLE_BORDER_LEFT:
394 tableField.setBorderColumnLeftSingle();
395 return;
396 case TMenu.MID_TABLE_BORDER_TOP:
397 tableField.setBorderRowAboveSingle();
398 return;
399 case TMenu.MID_TABLE_BORDER_BOTTOM:
400 tableField.setBorderRowBelowSingle();
401 return;
402 case TMenu.MID_TABLE_BORDER_DOUBLE_BOTTOM:
403 tableField.setBorderRowBelowDouble();
404 return;
405 case TMenu.MID_TABLE_BORDER_THICK_BOTTOM:
406 tableField.setBorderRowBelowThick();
407 return;
408 case TMenu.MID_TABLE_DELETE_LEFT:
409 tableField.deleteCellShiftLeft();
410 return;
411 case TMenu.MID_TABLE_DELETE_UP:
412 tableField.deleteCellShiftUp();
413 return;
414 case TMenu.MID_TABLE_DELETE_ROW:
415 tableField.deleteRow(tableField.getSelectedRowNumber());
416 return;
417 case TMenu.MID_TABLE_DELETE_COLUMN:
418 tableField.deleteColumn(tableField.getSelectedColumnNumber());
419 return;
420 case TMenu.MID_TABLE_INSERT_LEFT:
421 tableField.insertColumnLeft(tableField.getSelectedColumnNumber());
422 return;
423 case TMenu.MID_TABLE_INSERT_RIGHT:
424 tableField.insertColumnRight(tableField.getSelectedColumnNumber());
425 return;
426 case TMenu.MID_TABLE_INSERT_ABOVE:
427 tableField.insertRowAbove(tableField.getSelectedColumnNumber());
428 return;
429 case TMenu.MID_TABLE_INSERT_BELOW:
430 tableField.insertRowBelow(tableField.getSelectedColumnNumber());
431 return;
432 case TMenu.MID_TABLE_COLUMN_NARROW:
433 tableField.setColumnWidth(tableField.getSelectedColumnNumber(),
434 tableField.getColumnWidth(tableField.getSelectedColumnNumber()) - 1);
435 return;
436 case TMenu.MID_TABLE_COLUMN_WIDEN:
437 tableField.setColumnWidth(tableField.getSelectedColumnNumber(),
438 tableField.getColumnWidth(tableField.getSelectedColumnNumber()) + 1);
439 return;
440 case TMenu.MID_TABLE_FILE_OPEN_CSV:
441 // TODO
442 return;
443 case TMenu.MID_TABLE_FILE_SAVE_CSV:
444 // TODO
445 return;
446 case TMenu.MID_TABLE_FILE_SAVE_TEXT:
447 // TODO
448 return;
449 default:
450 break;
759cb83e
KL
451 }
452
f528c340 453 super.onMenu(menu);
759cb83e
KL
454 }
455
1dac6b8d
KL
456 // ------------------------------------------------------------------------
457 // TTableWindow -----------------------------------------------------------
458 // ------------------------------------------------------------------------
459
460 /**
461 * Setup other fields after the table is created.
462 */
463 private void setupAfterTable() {
464 hScroller = new THScroller(this, 17, getHeight() - 2, getWidth() - 20);
465 vScroller = new TVScroller(this, getWidth() - 2, 0, getHeight() - 2);
466 setMinimumWindowWidth(25);
467 setMinimumWindowHeight(10);
759cb83e
KL
468 setTopValue(tableField.getSelectedRowNumber());
469 setBottomValue(tableField.getRowCount() - 1);
470 setLeftValue(tableField.getSelectedColumnNumber());
471 setRightValue(tableField.getColumnCount() - 1);
1dac6b8d
KL
472
473 statusBar = newStatusBar(i18n.getString("statusBar"));
474 statusBar.addShortcutKeypress(kbF1, cmHelp,
475 i18n.getString("statusBarHelp"));
759cb83e 476
1dac6b8d
KL
477 statusBar.addShortcutKeypress(kbF2, cmSave,
478 i18n.getString("statusBarSave"));
479 statusBar.addShortcutKeypress(kbF3, cmOpen,
480 i18n.getString("statusBarOpen"));
1dac6b8d
KL
481 statusBar.addShortcutKeypress(kbF10, cmMenu,
482 i18n.getString("statusBarMenu"));
f528c340
KL
483
484 // Synchronize the menu with tableField's flags.
485 onFocus();
1dac6b8d
KL
486 }
487
488 /**
489 * Check if a mouse press/release/motion event coordinate is over the
490 * table.
491 *
492 * @param mouse a mouse-based event
493 * @return whether or not the mouse is on the table
494 */
495 private boolean mouseOnTable(final TMouseEvent mouse) {
496 if ((mouse.getAbsoluteX() >= getAbsoluteX() + 1)
497 && (mouse.getAbsoluteX() < getAbsoluteX() + getWidth() - 1)
498 && (mouse.getAbsoluteY() >= getAbsoluteY() + 1)
499 && (mouse.getAbsoluteY() < getAbsoluteY() + getHeight() - 1)
500 ) {
501 return true;
502 }
503 return false;
504 }
505
506}