1 // This file is part of the utui library, a terminal UI framework.
3 // Copyright (C) 2006 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
12 //----------------------------------------------------------------------
14 long CRootWindow::s_IdleTimeout
= 200000;
16 //----------------------------------------------------------------------
18 /// Singleton instance reference.
19 /*static*/ CRootWindow
& CRootWindow::Instance (void)
25 /// Default constructor.
26 CRootWindow::CRootWindow (void)
35 /// Virtual destructor.
36 CRootWindow::~CRootWindow (void)
38 CRootWindow::OnDestroy(); // This is for abnormal exit.
41 /// Writes the window GC onto the terminal.
42 void CRootWindow::Flush (void)
45 bool bCursorOff
= (m_ScreenPos
== pos_CaretOff
);
46 bool bWillBeOff
= (CaretPos() == pos_CaretOff
);
47 if (rgc
.MakeDiffFrom (m_Screen
)) {
48 // gc now has only new stuff, the rest is zeroed out, and isn't drawn.
49 cout
<< m_TI
.HideCursor();
51 cout
<< m_TI
.Image (0, 0, rgc
.Width(), rgc
.Height(), rgc
.Canvas().begin());
52 m_Screen
.Image (rgc
); // Now apply the same diff to the screen cache.
53 rgc
.Image (m_Screen
); // ... and copy it back for a fresh start.
55 if (!bCursorOff
&& bWillBeOff
) {
56 cout
<< m_TI
.HideCursor();
59 bCursorOff
|= (m_ScreenPos
!= CaretPos());
60 if (bCursorOff
& ((m_ScreenPos
= CaretPos()) != pos_CaretOff
)) {
61 cout
<< m_TI
.MoveTo (CaretPos()[0], CaretPos()[1]);
62 cout
<< m_TI
.ShowCursor();
68 /// Initializes the output device.
69 void CRootWindow::OnCreate (void)
73 m_TI
.Load(); // The terminfo database
74 m_Kb
.Open (m_TI
); // Put the keyboard in UI mode
75 cout
<< m_TI
.HideCursor(); // No cursor in UI mode
76 cout
<< m_TI
.Clear(); // Screen is clear in the beginning
78 OnResize (Rect (0, 0, m_TI
.Width(), m_TI
.Height()));
81 /// Deinitializes the output device.
82 void CRootWindow::OnDestroy (void)
84 if (!m_Kb
.IsInUIMode()) // To not close twice (from dtor)
86 m_Kb
.Close(); // Coming back to tty mode
87 cout
<< m_TI
.Clear(); // Clear the screen
88 cout
<< m_TI
.ShowCursor(); // No cursor in UI mode
90 CWindow::OnDestroy(); // OnDestroy errors can now be printed to tty
93 /// Sets the window rect to \p wr.
94 void CRootWindow::OnResize (rcrect_t wr
)
96 CWindow::OnResize (wr
);
97 m_Screen
.Resize (wr
.Width(), wr
.Height());
98 // Root window children are placed wherever they want to be.
100 foreach (winvec_t::iterator
, i
, Children()) {
101 (*i
)->SizeHints (cwr
= wr
);
102 (*i
)->OnResize (cwr
);
106 /// Called when a root-level exception is caught.
107 void CRootWindow::OnError (exception
& e
)
109 // Print the exception to string
112 // Delete all windows to avoid further errors.
114 // Display the error in a box.
115 MessageBox (os
.str());
116 // If any of the above throws, Terminate gets called with a message and a dtor call.
119 /// Checks for keypresses and other events.
120 wchar_t CRootWindow::GetKey (void) const
122 wchar_t key
= m_Kb
.GetKey (false);
124 m_Kb
.WaitForKeyData (s_IdleTimeout
);
128 /// The main event loop.
129 int CRootWindow::Run (void)
132 while (!Flag (f_Closed
) & !Children().empty()) {
136 if ((key
= GetKey()))
144 //----------------------------------------------------------------------
146 int CRootWindow::s_ModalStack
[15];
147 unsigned int CRootWindow::s_ModalDepth
= 1;
149 /// Extracts status information from the child window before it dies.
150 void CRootWindow::OnChildClose (uoff_t i
)
152 CWindow::OnChildClose (i
);
153 s_ModalStack
[s_ModalDepth
-1] = CW(i
).Status();
156 /// Runs \p pw as a modal dialog. \p pw is deleted before returning.
157 int CRootWindow::RunModal (CDialog
* pw
)
159 assert (s_ModalDepth
< VectorSize(s_ModalStack
) - 1 && "Too many nested modal dialog calls. Either use fewer or increase s_ModalStack size in rootwin.cc");
160 s_ModalStack
[s_ModalDepth
++] = 0;
161 uint32_t ci
= Children().size(), oldFocus (Focus());
164 while ((ci
< Children().size()) && Children()[ci
] == pw
) {
168 if ((key
= GetKey()))
172 if (oldFocus
>= Children().size())
173 oldFocus
= GetNextFocus(-1);
175 return (s_ModalStack
[--s_ModalDepth
]);