draggable window
[fanfix.git] / src / jexer / TWindow.java
CommitLineData
48e27807
KL
1/**
2 * Jexer - Java Text User Interface
3 *
4 * License: LGPLv3 or later
5 *
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
9 *
10 * Copyright (C) 2015 Kevin Lamonte
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * 02110-1301 USA
27 *
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 * @version 1
30 */
31package jexer;
32
33import jexer.bits.Cell;
34import jexer.bits.CellAttributes;
35import jexer.bits.GraphicsChars;
36import jexer.event.TCommandEvent;
37import jexer.event.TKeypressEvent;
38import jexer.event.TMenuEvent;
39import jexer.event.TMouseEvent;
40import jexer.event.TResizeEvent;
41import jexer.io.Screen;
42import static jexer.TCommand.*;
43import static jexer.TKeypress.*;
44
45/**
46 * TWindow is the top-level container and drawing surface for other widgets.
47 */
a06459bd 48public class TWindow extends TWidget implements Comparable<TWindow> {
48e27807
KL
49
50 /**
51 * Window's parent TApplication.
52 */
53 protected TApplication application;
54
55 /**
56 * Get this TWindow's parent TApplication.
57 *
58 * @return this TWindow's parent TApplication
59 */
60 public final TApplication getApplication() {
61 return application;
62 }
63
64 /**
65 * Get the Screen.
66 *
67 * @return the Screen
68 */
69 public final Screen getScreen() {
70 return application.getScreen();
71 }
72
73 /**
74 * Window title.
75 */
76 protected String title = "";
77
78 /**
79 * Window is resizable (default yes).
80 */
81 public static final int RESIZABLE = 0x01;
82
83 /**
84 * Window is modal (default no).
85 */
86 public static final int MODAL = 0x02;
87
88 /**
89 * Window is centered (default no).
90 */
91 public static final int CENTERED = 0x04;
92
93 /**
94 * Window flags.
95 */
96 private int flags = RESIZABLE;
97
98 /**
99 * Z order. Lower number means more in-front.
100 */
101 private int z = 0;
102
a06459bd
KL
103 /**
104 * Get Z order. Lower number means more in-front.
105 *
106 * @return Z value. Lower number means more in-front.
107 */
108 public final int getZ() {
109 return z;
110 }
111
112 /**
113 * Set Z order. Lower number means more in-front.
114 *
115 * @param z the new Z value. Lower number means more in-front.
116 */
117 public final void setZ(final int z) {
118 this.z = z;
119 }
120
48e27807
KL
121 /**
122 * If true, then the user clicked on the title bar and is moving the
123 * window.
124 */
125 private boolean inWindowMove = false;
126
127 /**
128 * If true, then the user clicked on the bottom right corner and is
129 * resizing the window.
130 */
131 private boolean inWindowResize = false;
132
133 /**
134 * If true, then the user selected "Size/Move" (or hit Ctrl-F5) and is
135 * resizing/moving the window via the keyboard.
136 */
137 private boolean inKeyboardResize = false;
138
139 /**
140 * If true, this window is maximized.
141 */
142 private boolean maximized = false;
143
144 /**
145 * Remember mouse state.
146 */
147 protected TMouseEvent mouse;
148
149 // For moving the window. resizing also uses moveWindowMouseX/Y
150 private int moveWindowMouseX;
151 private int moveWindowMouseY;
152 private int oldWindowX;
153 private int oldWindowY;
154
155 // Resizing
156 private int resizeWindowWidth;
157 private int resizeWindowHeight;
158 private int minimumWindowWidth = 10;
159 private int minimumWindowHeight = 2;
160 private int maximumWindowWidth = -1;
161 private int maximumWindowHeight = -1;
162
163 // For maximize/restore
164 private int restoreWindowWidth;
165 private int restoreWindowHeight;
166 private int restoreWindowX;
167 private int restoreWindowY;
168
169 /**
170 * Public constructor. Window will be located at (0, 0).
171 *
172 * @param application TApplication that manages this window
173 * @param title window title, will be centered along the top border
174 * @param width width of window
175 * @param height height of window
176 */
177 public TWindow(final TApplication application, final String title,
178 final int width, final int height) {
179
180 this(application, title, 0, 0, width, height, RESIZABLE);
181 }
182
183 /**
184 * Public constructor. Window will be located at (0, 0).
185 *
186 * @param application TApplication that manages this window
187 * @param title window title, will be centered along the top border
188 * @param width width of window
189 * @param height height of window
190 * @param flags bitmask of RESIZABLE, CENTERED, or MODAL
191 */
192 public TWindow(final TApplication application, final String title,
193 final int width, final int height, final int flags) {
194
195 this(application, title, 0, 0, width, height, flags);
196 }
197
198 /**
199 * Public constructor.
200 *
201 * @param application TApplication that manages this window
202 * @param title window title, will be centered along the top border
203 * @param x column relative to parent
204 * @param y row relative to parent
205 * @param width width of window
206 * @param height height of window
207 */
208 public TWindow(final TApplication application, final String title,
209 final int x, final int y, final int width, final int height) {
210
211 this(application, title, x, y, width, height, RESIZABLE);
212 }
213
214 /**
215 * Public constructor.
216 *
217 * @param application TApplication that manages this window
218 * @param title window title, will be centered along the top border
219 * @param x column relative to parent
220 * @param y row relative to parent
221 * @param width width of window
222 * @param height height of window
223 * @param flags mask of RESIZABLE, CENTERED, or MODAL
224 */
225 public TWindow(final TApplication application, final String title,
226 final int x, final int y, final int width, final int height,
227 final int flags) {
228
229 // I am my own window and parent
230 this.parent = this;
231 this.window = this;
232
233 // Save fields
234 this.title = title;
235 this.application = application;
236 this.x = x;
237 this.y = y + application.getDesktopTop();
238 this.width = width;
239 this.height = height;
240 this.flags = flags;
241
242 // Minimum width/height are 10 and 2
243 assert (width >= 10);
244 assert (height >= 2);
245
246 // MODAL implies CENTERED
247 if (isModal()) {
248 this.flags |= CENTERED;
249 }
250
251 // Center window if specified
252 center();
253
254 // Add me to the application
255 application.addWindow(this);
256 }
257
258 /**
259 * Recenter the window on-screen.
260 */
261 public final void center() {
262 if ((flags & CENTERED) != 0) {
263 if (width < getScreen().getWidth()) {
264 x = (getScreen().getWidth() - width) / 2;
265 } else {
266 x = 0;
267 }
268 y = (application.getDesktopBottom() - application.getDesktopTop());
269 y -= height;
270 y /= 2;
271 if (y < 0) {
272 y = 0;
273 }
274 y += application.getDesktopTop();
275 }
276 }
277
278 /**
279 * Returns true if this window is modal.
280 *
281 * @return true if this window is modal
282 */
283 public final boolean isModal() {
284 if ((flags & MODAL) == 0) {
285 return false;
286 }
287 return true;
288 }
289
290 /**
291 * Comparison operator sorts on z.
292 *
293 * @param that another TWindow instance
294 * @return difference between this.z and that.z
295 */
a06459bd
KL
296 @Override
297 public final int compareTo(final TWindow that) {
298 return (this.z - that.z);
48e27807
KL
299 }
300
301 /**
302 * Returns true if the mouse is currently on the close button.
303 *
304 * @return true if mouse is currently on the close button
305 */
306 private boolean mouseOnClose() {
307 if ((mouse != null)
308 && (mouse.getAbsoluteY() == y)
309 && (mouse.getAbsoluteX() == x + 3)
310 ) {
311 return true;
312 }
313 return false;
314 }
315
316 /**
317 * Returns true if the mouse is currently on the maximize/restore button.
318 *
319 * @return true if the mouse is currently on the maximize/restore button
320 */
321 private boolean mouseOnMaximize() {
322 if ((mouse != null)
323 && !isModal()
324 && (mouse.getAbsoluteY() == y)
325 && (mouse.getAbsoluteX() == x + width - 4)
326 ) {
327 return true;
328 }
329 return false;
330 }
331
332 /**
333 * Returns true if the mouse is currently on the resizable lower right
334 * corner.
335 *
336 * @return true if the mouse is currently on the resizable lower right
337 * corner
338 */
339 private boolean mouseOnResize() {
340 if (((flags & RESIZABLE) != 0)
341 && !isModal()
342 && (mouse != null)
343 && (mouse.getAbsoluteY() == y + height - 1)
344 && ((mouse.getAbsoluteX() == x + width - 1)
345 || (mouse.getAbsoluteX() == x + width - 2))
346 ) {
347 return true;
348 }
349 return false;
350 }
351
352 /**
353 * Retrieve the background color.
354 *
355 * @return the background color
356 */
357 protected final CellAttributes getBackground() {
358 if (!isModal()
359 && (inWindowMove || inWindowResize || inKeyboardResize)
360 ) {
361 assert (active);
362 return application.getTheme().getColor("twindow.background.windowmove");
363 } else if (isModal() && inWindowMove) {
364 assert (active);
365 return application.getTheme().getColor("twindow.background.modal");
366 } else if (isModal()) {
367 if (active) {
368 return application.getTheme().getColor("twindow.background.modal");
369 }
370 return application.getTheme().getColor("twindow.background.modal.inactive");
371 } else if (active) {
372 assert (!isModal());
373 return application.getTheme().getColor("twindow.background");
374 } else {
375 assert (!isModal());
376 return application.getTheme().getColor("twindow.background.inactive");
377 }
378 }
379
380 /**
381 * Retrieve the border color.
382 *
383 * @return the border color
384 */
385 protected final CellAttributes getBorder() {
386 if (!isModal()
387 && (inWindowMove || inWindowResize || inKeyboardResize)
388 ) {
389 assert (active);
390 return application.getTheme().getColor("twindow.border.windowmove");
391 } else if (isModal() && inWindowMove) {
392 assert (active);
393 return application.getTheme().getColor("twindow.border.modal.windowmove");
394 } else if (isModal()) {
395 if (active) {
396 return application.getTheme().getColor("twindow.border.modal");
397 } else {
398 return application.getTheme().getColor("twindow.border.modal.inactive");
399 }
400 } else if (active) {
401 assert (!isModal());
402 return application.getTheme().getColor("twindow.border");
403 } else {
404 assert (!isModal());
405 return application.getTheme().getColor("twindow.border.inactive");
406 }
407 }
408
409 /**
410 * Retrieve the border line type.
411 *
412 * @return the border line type
413 */
414 protected final int getBorderType() {
415 if (!isModal()
416 && (inWindowMove || inWindowResize || inKeyboardResize)
417 ) {
418 assert (active);
419 return 1;
420 } else if (isModal() && inWindowMove) {
421 assert (active);
422 return 1;
423 } else if (isModal()) {
424 if (active) {
425 return 2;
426 } else {
427 return 1;
428 }
429 } else if (active) {
430 return 2;
431 } else {
432 return 1;
433 }
434 }
435
436 /**
437 * Subclasses should override this method to cleanup resources. This is
438 * called by application.closeWindow().
439 */
440 public void onClose() {
441 // Default: do nothing
442 }
443
444 /**
445 * Called by TApplication.drawChildren() to render on screen.
446 */
447 @Override
448 public void draw() {
449 // Draw the box and background first.
450 CellAttributes border = getBorder();
451 CellAttributes background = getBackground();
452 int borderType = getBorderType();
453
454 getScreen().drawBox(0, 0, width, height, border,
455 background, borderType, true);
456
457 // Draw the title
458 int titleLeft = (width - title.length() - 2) / 2;
459 putCharXY(titleLeft, 0, ' ', border);
460 putStrXY(titleLeft + 1, 0, title);
461 putCharXY(titleLeft + title.length() + 1, 0, ' ', border);
462
463 if (active) {
464
465 // Draw the close button
466 putCharXY(2, 0, '[', border);
467 putCharXY(4, 0, ']', border);
468 if (mouseOnClose() && mouse.getMouse1()) {
469 putCharXY(3, 0, GraphicsChars.CP437[0x0F],
470 !isModal()
471 ? application.getTheme().getColor("twindow.border.windowmove")
472 : application.getTheme().getColor("twindow.border.modal.windowmove"));
473 } else {
474 putCharXY(3, 0, GraphicsChars.CP437[0xFE],
475 !isModal()
476 ? application.getTheme().getColor("twindow.border.windowmove")
477 : application.getTheme().getColor("twindow.border.modal.windowmove"));
478 }
479
480 // Draw the maximize button
481 if (!isModal()) {
482
483 putCharXY(width - 5, 0, '[', border);
484 putCharXY(width - 3, 0, ']', border);
485 if (mouseOnMaximize() && mouse.getMouse1()) {
486 putCharXY(width - 4, 0, GraphicsChars.CP437[0x0F],
487 application.getTheme().getColor("twindow.border.windowmove"));
488 } else {
489 if (maximized) {
490 putCharXY(width - 4, 0, GraphicsChars.CP437[0x12],
491 application.getTheme().getColor("twindow.border.windowmove"));
492 } else {
493 putCharXY(width - 4, 0, GraphicsChars.UPARROW,
494 application.getTheme().getColor("twindow.border.windowmove"));
495 }
496 }
497
498 // Draw the resize corner
499 if ((flags & RESIZABLE) != 0) {
500 putCharXY(width - 2, height - 1, GraphicsChars.SINGLE_BAR,
501 application.getTheme().getColor("twindow.border.windowmove"));
502 putCharXY(width - 1, height - 1, GraphicsChars.LRCORNER,
503 application.getTheme().getColor("twindow.border.windowmove"));
504 }
505 }
506 }
507 }
508
509 /**
510 * Handle mouse button presses.
511 *
512 * @param mouse mouse button event
513 */
514 @Override
515 public void onMouseDown(final TMouseEvent mouse) {
516 this.mouse = mouse;
517 application.setRepaint();
518
519 inKeyboardResize = false;
520
521 if ((mouse.getAbsoluteY() == y)
522 && mouse.getMouse1()
523 && (x <= mouse.getAbsoluteX())
524 && (mouse.getAbsoluteX() < x + width)
525 && !mouseOnClose()
526 && !mouseOnMaximize()
527 ) {
528 // Begin moving window
529 inWindowMove = true;
530 moveWindowMouseX = mouse.getAbsoluteX();
531 moveWindowMouseY = mouse.getAbsoluteY();
532 oldWindowX = x;
533 oldWindowY = y;
534 if (maximized) {
535 maximized = false;
536 }
537 return;
538 }
539 if (mouseOnResize()) {
540 // Begin window resize
541 inWindowResize = true;
542 moveWindowMouseX = mouse.getAbsoluteX();
543 moveWindowMouseY = mouse.getAbsoluteY();
544 resizeWindowWidth = width;
545 resizeWindowHeight = height;
546 if (maximized) {
547 maximized = false;
548 }
549 return;
550 }
551
552 // I didn't take it, pass it on to my children
553 super.onMouseDown(mouse);
554 }
555
556 /**
557 * Maximize window.
558 */
559 private void maximize() {
560 restoreWindowWidth = width;
561 restoreWindowHeight = height;
562 restoreWindowX = x;
563 restoreWindowY = y;
564 width = getScreen().getWidth();
565 height = application.getDesktopBottom() - 1;
566 x = 0;
567 y = 1;
568 maximized = true;
569 }
570
571 /**
572 * Restote (unmaximize) window.
573 */
574 private void restore() {
575 width = restoreWindowWidth;
576 height = restoreWindowHeight;
577 x = restoreWindowX;
578 y = restoreWindowY;
579 maximized = false;
580 }
581
582 /**
583 * Handle mouse button releases.
584 *
585 * @param mouse mouse button release event
586 */
587 @Override
588 public void onMouseUp(final TMouseEvent mouse) {
589 this.mouse = mouse;
590 application.setRepaint();
591
592 if ((inWindowMove) && (mouse.getMouse1())) {
593 // Stop moving window
594 inWindowMove = false;
595 return;
596 }
597
598 if ((inWindowResize) && (mouse.getMouse1())) {
599 // Stop resizing window
600 inWindowResize = false;
601 return;
602 }
603
604 if (mouse.getMouse1() && mouseOnClose()) {
605 // Close window
606 application.closeWindow(this);
607 return;
608 }
609
610 if ((mouse.getAbsoluteY() == y) && mouse.getMouse1()
611 && mouseOnMaximize()) {
612 if (maximized) {
613 // Restore
614 restore();
615 } else {
616 // Maximize
617 maximize();
618 }
619 // Pass a resize event to my children
620 onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, width, height));
621 return;
622 }
623
624 // I didn't take it, pass it on to my children
625 super.onMouseUp(mouse);
626 }
627
628 /**
629 * Handle mouse movements.
630 *
631 * @param mouse mouse motion event
632 */
633 @Override
634 public void onMouseMotion(final TMouseEvent mouse) {
635 this.mouse = mouse;
636 application.setRepaint();
637
638 if (inWindowMove) {
639 // Move window over
640 x = oldWindowX + (mouse.getAbsoluteX() - moveWindowMouseX);
641 y = oldWindowY + (mouse.getAbsoluteY() - moveWindowMouseY);
642 // Don't cover up the menu bar
643 if (y < application.getDesktopTop()) {
644 y = application.getDesktopTop();
645 }
646 return;
647 }
648
649 if (inWindowResize) {
650 // Move window over
651 width = resizeWindowWidth + (mouse.getAbsoluteX() - moveWindowMouseX);
652 height = resizeWindowHeight + (mouse.getAbsoluteY() - moveWindowMouseY);
653 if (x + width > getScreen().getWidth()) {
654 width = getScreen().getWidth() - x;
655 }
656 if (y + height > application.getDesktopBottom()) {
657 y = application.getDesktopBottom() - height + 1;
658 }
659 // Don't cover up the menu bar
660 if (y < application.getDesktopTop()) {
661 y = application.getDesktopTop();
662 }
663
664 // Keep within min/max bounds
665 if (width < minimumWindowWidth) {
666 width = minimumWindowWidth;
667 inWindowResize = false;
668 }
669 if (height < minimumWindowHeight) {
670 height = minimumWindowHeight;
671 inWindowResize = false;
672 }
673 if ((maximumWindowWidth > 0) && (width > maximumWindowWidth)) {
674 width = maximumWindowWidth;
675 inWindowResize = false;
676 }
677 if ((maximumWindowHeight > 0) && (height > maximumWindowHeight)) {
678 height = maximumWindowHeight;
679 inWindowResize = false;
680 }
681
682 // Pass a resize event to my children
683 onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, width, height));
684 return;
685 }
686
687 // I didn't take it, pass it on to my children
688 super.onMouseMotion(mouse);
689 }
690
691 /**
692 * Handle keystrokes.
693 *
694 * @param keypress keystroke event
695 */
696 @Override
697 public void onKeypress(final TKeypressEvent keypress) {
698
699 if (inKeyboardResize) {
700
701 // ESC - Exit size/move
702 if (keypress.equals(kbEsc)) {
703 inKeyboardResize = false;
704 }
705
706 if (keypress.equals(kbLeft)) {
707 if (x > 0) {
708 x--;
709 }
710 }
711 if (keypress.equals(kbRight)) {
712 if (x < getScreen().getWidth() - 1) {
713 x++;
714 }
715 }
716 if (keypress.equals(kbDown)) {
717 if (y < application.getDesktopBottom() - 1) {
718 y++;
719 }
720 }
721 if (keypress.equals(kbUp)) {
722 if (y > 1) {
723 y--;
724 }
725 }
726 if (keypress.equals(kbShiftLeft)) {
727 if (width > minimumWindowWidth) {
728 width--;
729 }
730 }
731 if (keypress.equals(kbShiftRight)) {
732 if (width < maximumWindowWidth) {
733 width++;
734 }
735 }
736 if (keypress.equals(kbShiftUp)) {
737 if (height > minimumWindowHeight) {
738 height--;
739 }
740 }
741 if (keypress.equals(kbShiftDown)) {
742 if (height < maximumWindowHeight) {
743 height++;
744 }
745 }
746
747 return;
748 }
749
750 // These keystrokes will typically not be seen unless a subclass
751 // overrides onMenu() due to how TApplication dispatches
752 // accelerators.
753
754 // Ctrl-W - close window
755 if (keypress.equals(kbCtrlW)) {
756 application.closeWindow(this);
757 return;
758 }
759
760 // F6 - behave like Alt-TAB
761 if (keypress.equals(kbF6)) {
762 application.switchWindow(true);
763 return;
764 }
765
766 // Shift-F6 - behave like Shift-Alt-TAB
767 if (keypress.equals(kbShiftF6)) {
768 application.switchWindow(false);
769 return;
770 }
771
772 // F5 - zoom
773 if (keypress.equals(kbF5)) {
774 if (maximized) {
775 restore();
776 } else {
777 maximize();
778 }
779 }
780
781 // Ctrl-F5 - size/move
782 if (keypress.equals(kbCtrlF5)) {
783 inKeyboardResize = !inKeyboardResize;
784 }
785
786 // I didn't take it, pass it on to my children
787 super.onKeypress(keypress);
788 }
789
790 /**
791 * Handle posted command events.
792 *
793 * @param command command event
794 */
795 @Override
796 public void onCommand(final TCommandEvent command) {
797
798 // These commands will typically not be seen unless a subclass
799 // overrides onMenu() due to how TApplication dispatches
800 // accelerators.
801
802 if (command.equals(cmWindowClose)) {
803 application.closeWindow(this);
804 return;
805 }
806
807 if (command.equals(cmWindowNext)) {
808 application.switchWindow(true);
809 return;
810 }
811
812 if (command.equals(cmWindowPrevious)) {
813 application.switchWindow(false);
814 return;
815 }
816
817 if (command.equals(cmWindowMove)) {
818 inKeyboardResize = true;
819 return;
820 }
821
822 if (command.equals(cmWindowZoom)) {
823 if (maximized) {
824 restore();
825 } else {
826 maximize();
827 }
828 }
829
830 // I didn't take it, pass it on to my children
831 super.onCommand(command);
832 }
833
834 /**
835 * Handle posted menu events.
836 *
837 * @param menu menu event
838 */
839 @Override
840 public void onMenu(final TMenuEvent menu) {
841 if (menu.getId() == TMenu.MID_WINDOW_CLOSE) {
842 application.closeWindow(this);
843 return;
844 }
845
846 if (menu.getId() == TMenu.MID_WINDOW_NEXT) {
847 application.switchWindow(true);
848 return;
849 }
850
851 if (menu.getId() == TMenu.MID_WINDOW_PREVIOUS) {
852 application.switchWindow(false);
853 return;
854 }
855
856 if (menu.getId() == TMenu.MID_WINDOW_MOVE) {
857 inKeyboardResize = true;
858 return;
859 }
860
861 if (menu.getId() == TMenu.MID_WINDOW_ZOOM) {
862 if (maximized) {
863 restore();
864 } else {
865 maximize();
866 }
867 return;
868 }
869
870 // I didn't take it, pass it on to my children
871 super.onMenu(menu);
872 }
873
874 // ------------------------------------------------------------------------
875 // Passthru for Screen functions ------------------------------------------
876 // ------------------------------------------------------------------------
877
878 /**
879 * Get the attributes at one location.
880 *
881 * @param x column coordinate. 0 is the left-most column.
882 * @param y row coordinate. 0 is the top-most row.
883 * @return attributes at (x, y)
884 */
885 public final CellAttributes getAttrXY(final int x, final int y) {
886 return getScreen().getAttrXY(x, y);
887 }
888
889 /**
890 * Set the attributes at one location.
891 *
892 * @param x column coordinate. 0 is the left-most column.
893 * @param y row coordinate. 0 is the top-most row.
894 * @param attr attributes to use (bold, foreColor, backColor)
895 */
896 public final void putAttrXY(final int x, final int y,
897 final CellAttributes attr) {
898
899 getScreen().putAttrXY(x, y, attr);
900 }
901
902 /**
903 * Set the attributes at one location.
904 *
905 * @param x column coordinate. 0 is the left-most column.
906 * @param y row coordinate. 0 is the top-most row.
907 * @param attr attributes to use (bold, foreColor, backColor)
908 * @param clip if true, honor clipping/offset
909 */
910 public final void putAttrXY(final int x, final int y,
911 final CellAttributes attr, final boolean clip) {
912
913 getScreen().putAttrXY(x, y, attr, clip);
914 }
915
916 /**
917 * Fill the entire screen with one character with attributes.
918 *
919 * @param ch character to draw
920 * @param attr attributes to use (bold, foreColor, backColor)
921 */
922 public final void putAll(final char ch, final CellAttributes attr) {
923 getScreen().putAll(ch, attr);
924 }
925
926 /**
927 * Render one character with attributes.
928 *
929 * @param x column coordinate. 0 is the left-most column.
930 * @param y row coordinate. 0 is the top-most row.
931 * @param ch character + attributes to draw
932 */
933 public final void putCharXY(final int x, final int y, final Cell ch) {
934 getScreen().putCharXY(x, y, ch);
935 }
936
937 /**
938 * Render one character with attributes.
939 *
940 * @param x column coordinate. 0 is the left-most column.
941 * @param y row coordinate. 0 is the top-most row.
942 * @param ch character to draw
943 * @param attr attributes to use (bold, foreColor, backColor)
944 */
945 public final void putCharXY(final int x, final int y, final char ch,
946 final CellAttributes attr) {
947
948 getScreen().putCharXY(x, y, ch, attr);
949 }
950
951 /**
952 * Render one character without changing the underlying attributes.
953 *
954 * @param x column coordinate. 0 is the left-most column.
955 * @param y row coordinate. 0 is the top-most row.
956 * @param ch character to draw
957 */
958 public final void putCharXY(final int x, final int y, final char ch) {
959 getScreen().putCharXY(x, y, ch);
960 }
961
962 /**
963 * Render a string. Does not wrap if the string exceeds the line.
964 *
965 * @param x column coordinate. 0 is the left-most column.
966 * @param y row coordinate. 0 is the top-most row.
967 * @param str string to draw
968 * @param attr attributes to use (bold, foreColor, backColor)
969 */
970 public final void putStrXY(final int x, final int y, final String str,
971 final CellAttributes attr) {
972
973 getScreen().putStrXY(x, y, str, attr);
974 }
975
976 /**
977 * Render a string without changing the underlying attribute. Does not
978 * wrap if the string exceeds the line.
979 *
980 * @param x column coordinate. 0 is the left-most column.
981 * @param y row coordinate. 0 is the top-most row.
982 * @param str string to draw
983 */
984 public final void putStrXY(final int x, final int y, final String str) {
985 getScreen().putStrXY(x, y, str);
986 }
987
988 /**
989 * Draw a vertical line from (x, y) to (x, y + n).
990 *
991 * @param x column coordinate. 0 is the left-most column.
992 * @param y row coordinate. 0 is the top-most row.
993 * @param n number of characters to draw
994 * @param ch character to draw
995 * @param attr attributes to use (bold, foreColor, backColor)
996 */
997 public final void vLineXY(final int x, final int y, final int n,
998 final char ch, final CellAttributes attr) {
999
1000 getScreen().vLineXY(x, y, n, ch, attr);
1001 }
1002
1003 /**
1004 * Draw a horizontal line from (x, y) to (x + n, y).
1005 *
1006 * @param x column coordinate. 0 is the left-most column.
1007 * @param y row coordinate. 0 is the top-most row.
1008 * @param n number of characters to draw
1009 * @param ch character to draw
1010 * @param attr attributes to use (bold, foreColor, backColor)
1011 */
1012 public final void hLineXY(final int x, final int y, final int n,
1013 final char ch, final CellAttributes attr) {
1014
1015 getScreen().hLineXY(x, y, n, ch, attr);
1016 }
1017
1018
1019}