experimental 24-bit image protocol
[nikiroo-utils.git] / examples / JexerTilingWindowManager2.java
CommitLineData
2bc32111
KL
1import jexer.TAction;
2import jexer.TApplication;
3import jexer.TDesktop;
4import jexer.TTerminalWidget;
469c2b3c 5import jexer.TSplitPane;
2bc32111 6import jexer.TWidget;
2bc32111 7import jexer.event.TMenuEvent;
2bc32111
KL
8import jexer.menu.TMenu;
9
10/**
11 * Implements a simple tiling window manager. A terminal widget is added to
12 * the desktop, which can be split horizontally or vertically. A close
13 * action is provided to each window to remove the split when its shell
14 * exits.
15 *
16 * This example shows what can be done with minimal changes to stock Jexer
17 * widgets.
18 */
19public class JexerTilingWindowManager2 extends TApplication {
20
21 /**
22 * Menu item: split the terminal vertically.
23 */
24 private static final int MENU_SPLIT_VERTICAL = 2000;
25
26 /**
27 * Menu item: split the terminal horizontally.
28 */
29 private static final int MENU_SPLIT_HORIZONTAL = 2001;
955c55b7
KL
30 /**
31 * Menu item: recreate the root terminal.
32 */
33 private static final int MENU_RESPAWN_ROOT = 2002;
2bc32111
KL
34
35 /**
36 * Handle to the root widget.
37 */
38 private TWidget root = null;
469c2b3c 39
2bc32111
KL
40 /**
41 * Main entry point.
42 */
43 public static void main(String [] args) throws Exception {
44 // For this application, we must use ptypipe so that the terminal
45 // shells can be aware of their size.
46 System.setProperty("jexer.TTerminal.ptypipe", "true");
47
48 // Let's also suppress the status line.
49 System.setProperty("jexer.hideStatusBar", "true");
50
51 JexerTilingWindowManager2 jtwm = new JexerTilingWindowManager2();
52 (new Thread(jtwm)).start();
53 }
54
55 /**
56 * Public constructor chooses the ECMA-48 / Xterm backend.
57 */
58 public JexerTilingWindowManager2() throws Exception {
9ad2ce4f 59 super(BackendType.XTERM);
2bc32111
KL
60
61 // The stock tool menu has items for redrawing the screen, opening
62 // images, and (when using the Swing backend) setting the font.
63 addToolMenu();
64
65 // We will have one menu containing a mix of new and stock commands
66 TMenu tileMenu = addMenu("&Tile");
67
68 // New commands for this example: split vertical and horizontal.
69 tileMenu.addItem(MENU_SPLIT_VERTICAL, "&Vertical Split");
70 tileMenu.addItem(MENU_SPLIT_HORIZONTAL, "&Horizontal Split");
955c55b7 71 tileMenu.addItem(MENU_RESPAWN_ROOT, "&Respawn Root Terminal");
2bc32111 72
9ad2ce4f
KL
73 // Stock commands: a new shell with resizable window, and exit
74 // program.
2bc32111 75 tileMenu.addSeparator();
9ad2ce4f 76 tileMenu.addItem(TMenu.MID_SHELL, "&New Windowed Terminal");
2bc32111
KL
77 tileMenu.addSeparator();
78 tileMenu.addDefaultItem(TMenu.MID_EXIT);
79
9ad2ce4f
KL
80 // TTerminalWidget can request the text-block mouse pointer be
81 // suppressed, but the default TDesktop will ignore it. Let's set a
82 // new TDesktop to pass that mouse pointer visibility option to
83 // TApplication.
84 setDesktop(new TDesktop(this) {
85 @Override
86 public boolean hasHiddenMouse() {
87 TWidget active = getActiveChild();
88 if (active instanceof TTerminalWidget) {
89 return ((TTerminalWidget) active).hasHiddenMouse();
90 }
91 return false;
92 }
93 });
94
2bc32111 95 // Spin up the root terminal
469c2b3c 96 createRootTerminal();
2bc32111
KL
97 }
98
99 /**
100 * Process menu events.
101 */
102 @Override
103 protected boolean onMenu(TMenuEvent event) {
955c55b7
KL
104 TWidget active = getDesktop().getActiveChild();
105 TSplitPane split = null;
106
107 switch (event.getId()) {
108 case MENU_RESPAWN_ROOT:
109 assert (root == null);
110 createRootTerminal();
111 return true;
112
113 case MENU_SPLIT_VERTICAL:
469c2b3c 114 if (root == null) {
90d87fca 115 assert (getDesktop().getActiveChild() == null);
469c2b3c
KL
116 createRootTerminal();
117 return true;
118 }
955c55b7 119 split = active.splitVertical(false, createTerminal());
469c2b3c
KL
120 if (active == root) {
121 root = split;
122 }
2bc32111 123 return true;
955c55b7
KL
124
125 case MENU_SPLIT_HORIZONTAL:
469c2b3c 126 if (root == null) {
90d87fca 127 assert (getDesktop().getActiveChild() == null);
469c2b3c
KL
128 createRootTerminal();
129 return true;
130 }
955c55b7 131 split = active.splitHorizontal(false, createTerminal());
90d87fca
KL
132 if (active == root) {
133 root = split;
134 }
2bc32111 135 return true;
955c55b7
KL
136
137 default:
138 return super.onMenu(event);
2bc32111
KL
139 }
140
2bc32111
KL
141 }
142
143 /**
469c2b3c 144 * Create the root terminal.
2bc32111 145 */
469c2b3c
KL
146 private void createRootTerminal() {
147 assert (root == null);
955c55b7
KL
148 disableMenuItem(MENU_RESPAWN_ROOT);
149 root = createTerminal();
150 }
151
152 /**
153 * Create a new terminal.
154 *
155 * @return the new terminal
156 */
157 private TWidget createTerminal() {
158 return new TTerminalWidget(getDesktop(), 0, 0,
469c2b3c
KL
159 getDesktop().getWidth(), getDesktop().getHeight(),
160 new TAction() {
161 public void DO() {
a524aa2e 162 if (source.getParent() instanceof TSplitPane) {
955c55b7
KL
163 ((TSplitPane) source.getParent()).removeSplit(source,
164 true);
165 } else {
166 source.getApplication().enableMenuItem(
167 MENU_RESPAWN_ROOT);
168 source.remove();
469c2b3c
KL
169 root = null;
170 }
171 }
172 });
2bc32111
KL
173 }
174
175}