Stroika Library 3.0d18
 
Loading...
Searching...
No Matches
LedLineItMainFrame.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4
5#include "Stroika/Foundation/StroikaPreComp.h"
6
7#include <cstdio>
8
10
11#include "FontMenu.h"
12#include "LedLineItView.h"
13#include "Resource.h"
14
15#include "LedLineItMainFrame.h"
16
17using namespace Stroika::Foundation;
19using namespace Stroika::Frameworks::Led;
20
21inline LedLineItView* GetActiveLedItView ()
22{
23 CMDIFrameWnd* mainFrame = dynamic_cast<CMDIFrameWnd*> (::AfxGetMainWnd ());
24 if (mainFrame != NULL) {
25 CMDIChildWnd* childFrame = mainFrame->MDIGetActive ();
26 if (childFrame != NULL) {
27 return dynamic_cast<LedLineItView*> (childFrame->GetActiveView ());
28 }
29 }
30 return NULL;
31}
32
33/*
34 ********************************************************************************
35 ***************** LedLineItMainFrame::StatusBar::GotoEdit **********************
36 ********************************************************************************
37 */
38using StatusBar = LedLineItMainFrame::StatusBar;
39using GotoEdit = StatusBar::GotoEdit;
40BEGIN_MESSAGE_MAP (GotoEdit, CEdit)
41ON_WM_GETDLGCODE ()
42ON_WM_KEYDOWN ()
43END_MESSAGE_MAP ()
44
45UINT GotoEdit::OnGetDlgCode ()
46{
47 return CEdit::OnGetDlgCode () | DLGC_WANTALLKEYS;
48}
49
50void GotoEdit::OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags)
51{
52 if (nChar == VK_TAB or nChar == VK_RETURN) {
53 LedLineItView* v = GetActiveLedItView ();
54 if (v != NULL) {
55 v->SetFocus ();
56 }
57 }
58 else {
59 CEdit::OnKeyDown (nChar, nRepCnt, nFlags);
60 }
61}
62
63/*
64 ********************************************************************************
65 ************************ LedLineItMainFrame::StatusBar *************************
66 ********************************************************************************
67 */
68const int kMagicGotoWidgetID = 9991;
69using StatusBar = LedLineItMainFrame::StatusBar;
70BEGIN_MESSAGE_MAP (StatusBar, CStatusBar)
71ON_EN_CHANGE (kMagicGotoWidgetID, OnMagicEdited)
72ON_EN_KILLFOCUS (kMagicGotoWidgetID, OnMagicLoseFocus)
73ON_WM_LBUTTONDOWN ()
74END_MESSAGE_MAP ()
75void StatusBar::OnLButtonDown (UINT nFlags, CPoint oPoint)
76{
77 CRect r;
78 GetItemRect (1, &r);
79 if (r.PtInRect (oPoint)) {
80 TrackInGotoLineField ();
81 }
82 else {
83 inherited::OnLButtonDown (nFlags, oPoint);
84 }
85}
86
87void StatusBar::TrackInGotoLineField ()
88{
89 CRect r;
90 GetItemRect (1, &r);
91 // make sure plenty wide..
92 r.right = max (r.right, r.left + 50);
93 if (fGotoEdit.m_hWnd == 0) {
94 Verify (fGotoEdit.Create (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | ES_NUMBER | ES_AUTOHSCROLL | ES_RIGHT, r,
95 this, kMagicGotoWidgetID));
96 }
97 fGotoEdit.SetFont (GetFont ());
98 fGotoEdit.SetWindowText (GetPaneText (1));
99 fGotoEdit.SetSel (0, -1);
100 fGotoEdit.SetFocus ();
101}
102
103void StatusBar::OnMagicEdited ()
104{
105 DISABLE_COMPILER_MSC_WARNING_START (4996)
106 CString wt;
107 fGotoEdit.GetWindowText (wt);
108 int lines = 0;
109 if (::_stscanf (wt, _T ("%d"), &lines) == 1) {
110 LedLineItView* v = GetActiveLedItView ();
111 if (v != NULL) {
112 v->SetCurUserLine (lines);
113 }
114 }
115 else {
116 Led_BeepNotify ();
117 }
118 DISABLE_COMPILER_MSC_WARNING_END (4996)
119}
120
121void StatusBar::OnMagicLoseFocus ()
122{
123 Verify (fGotoEdit.DestroyWindow ());
124}
125
126/*
127 ********************************************************************************
128 ******************************** LedLineItMainFrame ****************************
129 ********************************************************************************
130 */
131IMPLEMENT_DYNCREATE (LedLineItMainFrame, CMDIFrameWnd)
132BEGIN_MESSAGE_MAP (LedLineItMainFrame, LedLineItMainFrame::inherited)
133ON_WM_CREATE ()
134ON_WM_INITMENUPOPUP ()
135ON_COMMAND (ID_HELP_FINDER, OnHelpFinder)
136ON_COMMAND (ID_HELP, OnHelp)
137ON_COMMAND (ID_CONTEXT_HELP, OnContextHelp)
138ON_COMMAND (ID_DEFAULT_HELP, OnHelpFinder)
139ON_UPDATE_COMMAND_UI (ID_LINENUMBER, OnUpdateLineIndicator)
140ON_COMMAND (kCloseWindowCmdID, OnCloseWindowCommand)
141ON_COMMAND (kCloseAllWindowsCmdID, OnCloseAllWindowsCommand)
142END_MESSAGE_MAP ()
143
144bool LedLineItMainFrame::GetStatusBarShown () const
145{
146 return !!fStatusBar.IsWindowVisible ();
147}
148
149void LedLineItMainFrame::SetStatusBarShown (bool shown)
150{
151 fStatusBar.ShowWindow (shown ? SW_SHOWNORMAL : SW_HIDE);
152}
153
154void LedLineItMainFrame::TrackInGotoLineField ()
155{
156 Require (GetStatusBarShown ());
157 fStatusBar.TrackInGotoLineField ();
158}
159
160int LedLineItMainFrame::OnCreate (LPCREATESTRUCT lpCreateStruct)
161{
162 RequireNotNull (lpCreateStruct);
163
164 if (inherited::OnCreate (lpCreateStruct) == -1) {
165 return -1;
166 }
167
168 Led_Size desiredSize =
169 Led_Size (Led_CvtScreenPixelsFromTWIPSV (TWIPS (1440 * 11)), Led_CvtScreenPixelsFromTWIPSH (TWIPS (static_cast<long> (1440 * 8.5))));
170 Led_Rect newBounds = Led_Rect (lpCreateStruct->y, lpCreateStruct->x, desiredSize.v, desiredSize.h);
171 newBounds = EnsureRectOnScreen (newBounds);
172 MoveWindow (CRect (AsRECT (newBounds)));
173
174 CMenu* menuBar = GetMenu ();
175 AssertNotNull (menuBar);
176#if qSupportSyntaxColoring
177 FixupFontMenu (menuBar->GetSubMenu (2)->GetSubMenu (7));
178#else
179 FixupFontMenu (menuBar->GetSubMenu (2)->GetSubMenu (6));
180#endif
181
182 if (!fToolBar.Create (this) || !fToolBar.LoadToolBar (IDR_MAINFRAME)) {
183 TRACE0 ("Failed to create toolbar\n");
184 return -1; // fail to create
185 }
186
187 static UINT indicators[] = {
188 ID_SEPARATOR, // status line indicator
189 ID_LINENUMBER,
190 };
191 if (!fStatusBar.Create (this) || !fStatusBar.SetIndicators (indicators, sizeof (indicators) / sizeof (UINT))) {
192 TRACE0 ("Failed to create status bar\n");
193 return -1; // fail to create
194 }
195
196 // TODO: Remove this if you don't want tool tips or a resizeable toolbar
197 fToolBar.SetBarStyle (fToolBar.GetBarStyle () | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
198
199 // TODO: Delete these three lines if you don't want the toolbar to
200 // be dockable
201 fToolBar.EnableDocking (CBRS_ALIGN_ANY);
202 EnableDocking (CBRS_ALIGN_ANY);
203 DockControlBar (&fToolBar);
204
205 return 0;
206}
207
208void LedLineItMainFrame::OnUpdateLineIndicator (CCmdUI* pCmdUI)
209{
210 RequireNotNull (pCmdUI);
211
212 TCHAR buf[1024];
213 {
214 LedLineItView* v = GetActiveLedItView ();
215 if (v == NULL) {
216 // can happen, for example, during PrintPreview
217 Characters::CString::Copy (buf, Memory::NEltsOf (buf), _T ("N/A"));
218 }
219 else {
220 Characters::CString::Copy (buf, Memory::NEltsOf (buf),
221 Characters::Format ("{}"_f, static_cast<int> (v->GetCurUserLine ())).AsSDKString ().c_str ());
222 }
223 }
224 pCmdUI->SetText (buf);
225 pCmdUI->Enable ();
226
227 // dynamicly size the indicator
228 HFONT hFont = (HFONT)fStatusBar.SendMessage (WM_GETFONT);
229 CClientDC dcScreen (NULL);
230 HGDIOBJ oldFont = NULL;
231 if (hFont != NULL) {
232 oldFont = dcScreen.SelectObject (hFont);
233 }
234 UINT nID = 0;
235 UINT nStyle = 0;
236 int cxWidth = 0;
237 fStatusBar.GetPaneInfo (1, nID, nStyle, cxWidth);
238 cxWidth = max (dcScreen.GetTextExtent (buf).cx, 20l);
239 fStatusBar.SetPaneInfo (1, nID, nStyle, cxWidth);
240 if (oldFont != NULL) {
241 (void)dcScreen.SelectObject (oldFont);
242 }
243}
244
245static bool IsPopupInOwningMenu (HMENU popup, HMENU potentialOwner)
246{
247 RequireNotNull (popup);
248 if (potentialOwner != NULL) {
249 int nIndexMax = ::GetMenuItemCount (potentialOwner);
250 for (int nIndex = 0; nIndex < nIndexMax; ++nIndex) {
251 HMENU itsSubMenu = ::GetSubMenu (potentialOwner, nIndex);
252 if (itsSubMenu == popup) {
253 return true;
254 }
255 else if (itsSubMenu != NULL) {
256 // See if its inside sub menu.
257 if (IsPopupInOwningMenu (popup, itsSubMenu)) {
258 return true;
259 }
260 }
261 }
262 }
263 return false;
264}
265void LedLineItMainFrame::OnInitMenuPopup (CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
266{
267 // Disable inappropriate commands (done by inherited version)
268 inherited::OnInitMenuPopup (pPopupMenu, nIndex, bSysMenu);
269
270 // Check if this is our context menu, or the systemmenu, or one of the
271 // applications main window menus.
272 // We only do our remove-disabled hack for the context menu...
273 if (bSysMenu or IsPopupInOwningMenu (pPopupMenu->m_hMenu, ::GetMenu (m_hWnd))) {
274 return;
275 }
276
277 // Remove disabled menu items from the popup (to save space).
278 // Remove consecutive (or leading) separators as useless.
279 CCmdUI state;
280 state.m_pSubMenu = NULL;
281 state.m_pMenu = pPopupMenu;
282 Assert (state.m_pOther == NULL);
283 Assert (state.m_pParentMenu == NULL);
284
285 state.m_nIndexMax = pPopupMenu->GetMenuItemCount ();
286
287 // Remove disabled items (and unneeded separators)
288 {
289 bool prevItemSep = true; // prevent initial separators
290 for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;) {
291 state.m_nID = pPopupMenu->GetMenuItemID (state.m_nIndex);
292 if (state.m_nID == 0 and prevItemSep) {
293 pPopupMenu->RemoveMenu (state.m_nIndex, MF_BYPOSITION);
294 --state.m_nIndexMax;
295 continue;
296 }
297 if (state.m_nID != 0) {
298 MENUITEMINFO mInfo;
299 memset (&mInfo, 0, sizeof (mInfo));
300 mInfo.cbSize = sizeof (mInfo);
301 mInfo.fMask = MIIM_STATE;
302 Verify (::GetMenuItemInfo (pPopupMenu->GetSafeHmenu (), state.m_nIndex, true, &mInfo));
303 if (mInfo.fState & MFS_DISABLED) {
304 pPopupMenu->RemoveMenu (state.m_nIndex, MF_BYPOSITION);
305 --state.m_nIndexMax;
306 continue;
307 }
308 }
309 prevItemSep = bool (state.m_nID == 0);
310 ++state.m_nIndex;
311 }
312 // if LAST item is a separator - remove THAT
313 if (prevItemSep) {
314 pPopupMenu->RemoveMenu (state.m_nIndexMax - 1, MF_BYPOSITION);
315 }
316 }
317}
318
319void LedLineItMainFrame::OnCloseWindowCommand ()
320{
321 CMDIChildWnd* childFrame = MDIGetActive ();
322 if (childFrame != NULL) {
323 childFrame->SendMessage (WM_SYSCOMMAND, SC_CLOSE);
324 }
325}
326
327void LedLineItMainFrame::OnCloseAllWindowsCommand ()
328{
329 CMDIChildWnd* childFrame = NULL;
330 while ((childFrame = MDIGetActive ()) != NULL) {
331 CDocument* pDocument = childFrame->GetActiveDocument ();
332 if (pDocument != NULL) {
333 if (pDocument->SaveModified ()) {
334 pDocument->OnCloseDocument ();
335 continue;
336 }
337 else {
338 return;
339 }
340 }
341 childFrame->SendMessage (WM_SYSCOMMAND, SC_CLOSE);
342 }
343}
#define AssertNotNull(p)
Definition Assertions.h:333
#define RequireNotNull(p)
Definition Assertions.h:347
#define Verify(c)
Definition Assertions.h:419
Create a format-string (see std::wformat_string or Stroika FormatString, or python 'f' strings.