1 // screen_flow_edit_dlg.cpp : implementation file
2 //
3 
4 #include "studiox_includes.h"
5 #include "screen_flow_edit_dlg.h"
6 
7 enum drag_modes {
8     DRAG_NONE = 0,
9     DRAG_TOP_LEFT,
10     DRAG_TOP,
11     DRAG_TOP_RIGHT,
12     DRAG_RIGHT,
13     DRAG_BOTTOM_RIGHT,
14     DRAG_BOTTOM,
15     DRAG_BOTTOM_LEFT,
16     DRAG_LEFT,
17     DRAG_ALL
18 };
19 
20 enum zoom_types{
21     TYPE_ZOOM_IN = 0,
22     TYPE_ZOOM_OUT,
23     TYPE_FIT_CONTENT
24 };
25 
26 enum ctrl_ids {
27     BTN_ID_FIT_CONTENT = 1024,
28     BTN_ID_ZOOM_IN,
29     BTN_ID_ZOOM_OUT,
30     BTN_ID_RUN_PROJECT,
31     ID_ZOOM_VALUE_LABLE,
32 };
33 
34 #define MIN_SCREEN_FLOW_EDIT_DLG_WIDTH  800
35 #define MIN_SCREEN_FLOW_EDIT_DLG_HEIGHT 400
36 
37 #define HDRAG_TIMER 1000
38 #define VDRAG_TIMER 1001
39 #define ANIMATION_INTERVAL 100
40 #define ANIMATION_SHIFT 5
41 
42 #define BUTTON_FRAME_HEIGHT 29
43 #define ICON_HEIGHT 22
44 #define ICON_WIDTH  30
45 #define MIN_SCREEN_BOX_SIZE 10
46 
47 #define ZOOM_IN_PUSHED     0x1
48 #define ZOOM_OUT_PUSHED    0x2
49 #define FIT_CONTENT_PUSHED 0x4
50 
51 #define SHIFTED 0x8000
52 
53 extern CString target_class_name;
54 
BEGIN_MESSAGE_MAP(screen_flow_button_frame,CWnd)55 BEGIN_MESSAGE_MAP(screen_flow_button_frame, CWnd)
56     ON_WM_ERASEBKGND()
57     ON_WM_CREATE()
58     ON_WM_SIZE()
59     ON_BN_CLICKED(BTN_ID_FIT_CONTENT, OnFitContent)
60     ON_BN_CLICKED(BTN_ID_ZOOM_OUT, OnZoomOut)
61     ON_BN_CLICKED(BTN_ID_ZOOM_IN, OnZoomIn)
62     ON_BN_CLICKED(BTN_ID_RUN_PROJECT, OnRunProject)
63     ON_WM_CTLCOLOR()
64 END_MESSAGE_MAP()
65 
66 ///////////////////////////////////////////////////////////////////////////////
67 screen_flow_button_frame::screen_flow_button_frame(screen_flow *flow, CWnd * pParent)
68 {
69     mpScreenFlow = flow;
70 }
71 
72 ///////////////////////////////////////////////////////////////////////////////
~screen_flow_button_frame()73 screen_flow_button_frame::~screen_flow_button_frame()
74 {
75 
76 }
77 
78 
79 ///////////////////////////////////////////////////////////////////////////////
OnCreate(LPCREATESTRUCT lpCreateStruct)80 int screen_flow_button_frame::OnCreate(LPCREATESTRUCT lpCreateStruct)
81 {
82     if (CWnd::OnCreate(lpCreateStruct) == -1)
83         return -1;
84 
85     // TODO:  Add your specialized creation code here
86     mFitContent.Create(_T(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW | MAX_TAB_STOPS, CRect(0, 0, 0, 0), this, BTN_ID_FIT_CONTENT);
87     mFitContent.LoadBitmaps(IDB_SCREEN_FLOW_FIT_CONTENT, IDB_SCREEN_FLOW_FIT_CONTENT_PRESSED);
88     SetControlAccessibleName(mFitContent.GetSafeHwnd(), _T("fit content"));
89 
90     mZoomOutButton.Create(_T(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW | MAX_TAB_STOPS, CRect(0, 0, 0, 0), this, BTN_ID_ZOOM_OUT);
91     mZoomOutButton.LoadBitmaps(IDB_SCREEN_FLOW_ZOOM_OUT, IDB_SCREEN_FLOW_ZOOM_OUT_PRESSED);
92     SetControlAccessibleName(mZoomOutButton.GetSafeHwnd(), _T("zoom out"));
93 
94     mZoomInButton.Create(_T(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW | MAX_TAB_STOPS, CRect(0, 0, 0, 0), this, BTN_ID_ZOOM_IN);
95     mZoomInButton.LoadBitmaps(IDB_SCREEN_FLOW_ZOOM_IN, IDB_SCREEN_FLOW_ZOOM_IN_PRESSED);
96     SetControlAccessibleName(mZoomInButton.GetSafeHwnd(), _T("zoom in"));
97 
98     mZoomValueLable.Create(_T(""), WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, ID_ZOOM_VALUE_LABLE);
99     UpdateZoomValue();
100 
101     mFont.CreateFont(ICON_HEIGHT, 0, 0, 0,
102         FW_NORMAL, FALSE, TRUE, 0,
103         ANSI_CHARSET,
104         OUT_TT_PRECIS,
105         CLIP_DEFAULT_PRECIS,
106         CLEARTYPE_QUALITY,
107         DEFAULT_PITCH | FF_SWISS, _T("Arial"));
108 
109     mZoomValueLable.SetFont(&mFont);
110     SetLiveRegion(mZoomValueLable.GetSafeHwnd());
111 
112 
113     //Add run button
114     mRunButton.Create(_T("Run"), BS_PUSHBUTTON | BS_CENTER | BS_VCENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, CRect(0, 0, 0, 0), this, BTN_ID_RUN_PROJECT);
115     return 0;
116 }
117 
118 ///////////////////////////////////////////////////////////////////////////////
OnSize(UINT nType,int cx,int cy)119 void screen_flow_button_frame::OnSize(UINT nType, int cx, int cy)
120 {
121     CWnd::OnSize(nType, cx, cy);
122 
123     // TODO: Add your message handler code here
124     CRect size;
125     CRect client;
126     GetClientRect(&client);
127 
128     CBitmap icon;
129     BITMAP bmp;
130     icon.LoadBitmap(IDB_FIT_CONTENT);
131     icon.GetObject(sizeof(BITMAP), &bmp);
132 
133     //Position fit content button
134     size.top = (client.Height() - bmp.bmHeight) >> 1;
135     size.bottom = size.top + bmp.bmHeight;
136     size.left = client.left + 10;
137     size.right = size.left + bmp.bmWidth;
138 
139     mFitContent.MoveWindow(size);
140 
141     //Position zoom out button
142     size.OffsetRect(CPoint(bmp.bmWidth + 10, 0));
143     mZoomOutButton.MoveWindow(size);
144 
145     //Position zoom in button
146     size.OffsetRect(CPoint(bmp.bmWidth + 10, 0));
147     mZoomInButton.MoveWindow(size);
148 
149     //Position zoom value lable
150     size.left = size.right + 10;
151     size.right = size.left + ICON_WIDTH * 2;
152     mZoomValueLable.MoveWindow(size);
153 
154     //Position run button
155     size.top = client.top + 2;
156     size.bottom = client.bottom - 2;
157     size.right = client.right - 10;
158     size.left = size.right - SAVE_BUTTON_WIDTH;
159     mRunButton.MoveWindow(size);
160 }
161 
162 
163 ///////////////////////////////////////////////////////////////////////////////
PreTranslateMessage(MSG * pMsg)164 BOOL screen_flow_button_frame::PreTranslateMessage(MSG* pMsg)
165 {
166     // TODO: Add your specialized code here and/or call the base class
167     if ((pMsg->message == WM_KEYDOWN) &&
168         (pMsg->wParam == VK_RETURN))
169     {
170         CWnd* focus_owner = GetFocus();
171         switch (focus_owner->GetDlgCtrlID())
172         {
173         case BTN_ID_FIT_CONTENT:
174             OnFitContent();
175             return TRUE;
176 
177         case BTN_ID_ZOOM_OUT:
178             OnZoomOut();
179             return TRUE;
180 
181         case BTN_ID_ZOOM_IN:
182             OnZoomIn();
183             return TRUE;
184 
185         case BTN_ID_RUN_PROJECT:
186             OnRunProject();
187             return TRUE;
188         }
189     }
190 
191     return CWnd::PreTranslateMessage(pMsg);
192 }
193 
194 ///////////////////////////////////////////////////////////////////////////////
UpdateZoomValue()195 void screen_flow_button_frame::UpdateZoomValue()
196 {
197     CString text;
198 
199     text.Format(_T("%d"), mpScreenFlow->GetScale());
200     text.Append(_T("%"));
201     mZoomValueLable.SetWindowText(text);
202 
203     CRect size;
204     mZoomValueLable.GetWindowRect(&size);
205     ScreenToClient(&size);
206     InvalidateRect(&size);
207 
208     // Raise a UIA LiveRegionChanged
209     // event so that a screen reader is made aware of a change to the LiveRegion.
210     // Make sure the updated text is set on the label before making this call.
211     mZoomValueLable.NotifyWinEvent(
212         EVENT_OBJECT_LIVEREGIONCHANGED,
213         OBJID_CLIENT,
214         CHILDID_SELF);
215 }
216 
217 ///////////////////////////////////////////////////////////////////////////////
OnFitContent()218 void screen_flow_button_frame::OnFitContent()
219 {
220     screen_flow_edit_dlg* dlg = (screen_flow_edit_dlg*)GetParent();
221 
222     dlg->Zoom(TYPE_FIT_CONTENT);
223     UpdateZoomValue();
224 }
225 
226 ///////////////////////////////////////////////////////////////////////////////
OnZoomOut()227 void screen_flow_button_frame::OnZoomOut()
228 {
229     screen_flow_edit_dlg* dlg = (screen_flow_edit_dlg*)GetParent();
230 
231     dlg->Zoom(TYPE_ZOOM_OUT);
232     UpdateZoomValue();
233 }
234 
235 ///////////////////////////////////////////////////////////////////////////////
OnZoomIn()236 void screen_flow_button_frame::OnZoomIn()
237 {
238     screen_flow_edit_dlg* dlg = (screen_flow_edit_dlg*)GetParent();
239 
240     dlg->Zoom(TYPE_ZOOM_IN);
241     UpdateZoomValue();
242 }
243 
244 
245 ///////////////////////////////////////////////////////////////////////////////
OnRunProject()246 void screen_flow_button_frame::OnRunProject()
247 {
248     project_view* project_view = GetProjectView();
249 
250     if (project_view)
251     {
252         project_view->RunApplication(this);
253     }
254 }
255 
256 ///////////////////////////////////////////////////////////////////////////////
OnEraseBkgnd(CDC * pDC)257 BOOL screen_flow_button_frame::OnEraseBkgnd(CDC* pDC)
258 {
259     HIGHCONTRAST info = { 0 };
260     info.cbSize = sizeof(HIGHCONTRAST);
261 
262     SystemParametersInfoW(SPI_GETHIGHCONTRAST, 0, &info, 0);
263 
264     CBrush *oldBrush;
265     CBrush brush;
266 
267     if (info.dwFlags & HCF_HIGHCONTRASTON)
268     {
269         brush.CreateSolidBrush(GetSysColor(COLOR_WINDOW));
270 
271     }
272     else
273     {
274         brush.CreateSolidBrush(RGB(215, 215, 215));
275     }
276 
277     oldBrush = pDC->SelectObject(&brush);
278 
279     CRect size;
280     GetClientRect(&size);
281     pDC->Rectangle(size);
282     pDC->SelectObject(oldBrush);
283 
284     return TRUE;
285 }
286 
287 ///////////////////////////////////////////////////////////////////////////////
OnCtlColor(CDC * pDC,CWnd * pWnd,UINT nCtlColor)288 HBRUSH screen_flow_button_frame::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
289 {
290     HBRUSH hbr = CWnd::OnCtlColor(pDC, pWnd, nCtlColor);
291 
292     // TODO:  Change any attributes of the DC here
293     if (pWnd->GetDlgCtrlID() == ID_ZOOM_VALUE_LABLE)
294     {
295         pDC->SetBkMode(TRANSPARENT);
296         return (HBRUSH)GetStockObject(NULL_BRUSH);
297     }
298 
299     // TODO:  Return a different brush if the default is not desired
300     return hbr;
301 }
302 
BEGIN_MESSAGE_MAP(screen_flow_diagram_win,CWnd)303 BEGIN_MESSAGE_MAP(screen_flow_diagram_win, CWnd)
304     ON_WM_PAINT()
305     ON_WM_LBUTTONDOWN()
306     ON_WM_RBUTTONDOWN()
307     ON_WM_LBUTTONUP()
308     ON_WM_MOUSEMOVE()
309     ON_WM_ERASEBKGND()
310     ON_WM_RBUTTONUP()
311     ON_WM_LBUTTONDBLCLK()
312     ON_WM_HSCROLL()
313     ON_WM_VSCROLL()
314     ON_WM_MOUSEWHEEL()
315     ON_WM_SETFOCUS()
316     ON_WM_KILLFOCUS()
317     ON_WM_SIZE()
318 END_MESSAGE_MAP()
319 
320 ///////////////////////////////////////////////////////////////////////////////
321 screen_flow_diagram_win::screen_flow_diagram_win(int display, screen_flow *flow, CWnd* pParent)
322 {
323     mpScreenFlow = flow;
324     mpDragItem = NULL;
325     mConnectionList.RemoveAll();
326     mActiveDisplay = display;
327 
328     m_scroll_helper = new CScrollHelper;
329     m_scroll_helper->AttachWnd(this);
330 
331     mDisplayHeight = 0;
332     mDisplayWidth = 0;
333 
334     mDiagramScale = flow->GetScale();
335     mSystemDpi = GetSystemDPI();
336     mScale = MulDiv(mDiagramScale, mSystemDpi, DEFAULT_DPI_96);
337 
338     InitConnectionList();
339 }
340 
341 ///////////////////////////////////////////////////////////////////////////////
~screen_flow_diagram_win()342 screen_flow_diagram_win::~screen_flow_diagram_win()
343 {
344     for (int index = 0; index < mConnectionList.GetCount(); index++)
345     {
346         delete mConnectionList.GetAt(index);
347     }
348     mConnectionList.RemoveAll();
349 
350     delete m_scroll_helper;
351 }
352 
353 ///////////////////////////////////////////////////////////////////////////////
OnEraseBkgnd(CDC * pDC)354 BOOL screen_flow_diagram_win::OnEraseBkgnd(CDC* pDC)
355 {
356     return TRUE;
357 }
358 
359 ///////////////////////////////////////////////////////////////////////////////
OnPaint()360 void screen_flow_diagram_win::OnPaint()
361 {
362     CPaintDC dc(this);
363 
364     flow_item *item;
365     CRect client;
366     GetClientRect(&client);
367 
368     CDC        dcMem;
369     HBITMAP    hbmMem;
370     HANDLE     hOld;
371 
372     /* Flush canvas memory to off-screen DC. */
373     dcMem.CreateCompatibleDC(&dc);
374     hbmMem = CreateCompatibleBitmap(dc, client.Width(), client.Height());
375     hOld = SelectObject(dcMem, hbmMem);
376 
377     dcMem.FillSolidRect(client, GetSysColor(COLOR_3DFACE));
378 
379     Graphics       g(dcMem);
380     SolidBrush    *brush;
381     SolidBrush     normalBrush(Color(255, 0, 0, 0));
382     SolidBrush     selectedBrush(Color(255, 0, 120, 219));
383     SolidBrush     whiteBrush(Color(255, 255, 255, 255));
384     Pen           *pen;
385     Pen            normalPen(Color(255, 0, 0, 0), 2);
386     Pen            selectedPen(Color(255, 0, 120, 219), 2);
387     FontFamily     fontFamily(_T("Times New Roman"));
388     Gdiplus::Font  font(&fontFamily, (REAL)(16 * mScale / 100), FontStyleRegular, UnitPixel);
389     StringFormat   stringFormat;
390     AdjustableArrowCap bigArrow(5, 5);
391     RectF           rectF;
392 
393     CSize scrollpos = m_scroll_helper->GetScrollPos();
394 
395     //draw trigger connection
396     g.SetSmoothingMode(SmoothingModeAntiAlias);
397     normalPen.SetDashStyle(DashStyleSolid);
398     normalPen.SetCustomEndCap(&bigArrow);
399 
400     trigger_connection *connection;
401     flow_item *src_item, *target_item;
402     CPoint scaled_line_start;
403     CPoint scaled_line_end;
404 
405     for (int index = 0; index < mConnectionList.GetCount(); index++)
406     {
407         connection = mConnectionList.GetAt(index);
408 
409         src_item = mpScreenFlow->GetFlowItem(connection->source_screen);
410         target_item = mpScreenFlow->GetFlowItem(connection->target_screen);
411 
412         if (src_item && target_item && src_item->enabled && target_item->enabled)
413         {
414             // scaling line start and end point
415             scaled_line_start = GetScaledPoint(connection->line_start);
416             scaled_line_end = GetScaledPoint(connection->line_end);
417 
418             g.DrawLine(&normalPen,
419                 scaled_line_start.x - scrollpos.cx,
420                 scaled_line_start.y - scrollpos.cy,
421                 scaled_line_end.x - scrollpos.cx,
422                 scaled_line_end.y - scrollpos.cy);
423         }
424     }
425 
426     //draw screen flow
427 
428     // Center-justify each line of text.
429     stringFormat.SetAlignment(StringAlignmentCenter);
430 
431     // Center the block of text (top to bottom) in the rectangle.
432     stringFormat.SetLineAlignment(StringAlignmentCenter);
433     stringFormat.SetTrimming(StringTrimmingEllipsisCharacter);
434 
435     CRect scaled_rect;
436 
437     selectedPen.SetDashStyle(DashStyleDash);
438 
439     if (GetFocus() != this)
440     {
441         Color color;
442         normalBrush.GetColor(&color);
443         selectedBrush.SetColor(color);
444         selectedPen.SetColor(color);
445     }
446 
447     for (int index = 0; index < mpScreenFlow->GetFlowListCount() + 1; index++)
448     {
449         if (index < mpScreenFlow->GetFlowListCount())
450         {
451             item = mpScreenFlow->GetFlowItem(index);
452 
453             if (item == mpDragItem)
454             {
455                 //draw selected item on the top of other screen items
456                 continue;
457             }
458         }
459         else
460         {
461             item = mpDragItem;
462         }
463 
464         if (item && item->enabled)
465         {
466             if (mpDragItem == item)
467             {
468                 brush = &selectedBrush;
469                 pen = &selectedPen;
470             }
471             else
472             {
473                 brush = &normalBrush;
474                 pen = &normalPen;
475             }
476 
477             scaled_rect = GetScaledRect(item->rect);
478 
479             scaled_rect.DeflateRect(1, 1, 1, 1);
480 
481             rectF.X = (REAL)(scaled_rect.left - scrollpos.cx);
482             rectF.Y = (REAL)(scaled_rect.top - scrollpos.cy);
483             rectF.Width = (REAL)scaled_rect.Width() - 1;
484             rectF.Height = (REAL)scaled_rect.Height() - 1;
485 
486             g.FillRectangle(&whiteBrush, rectF);
487             g.DrawRectangle(pen, rectF);
488             g.DrawString(item->screen_name, -1, &font, rectF, &stringFormat, brush);
489         }
490     }
491 
492     /* Transfer the off-screen DC to the screen. */
493     BitBlt(dc, 0, 0, client.Width(), client.Height(), dcMem, 0, 0, SRCCOPY);
494 
495     /* Free-up the off-screen DC.  */
496     SelectObject(dcMem, hOld);
497     DeleteObject(hbmMem);
498     DeleteDC(dcMem);
499 }
500 
501 ///////////////////////////////////////////////////////////////////////////////
OnLButtonDown(UINT nFlags,CPoint point)502 void screen_flow_diagram_win::OnLButtonDown(UINT nFlags, CPoint point)
503 {
504     CPoint pt = point;
505     CSize scrollpos = m_scroll_helper->GetScrollPos();
506     pt.x += scrollpos.cx;
507     pt.y += scrollpos.cy;
508 
509     SetFocus();
510     SetCapture();
511 
512     mDragMode = CheckResizeCursor(pt);
513 
514     if (mDragMode != DRAG_NONE)
515     {
516         mDragStart = point;
517     }
518     else
519     {
520         CRect dirty;
521         CSize scrollpos = m_scroll_helper->GetScrollPos();
522 
523         if (mpDragItem)
524         {
525             dirty = GetScaledRect(mpDragItem->rect);
526 
527             dirty.left -= scrollpos.cx;
528             dirty.right -= scrollpos.cx;
529             dirty.top -= scrollpos.cy;
530             dirty.bottom -= scrollpos.cy;
531 
532             //mark old drag item as dirty
533             InvalidateRect(&dirty);
534         }
535 
536         // Get flow item under left button down point.
537         mpDragItem = mpScreenFlow->GetFlowItem(pt, TRUE);
538 
539         if (mpDragItem)
540         {
541             mDragMode = DRAG_ALL;
542             mDragStart = point;
543             SelectedVisible();
544         }
545     }
546 }
547 
548 ///////////////////////////////////////////////////////////////////////////////
OnLButtonUp(UINT nFlags,CPoint point)549 void screen_flow_diagram_win::OnLButtonUp(UINT nFlags, CPoint point)
550 {
551     mDragMode = DRAG_NONE;
552 
553 
554     ReleaseCapture();
555     UpdateDisplaySize();
556 }
557 
558 ///////////////////////////////////////////////////////////////////////////////
OnRButtonDown(UINT nFlags,CPoint point)559 void screen_flow_diagram_win::OnRButtonDown(UINT nFlags, CPoint point)
560 {
561     OnLButtonDown(nFlags, point);
562 
563     CWnd::OnRButtonDown(nFlags, point);
564 }
565 
566 ///////////////////////////////////////////////////////////////////////////////
OnRButtonUp(UINT nFlags,CPoint point)567 void screen_flow_diagram_win::OnRButtonUp(UINT nFlags, CPoint point)
568 {
569     CPoint pt = point;
570     CSize scrollpos = m_scroll_helper->GetScrollPos();
571     pt.x += scrollpos.cx;
572     pt.y += scrollpos.cy;
573 
574     ReleaseCapture();
575 
576     flow_item *item = mpScreenFlow->GetFlowItem(pt);
577 
578     if (item)
579     {
580         EditFlowItem(item);
581     }
582 
583     CWnd::OnRButtonUp(nFlags, point);
584 }
585 
586 ///////////////////////////////////////////////////////////////////////////////
OnSetFocus(CWnd * pOldWnd)587 void screen_flow_diagram_win::OnSetFocus(CWnd* pOldWnd)
588 {
589     CWnd::OnSetFocus(pOldWnd);
590 
591     // TODO: Add your message handler code here
592     if (!mpDragItem)
593     {
594         SelectFlowItem(FindFirstVisibleItem());
595     }
596     else
597     {
598         SelectFlowItem(mpDragItem);
599         CRect scaled_rect = GetScaledRect(mpDragItem->rect);
600         CSize scrollpos = m_scroll_helper->GetScrollPos();
601 
602         scaled_rect.OffsetRect(-scrollpos.cx, -scrollpos.cy);
603         InvalidateRect(scaled_rect);
604     }
605 }
606 
607 ///////////////////////////////////////////////////////////////////////////////
OnKillFocus(CWnd * pNewWnd)608 void screen_flow_diagram_win::OnKillFocus(CWnd* pNewWnd)
609 {
610     CWnd::OnKillFocus(pNewWnd);
611 
612     // TODO: Add your message handler code here
613     //mDragMode = DRAG_NONE;
614     if (mpDragItem)
615     {
616         CRect scaled_rect = GetScaledRect(mpDragItem->rect);
617         CSize scrollpos = m_scroll_helper->GetScrollPos();
618 
619         scaled_rect.OffsetRect(-scrollpos.cx, -scrollpos.cy);
620 
621         InvalidateRect(scaled_rect);
622     }
623 }
624 
625 ///////////////////////////////////////////////////////////////////////////////
OnSize(UINT nType,int cx,int cy)626 void screen_flow_diagram_win::OnSize(UINT nType, int cx, int cy)
627 {
628     CWnd::OnSize(nType, cx, cy);
629 
630     // TODO: Add your message handler code here
631     m_scroll_helper->OnSize(nType, cx, cy);
632 }
633 
634 ///////////////////////////////////////////////////////////////////////////////
FindFirstVisibleItem()635 flow_item * screen_flow_diagram_win::FindFirstVisibleItem()
636 {
637     flow_item *item;
638     flow_item *find = NULL;
639     CRect find_rect;
640     CRect scaled_rect;
641     CRect client;
642     CSize scrollpos = m_scroll_helper->GetScrollPos();
643 
644     GetClientRect(&client);
645 
646     for (int index = 0; index < mpScreenFlow->GetFlowListCount(); index++)
647     {
648         item = mpScreenFlow->GetFlowItem(index);
649 
650         if (item && item->enabled)
651         {
652             scaled_rect = GetScaledRect(item->rect);
653             scaled_rect.OffsetRect(-scrollpos.cx, -scrollpos.cy);
654 
655             if ((scaled_rect.left >= client.left) &&
656                 (scaled_rect.top >= client.top))
657             {
658                 if ((!find) ||
659                     (scaled_rect.top < find_rect.top) ||
660                     ((scaled_rect.top == find_rect.top) && (scaled_rect.left < find_rect.left)))
661                 {
662                     find = item;
663                     find_rect = scaled_rect;
664                 }
665             }
666         }
667     }
668 
669     return find;
670 }
671 
672 ///////////////////////////////////////////////////////////////////////////////
EditFlowItem(flow_item * item)673 BOOL screen_flow_diagram_win::EditFlowItem(flow_item *item)
674 {
675     if (!item)
676     {
677         return FALSE;
678     }
679     flow_item *old_item = new flow_item(*item);
680 
681     trigger_list_edit_dlg dlg(mActiveDisplay, mpScreenFlow, item);
682 
683     if (dlg.DoModal() == IDOK)
684     {
685         RemoveConnection(old_item);
686         CheckAddConnection(item);
687 
688         CRect client;
689         GetClientRect(&client);
690         InvalidateRect(&client);
691     }
692 
693     delete old_item;
694     return TRUE;
695 }
696 
697 ///////////////////////////////////////////////////////////////////////////////
SelectFlowItem(flow_item * item)698 void screen_flow_diagram_win::SelectFlowItem(flow_item* item)
699 {
700     if (item && item->enabled)
701     {
702         if (mpDragItem)
703         {
704             //invalid current selected item
705             CSize scrollpos = m_scroll_helper->GetScrollPos();
706             CRect scaled_rect = GetScaledRect(mpDragItem ->rect);
707             scaled_rect.OffsetRect(-scrollpos.cx, -scrollpos.cy);
708             InvalidateRect(scaled_rect);
709         }
710 
711         CString name = item->screen_name;
712         name.Format(_T("Screen flow diagram, item \"%s\" is selected"), name);
713 
714         SetControlAccessibleName(this->GetSafeHwnd(), name);
715 
716         mpDragItem = item;
717         SelectedVisible();
718     }
719 }
720 
721 ///////////////////////////////////////////////////////////////////////////////
HideFlowItem(flow_item * item)722 void screen_flow_diagram_win::HideFlowItem(flow_item* item)
723 {
724     if (item == mpDragItem)
725     {
726         mpDragItem = NULL;
727     }
728 }
729 
730 ///////////////////////////////////////////////////////////////////////////////
ShiftLeft(CRect scaled_rect,CRect client,INT scaled_shift_x,INT shift_x)731 void screen_flow_diagram_win::ShiftLeft(CRect scaled_rect, CRect client, INT scaled_shift_x, INT shift_x)
732 {
733     CSize scrollpos = m_scroll_helper->GetScrollPos();
734 
735     if (scaled_rect.left - scrollpos.cx + scaled_shift_x < client.left)
736     {
737         // exceed client left
738         int scaled_left;
739         int left;
740 
741         scaled_shift_x = client.left + scrollpos.cx - scaled_rect.left;
742         scaled_left = scaled_rect.left + scaled_shift_x;
743         left = (scaled_left * 100 + mScale - 1) / mScale;
744         shift_x = left - mpDragItem->rect.left;
745     }
746     else if (mpDragItem->rect.left + shift_x >= mpDragItem->rect.right - MIN_SCREEN_BOX_SIZE)
747     {
748         // exceed minimum screen box width
749         shift_x = mpDragItem->rect.right - MIN_SCREEN_BOX_SIZE - mpDragItem->rect.left;
750         scaled_shift_x = shift_x * mScale / 100;
751     }
752 
753     if (shift_x)
754     {
755         mpDragItem->rect.left += shift_x;
756         mDragStart.x += scaled_shift_x;
757     }
758 }
759 
760 ///////////////////////////////////////////////////////////////////////////////
ShiftTop(CRect scaled_rect,CRect client,INT scaled_shift_y,INT shift_y)761 void screen_flow_diagram_win::ShiftTop(CRect scaled_rect, CRect client, INT scaled_shift_y, INT shift_y)
762 {
763     CSize scrollpos = m_scroll_helper->GetScrollPos();
764 
765     if (scaled_rect.top - scrollpos.cy + scaled_shift_y < client.top)
766     {
767         // exceed client top
768         int scaled_top;
769         int top;
770 
771         scaled_shift_y = client.top  + scrollpos.cy - scaled_rect.top;
772         scaled_top = scaled_rect.top + scaled_shift_y;
773         top = (scaled_top * 100 + mScale - 1) / mScale;
774         shift_y = top - mpDragItem->rect.top;
775     }
776     else if (mpDragItem->rect.top + shift_y >= mpDragItem->rect.bottom - MIN_SCREEN_BOX_SIZE)
777     {
778         // exceed minimum screen box height
779         shift_y = mpDragItem->rect.bottom - MIN_SCREEN_BOX_SIZE - mpDragItem->rect.top;
780         scaled_shift_y = shift_y * mScale / 100;
781     }
782 
783     if (shift_y)
784     {
785         mpDragItem->rect.top += shift_y;
786         mDragStart.y += scaled_shift_y;
787     }
788 }
789 
790 ///////////////////////////////////////////////////////////////////////////////
ShiftRight(CRect scaled_rect,CRect client,INT scaled_shift_x,INT shift_x)791 void screen_flow_diagram_win::ShiftRight(CRect scaled_rect, CRect client, INT scaled_shift_x, INT shift_x)
792 {
793     CSize scrollpos = m_scroll_helper->GetScrollPos();
794 
795     if (scaled_rect.right - scrollpos.cx + scaled_shift_x> client.right)
796     {
797         // exceed client right
798         int scaled_right;
799         int right;
800 
801         scaled_shift_x = client.right + scrollpos.cx - scaled_rect.right;
802         scaled_right = scaled_rect.right + scaled_shift_x;
803         right = (scaled_right * 100) / mScale;
804         shift_x = right - mpDragItem->rect.right;
805     }
806     else if (mpDragItem->rect.right + shift_x <= mpDragItem->rect.left + MIN_SCREEN_BOX_SIZE)
807     {
808         // exceed minimum screen box width
809         shift_x = mpDragItem->rect.left + MIN_SCREEN_BOX_SIZE - mpDragItem->rect.right;
810         scaled_shift_x = shift_x * mScale / 100;
811     }
812 
813     if (shift_x)
814     {
815         mpDragItem->rect.right += shift_x;
816         mDragStart.x += scaled_shift_x;
817     }
818 }
819 
820 ///////////////////////////////////////////////////////////////////////////////
ShiftBottom(CRect scaled_rect,CRect client,INT scaled_shift_y,INT shift_y)821 void screen_flow_diagram_win::ShiftBottom(CRect scaled_rect, CRect client, INT scaled_shift_y, INT shift_y)
822 {
823     CSize scrollpos = m_scroll_helper->GetScrollPos();
824 
825     if (scaled_rect.bottom - scrollpos.cy + scaled_shift_y> client.bottom)
826     {
827         // exceed client bottom
828         int scaled_bottom;
829         int bottom;
830 
831         scaled_shift_y = client.bottom + scrollpos.cy - scaled_rect.bottom;
832         scaled_bottom = scaled_rect.bottom + scaled_shift_y;
833         bottom = (scaled_bottom * 100) / mScale;
834         shift_y = bottom - mpDragItem->rect.bottom;
835     }
836 
837     if (mpDragItem->rect.bottom + shift_y <= mpDragItem->rect.top + MIN_SCREEN_BOX_SIZE)
838     {
839         // exceed minimum screen box height
840         shift_y = mpDragItem->rect.top + MIN_SCREEN_BOX_SIZE - mpDragItem->rect.bottom;
841         scaled_shift_y = shift_y * mScale / 100;
842     }
843 
844     if (shift_y)
845     {
846         mpDragItem->rect.bottom += shift_y;
847         mDragStart.y += scaled_shift_y;
848     }
849 }
850 
851 ///////////////////////////////////////////////////////////////////////////////
OnMouseMove(UINT nFlags,CPoint point)852 void screen_flow_diagram_win::OnMouseMove(UINT nFlags, CPoint point)
853 {
854     if (mDragMode == DRAG_NONE)
855     {
856         if ((nFlags & MK_LBUTTON) == 0)
857         {
858             CSize scrollpos = m_scroll_helper->GetScrollPos();
859             CPoint pt = point;
860             pt.x += scrollpos.cx;
861             pt.y += scrollpos.cy;
862 
863             CheckResizeCursor(pt);
864         }
865         return;
866     }
867 
868     if (mpDragItem && (nFlags & MK_LBUTTON))
869     {
870         int scaled_shift_x = point.x - mDragStart.x;
871         int scaled_shift_y = point.y - mDragStart.y;
872         int shift_x = point.x * 100 / mScale - mDragStart.x * 100 / mScale;
873         int shift_y = point.y * 100 / mScale - mDragStart.y * 100 / mScale;
874 
875         CRect client;
876         CRect scaled_rect = GetScaledRect(mpDragItem->rect);
877 
878         GetClientRect(&client);
879 
880         switch (mDragMode)
881         {
882         case DRAG_ALL:
883             if (scaled_rect.left + scaled_shift_x < client.left)
884             {
885                 int scaled_left;
886                 int left;
887 
888                 scaled_shift_x = client.left - scaled_rect.left;
889                 scaled_left = scaled_rect.left + scaled_shift_x;
890                 left = (scaled_left * 100 + mScale - 1) / mScale;
891                 shift_x = left - mpDragItem->rect.left;
892             }
893 
894             if (shift_x)
895             {
896                 mpDragItem->rect.left += shift_x;
897                 mpDragItem->rect.right += shift_x;
898                 mDragStart.x += scaled_shift_x;
899             }
900 
901             if (scaled_rect.top + scaled_shift_y < client.top)
902             {
903                 int scaled_top;
904                 int top;
905 
906                 scaled_shift_y = client.top - scaled_rect.top;
907                 scaled_top = scaled_rect.top + scaled_shift_y;
908                 top = (scaled_top * 100 + mScale - 1) / mScale;
909                 shift_y = top - mpDragItem->rect.top;
910             }
911 
912             if (shift_y)
913             {
914                 mpDragItem->rect.top += shift_y;
915                 mpDragItem->rect.bottom += shift_y;
916                 mDragStart.y += scaled_shift_y;
917             }
918             break;
919 
920         case DRAG_TOP_LEFT:
921             ShiftTop(scaled_rect, client, scaled_shift_y, shift_y);
922             ShiftLeft(scaled_rect, client, scaled_shift_x, shift_x);
923             break;
924 
925         case DRAG_TOP:
926             ShiftTop(scaled_rect, client, scaled_shift_y, shift_y);
927             break;
928 
929         case DRAG_TOP_RIGHT:
930             ShiftTop(scaled_rect, client, scaled_shift_y, shift_y);
931             ShiftRight(scaled_rect, client, scaled_shift_x, shift_x);
932             break;
933 
934         case DRAG_RIGHT:
935             ShiftRight(scaled_rect, client, scaled_shift_x, shift_x);
936             break;
937 
938         case DRAG_BOTTOM_RIGHT:
939             ShiftBottom(scaled_rect, client, scaled_shift_y, shift_y);
940             ShiftRight(scaled_rect, client, scaled_shift_x, shift_x);
941             break;
942 
943         case DRAG_BOTTOM:
944             ShiftBottom(scaled_rect, client, scaled_shift_y, shift_y);
945             break;
946 
947         case DRAG_BOTTOM_LEFT:
948             ShiftBottom(scaled_rect, client, scaled_shift_y, shift_y);
949             ShiftLeft(scaled_rect, client, scaled_shift_x, shift_x);
950             break;
951 
952         case DRAG_LEFT:
953             ShiftLeft(scaled_rect, client, scaled_shift_x, shift_x);
954             break;
955         }
956 
957         UpdateConnectionPos(mpDragItem);
958         InvalidateRect(&client);
959     }
960 
961     CWnd::OnMouseMove(nFlags, point);
962 }
963 
964 ///////////////////////////////////////////////////////////////////////////////
OnMouseWheel(UINT nFlags,short zDelta,CPoint pt)965 BOOL screen_flow_diagram_win::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
966 {
967 
968     if (nFlags & MK_CONTROL)
969     {
970         // TODO: Add your message handler code here and/or call default
971         if (zDelta > 0)
972         {
973             Zoom(TYPE_ZOOM_IN);
974         }
975         else
976         {
977             Zoom(TYPE_ZOOM_OUT);
978         }
979 
980         return CWnd::OnMouseWheel(nFlags, zDelta, pt);
981     }
982     else
983     {
984         BOOL wasScrolled = m_scroll_helper->OnMouseWheel(nFlags, zDelta, pt);
985         return wasScrolled;
986     }
987 }
988 
989 ///////////////////////////////////////////////////////////////////////////////
PreTranslateMessage(MSG * pMsg)990 BOOL screen_flow_diagram_win::PreTranslateMessage(MSG* pMsg)
991 {
992     // TODO: Add your specialized code here and/or call the base class
993     if (pMsg->message == WM_KEYDOWN)
994     {
995         if (HandleKeydown(pMsg->wParam))
996         {
997             return TRUE;
998         }
999     }
1000 
1001     return CWnd::PreTranslateMessage(pMsg);
1002 }
1003 
1004 
1005 ///////////////////////////////////////////////////////////////////////////////
Zoom(int type)1006 VOID screen_flow_diagram_win::Zoom(int type)
1007 {
1008     //make the inner window fit the client window
1009     int old_scale = mDiagramScale;
1010     int new_scale = mDiagramScale;
1011 
1012     switch (type)
1013     {
1014     case TYPE_ZOOM_IN:
1015         new_scale = new_scale + 25;
1016 
1017         if (new_scale % 25)
1018         {
1019             new_scale -= (new_scale % 25);
1020         }
1021         break;
1022 
1023     case TYPE_ZOOM_OUT:
1024         if (new_scale % 25)
1025         {
1026             new_scale -= (new_scale % 25);
1027         }
1028         else
1029         {
1030             new_scale -= 25;
1031         }
1032         break;
1033 
1034     case TYPE_FIT_CONTENT:
1035     {
1036         CRect client;
1037         int border_width = (::GetSystemMetrics(SM_CXBORDER)) * 2;
1038 
1039         GetWindowRect(&client);
1040 
1041         int scale_x = (client.Width() - border_width) * 100 / mDisplayWidth;
1042         int scale_y = (client.Height() - border_width) * 100 / mDisplayHeight;
1043 
1044         if (scale_x < scale_y)
1045         {
1046             new_scale = scale_x;
1047         }
1048         else
1049         {
1050             new_scale = scale_y;
1051         }
1052 
1053         new_scale = MulDiv(new_scale, DEFAULT_DPI_96, mSystemDpi);
1054     }
1055         break;
1056 
1057     default:
1058         return;
1059     }
1060 
1061     if (new_scale > SCREEN_FLOW_MAX_SCALE)
1062     {
1063         new_scale = SCREEN_FLOW_MAX_SCALE;
1064     }
1065     else if (new_scale < SCREEN_FLOW_MIN_SCALE)
1066     {
1067         new_scale = SCREEN_FLOW_MIN_SCALE;
1068     }
1069 
1070     mDiagramScale = new_scale;
1071 
1072     mpScreenFlow->SetScale(mDiagramScale);
1073     mScale = MulDiv(mDiagramScale, mSystemDpi, DEFAULT_DPI_96);
1074     m_scroll_helper->SetDisplaySize(mDisplayWidth * mScale / 100, mDisplayHeight * mScale / 100);
1075     Invalidate();
1076 }
1077 
1078 ///////////////////////////////////////////////////////////////////////////////
GetScaledRect(CRect rect)1079 CRect screen_flow_diagram_win::GetScaledRect(CRect rect)
1080 {
1081     CRect scaled;
1082 
1083     scaled.left = rect.left * mScale / 100;
1084     scaled.top = rect.top * mScale / 100;
1085     scaled.right = rect.right * mScale / 100;
1086     scaled.bottom = rect.bottom * mScale / 100;
1087 
1088     return scaled;
1089 }
1090 
1091 ///////////////////////////////////////////////////////////////////////////////
GetScaledPoint(CPoint point)1092 CPoint screen_flow_diagram_win::GetScaledPoint(CPoint point)
1093 {
1094     CPoint scaled;
1095 
1096     scaled.x = point.x * mScale / 100;
1097     scaled.y = point.y * mScale / 100;
1098 
1099     return scaled;
1100 }
1101 
1102 ///////////////////////////////////////////////////////////////////////////////
InitConnectionList()1103 void screen_flow_diagram_win::InitConnectionList()
1104 {
1105     flow_item *source;
1106 
1107     for (int index = 0; index < mpScreenFlow->GetFlowListCount(); index++)
1108     {
1109         //loop through flow items
1110         source = mpScreenFlow->GetFlowItem(index);
1111         CheckAddConnection(source);
1112     }
1113 }
1114 
1115 ///////////////////////////////////////////////////////////////////////////////
UpdateDisplaySize()1116 void screen_flow_diagram_win::UpdateDisplaySize()
1117 {
1118     flow_item *item;
1119 
1120     mDisplayWidth = 0;
1121     mDisplayHeight = 0;
1122 
1123     for (int index = 0; index < mpScreenFlow->GetFlowListCount(); index++)
1124     {
1125         //loop through flow items
1126         item = mpScreenFlow->GetFlowItem(index);
1127 
1128         if (item->enabled)
1129         {
1130             if (item->rect.right > mDisplayWidth)
1131             {
1132                 mDisplayWidth = item->rect.right;
1133             }
1134 
1135             if (item->rect.bottom > mDisplayHeight)
1136             {
1137                 mDisplayHeight = item->rect.bottom;
1138             }
1139         }
1140     }
1141 
1142     m_scroll_helper->SetDisplaySize(mDisplayWidth * mScale / 100, mDisplayHeight * mScale / 100);
1143 }
1144 
1145 ///////////////////////////////////////////////////////////////////////////////
SelectedVisible()1146 void screen_flow_diagram_win::SelectedVisible()
1147 {
1148     if (mpDragItem)
1149     {
1150         CSize scrollpos = m_scroll_helper->GetScrollPos();
1151 
1152         CRect rect = GetScaledRect(mpDragItem->rect);
1153 
1154         rect.MoveToXY(CPoint(rect.left - scrollpos.cx, rect.top - scrollpos.cy));
1155 
1156         CRect client;
1157         GetClientRect(&client);
1158         BOOL mark_whole_dirty = FALSE;
1159 
1160         if ((rect.right > client.right) && (rect.left > client.left))
1161         {
1162             //move scrollbar right
1163 
1164             scrollpos.cx += (rect.right - client.right);
1165             m_scroll_helper->SetScrollPos(SB_HORZ, scrollpos.cx, FALSE);
1166             mark_whole_dirty = TRUE;
1167         }
1168         else if ((rect.left < client.left) && (rect.right < client.right))
1169         {
1170             scrollpos.cx += (rect.left - client.left);
1171             m_scroll_helper->SetScrollPos(SB_HORZ, scrollpos.cx, FALSE);
1172             mark_whole_dirty = TRUE;
1173         }
1174 
1175         if ((rect.bottom > client.bottom) && (rect.top > client.top))
1176         {
1177             //move scrollbar down
1178             scrollpos.cy += (rect.bottom - client.bottom);
1179             m_scroll_helper->SetScrollPos(SB_VERT, scrollpos.cy, FALSE);
1180             mark_whole_dirty = TRUE;
1181         }
1182         else if ((rect.top < client.top) && (rect.bottom < client.bottom))
1183         {
1184             scrollpos.cy += (rect.top - client.top);
1185             m_scroll_helper->SetScrollPos(SB_VERT, scrollpos.cy, FALSE);
1186             mark_whole_dirty = TRUE;
1187         }
1188 
1189         if (mark_whole_dirty)
1190         {
1191             InvalidateRect(&client);
1192         }
1193         else
1194         {
1195             InvalidateRect(&rect);
1196         }
1197     }
1198 }
1199 
1200 ///////////////////////////////////////////////////////////////////////////////
HandleKeydown(UINT message)1201 BOOL screen_flow_diagram_win::HandleKeydown(UINT message)
1202 {
1203     BOOL handled = FALSE;
1204 
1205     if (mpDragItem)
1206     {
1207         CRect client;
1208         GetClientRect(&client);
1209         int nVirtKey = GetKeyState(VK_SHIFT);
1210 
1211         switch (message)
1212         {
1213         case VK_RETURN:
1214             if (EditFlowItem(mpDragItem))
1215             {
1216                 return TRUE;
1217             }
1218             break;
1219 
1220         case VK_UP:
1221             if (nVirtKey & SHIFTED)
1222             {
1223                 if (mpDragItem->rect.top + MIN_SCREEN_BOX_SIZE >= mpDragItem->rect.bottom)
1224                 {
1225                     return TRUE;
1226                 }
1227                 mpDragItem->rect.bottom--;
1228             }
1229             else
1230             {
1231                 if (mpDragItem->rect.top < 1)
1232                 {
1233                     return TRUE;
1234                 }
1235                 mpDragItem->rect.top -= 1;
1236                 mpDragItem->rect.bottom -= 1;
1237             }
1238             handled = TRUE;
1239             break;
1240 
1241         case VK_DOWN:
1242             if (nVirtKey & SHIFTED)
1243             {
1244                 mpDragItem->rect.bottom++;
1245             }
1246             else
1247             {
1248                 mpDragItem->rect.top += 1;
1249                 mpDragItem->rect.bottom += 1;
1250             }
1251             handled = TRUE;
1252             break;
1253 
1254         case VK_LEFT:
1255             if(nVirtKey & SHIFTED)
1256             {
1257                 if (mpDragItem->rect.left + MIN_SCREEN_BOX_SIZE >= mpDragItem->rect.right)
1258                 {
1259                     return TRUE;
1260                 }
1261 
1262                 mpDragItem->rect.right--;
1263             }
1264             else
1265             {
1266                 if (mpDragItem->rect.left < 1)
1267                 {
1268                     return TRUE;
1269                 }
1270                 mpDragItem->rect.left -= 1;
1271                 mpDragItem->rect.right -= 1;
1272             }
1273             handled = TRUE;
1274             break;
1275 
1276         case VK_RIGHT:
1277             if (nVirtKey & SHIFTED)
1278             {
1279                 mpDragItem->rect.right++;
1280             }
1281             else
1282             {
1283                 mpDragItem->rect.left += 1;
1284                 mpDragItem->rect.right += 1;
1285             }
1286             handled = TRUE;
1287             break;
1288         }
1289 
1290         if (handled)
1291         {
1292             UpdateConnectionPos(mpDragItem);
1293             UpdateDisplaySize();
1294             SelectedVisible();
1295 
1296             InvalidateRect(&client);
1297         }
1298     }
1299 
1300     return handled;
1301 }
1302 
1303 ///////////////////////////////////////////////////////////////////////////////
RemoveConnection(flow_item * source)1304 void screen_flow_diagram_win::RemoveConnection(flow_item *source)
1305 {
1306     //remove all connections start from specified source
1307     if (!source) return;
1308 
1309     flow_item *target;
1310     trigger_info *trigger;
1311     CArray<action_info *> *action_list;
1312     action_info *action;
1313 
1314     trigger = source->trigger_list;
1315 
1316     while (trigger)
1317     {
1318         //loop through trigger list
1319         action_list = &trigger->action_list;
1320 
1321         for (int count = 0; count < action_list->GetCount(); count++)
1322         {
1323             //loop through action list
1324             action = action_list->GetAt(count);
1325 
1326             if (!action->target_widget_name.IsEmpty())
1327             {
1328                 target = mpScreenFlow->GetFlowItem(action->target_widget_name);
1329                 RemoveConnection(source, target);
1330             }
1331         }
1332         trigger = trigger->next;
1333     }
1334 }
1335 
1336 ///////////////////////////////////////////////////////////////////////////////
RemoveConnection(flow_item * source,flow_item * target)1337 void screen_flow_diagram_win::RemoveConnection(flow_item *source, flow_item *target)
1338 {
1339     trigger_connection *remove;
1340 
1341     if (!source || !target) return;
1342 
1343     for (int index = 0; index < mConnectionList.GetCount(); index++)
1344     {
1345         remove = mConnectionList.GetAt(index);
1346         if ((remove->source_screen == source->screen_name) &&
1347             (remove->target_screen == target->screen_name))
1348         {
1349             delete remove;
1350             mConnectionList.RemoveAt(index);
1351         }
1352     }
1353 }
1354 
1355 ///////////////////////////////////////////////////////////////////////////////
CheckAddConnection(flow_item * source)1356 void screen_flow_diagram_win::CheckAddConnection(flow_item *source)
1357 {
1358     //add all connections start from specified source
1359     if (!source) return;
1360 
1361     flow_item *target;
1362     trigger_info *trigger;
1363     CArray<action_info *> *action_list;
1364     action_info *action;
1365 
1366     trigger = source->trigger_list;
1367 
1368     while (trigger)
1369     {
1370         //loop through trigger list
1371         action_list = &trigger->action_list;
1372 
1373         for (int count = 0; count < action_list->GetCount(); count++)
1374         {
1375             //loop through action list
1376             action = action_list->GetAt(count);
1377 
1378             if (!action->target_widget_name.IsEmpty())
1379             {
1380                 target = mpScreenFlow->GetFlowItem(action->target_widget_name);
1381                 CheckAddConnection(source, target);
1382             }
1383         }
1384         trigger = trigger->next;
1385     }
1386 }
1387 
1388 ///////////////////////////////////////////////////////////////////////////////
CheckAddConnection(flow_item * source,flow_item * target)1389 void screen_flow_diagram_win::CheckAddConnection(flow_item *source, flow_item *target)
1390 {
1391     GX_BOOL founded = FALSE;
1392     trigger_connection *exist;
1393 
1394     if (!source || !target || source == target) return;
1395 
1396     for (int index = 0; index < mConnectionList.GetCount(); index++)
1397     {
1398         exist = mConnectionList.GetAt(index);
1399         if ((exist->source_screen == source->screen_name) &&
1400             (exist->target_screen == target->screen_name))
1401         {
1402             founded = TRUE;
1403         }
1404     }
1405 
1406     if (!founded)
1407     {
1408         trigger_connection *connection = new trigger_connection;
1409         connection->source_screen = source->screen_name;
1410         connection->target_screen = target->screen_name;
1411 
1412         CalculateConnectionPos(connection, source, target);
1413         mConnectionList.Add(connection);
1414     }
1415 }
1416 
1417 ///////////////////////////////////////////////////////////////////////////////
CalculateConnectionPos(trigger_connection * connection,flow_item * source,flow_item * target)1418 void screen_flow_diagram_win::CalculateConnectionPos(trigger_connection *connection, flow_item *source, flow_item *target)
1419 {
1420     BOOL two_direction = FALSE;
1421     trigger_connection *other;
1422     for (int index = 0; index < mConnectionList.GetCount(); index++)
1423     {
1424         other = mConnectionList.GetAt(index);
1425 
1426         if (other == connection)
1427         {
1428             break;
1429         }
1430 
1431         if (other->source_screen == connection->target_screen &&
1432             other->target_screen == connection->source_screen)
1433         {
1434             two_direction = TRUE;
1435         }
1436     }
1437 
1438     CPoint source_center;
1439     CPoint target_center;
1440     CPoint line_start;
1441     CPoint line_end;
1442 
1443     source_center.x = (source->rect.left + source->rect.right) / 2;
1444     source_center.y = (source->rect.top + source->rect.bottom) / 2;
1445     target_center.x = (target->rect.left + target->rect.right) / 2;
1446     target_center.y = (target->rect.top + target->rect.bottom) / 2;
1447 
1448     float delta = (float)(target_center.x - source_center.x) / (target_center.y - source_center.y);
1449 
1450     if (source_center.y <= target_center.y)
1451     {
1452         if (delta <= -1)
1453         {
1454             line_start.x = source->rect.left;
1455             line_start.y = (source->rect.top + source->rect.bottom) / 2;
1456             line_end.x = target->rect.right;
1457             line_end.y = (target->rect.top + target->rect.bottom) / 2;
1458         }
1459         else if ((delta >= -1) && (delta < 1))
1460         {
1461             line_start.x = (source->rect.left + source->rect.right) / 2;
1462             line_start.y = source->rect.bottom;
1463             line_end.x = (target->rect.left + target->rect.right) / 2;
1464             line_end.y = target->rect.top;
1465         }
1466         else
1467         {
1468             line_start.x = source->rect.right;
1469             line_start.y = (source->rect.top + source->rect.bottom) / 2;
1470             line_end.x = target->rect.left;
1471             line_end.y = (target->rect.top + target->rect.bottom) / 2;
1472         }
1473     }
1474     else
1475     {
1476         if (delta >= 1)
1477         {
1478             line_start.x = source->rect.left;
1479             line_start.y = (source->rect.top + source->rect.bottom) / 2;
1480             line_end.x = target->rect.right;
1481             line_end.y = (target->rect.top + target->rect.bottom) / 2;
1482         }
1483         else if ((delta >= -1) && (delta < 1))
1484         {
1485             line_start.x = (source->rect.left + source->rect.right) / 2;
1486             line_start.y = source->rect.top;
1487             line_end.x = (target->rect.left + target->rect.right) / 2;
1488             line_end.y = target->rect.bottom;
1489         }
1490         else
1491         {
1492             line_start.x = source->rect.right;
1493             line_start.y = (source->rect.top + source->rect.bottom) / 2;
1494             line_end.x = target->rect.left;
1495             line_end.y = (target->rect.top + target->rect.bottom) / 2;
1496         }
1497     }
1498 
1499     connection->line_start = line_start;
1500     connection->line_end = line_end;
1501 }
1502 
1503 ///////////////////////////////////////////////////////////////////////////////
UpdateConnectionPos(flow_item * moved)1504 void screen_flow_diagram_win::UpdateConnectionPos(flow_item *moved)
1505 {
1506     trigger_info *trigger = moved->trigger_list;
1507     flow_item *source;
1508     flow_item *target;
1509     trigger_connection *connection = NULL;
1510 
1511     for (int index = 0; index < mConnectionList.GetCount(); index++)
1512     {
1513         connection = mConnectionList.GetAt(index);
1514         if (connection->source_screen == moved->screen_name)
1515         {
1516             source = moved;
1517             target = mpScreenFlow->GetFlowItem(connection->target_screen);
1518         }
1519         else if (connection->target_screen == moved->screen_name)
1520         {
1521             source = mpScreenFlow->GetFlowItem(connection->source_screen);
1522             target = moved;
1523         }
1524         else
1525         {
1526             continue;
1527         }
1528 
1529         //calculate new connection information
1530         CalculateConnectionPos(connection, source, target);
1531     }
1532 }
1533 
1534 ///////////////////////////////////////////////////////////////////////////////
CheckResizeCursor(CPoint point)1535 int screen_flow_diagram_win::CheckResizeCursor(CPoint point)
1536 {
1537     CRect select_outer;
1538     CRect select_inner;
1539     int drag_mode = DRAG_NONE;
1540 
1541     if (!mpDragItem)
1542     {
1543         ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
1544         return DRAG_NONE;
1545     }
1546 
1547     select_outer =GetScaledRect(mpDragItem->rect);
1548 
1549     select_inner = select_outer;
1550     select_outer.InflateRect(5, 5);
1551 
1552     if (select_outer.PtInRect(point))
1553     {
1554         if (select_inner.PtInRect(point))
1555         {
1556             ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
1557             return DRAG_NONE;
1558         }
1559 
1560         // we are between two rectangles, figure out where:
1561         if (point.y < select_inner.top)
1562         {
1563             if (point.x < select_inner.left)
1564             {
1565                 // top left corner
1566                 ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE));
1567                 drag_mode = DRAG_TOP_LEFT;
1568             }
1569             else
1570             {
1571                 if (point.x >= select_inner.right)
1572                 {
1573                     // top right corner
1574                     ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENESW));
1575                     drag_mode = DRAG_TOP_RIGHT;
1576                 }
1577                 else
1578                 {
1579                     // top
1580                     ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
1581                     drag_mode = DRAG_TOP;
1582                 }
1583             }
1584         }
1585         else
1586         {
1587             if (point.y >= select_inner.bottom)
1588             {
1589                 if (point.x < select_inner.left)
1590                 {
1591                     // bottom left corner
1592                     ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENESW));
1593                     drag_mode = DRAG_BOTTOM_LEFT;
1594                 }
1595                 else
1596                 {
1597                     if (point.x >= select_inner.right)
1598                     {
1599                         // bottom right corner
1600                         ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE));
1601                         drag_mode = DRAG_BOTTOM_RIGHT;
1602                     }
1603                     else
1604                     {
1605                         // bottom
1606                         ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
1607                         drag_mode = DRAG_BOTTOM;
1608                     }
1609                 }
1610             }
1611             else
1612             {
1613                 ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
1614                 if (point.x < select_inner.left)
1615                 {
1616                     drag_mode = DRAG_LEFT;
1617                 }
1618                 else
1619                 {
1620                     drag_mode = DRAG_RIGHT;
1621                 }
1622             }
1623         }
1624     }
1625     else
1626     {
1627         ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
1628         drag_mode = DRAG_NONE;
1629     }
1630     return drag_mode;
1631 }
1632 
1633 ///////////////////////////////////////////////////////////////////////////////
OnHScroll(UINT nSBCode,UINT nPos,CScrollBar * pScrollBar)1634 void screen_flow_diagram_win::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
1635 {
1636     m_scroll_helper->OnHScroll(nSBCode, nPos, pScrollBar);
1637 }
1638 
1639 ///////////////////////////////////////////////////////////////////////////////
OnVScroll(UINT nSBCode,UINT nPos,CScrollBar * pScrollBar)1640 void screen_flow_diagram_win::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
1641 {
1642     m_scroll_helper->OnVScroll(nSBCode, nPos, pScrollBar);
1643 }
1644 
1645 // screen_flow_edit_dlg dialog
1646 
1647 enum screen_flow_edit_dlg_test_commands{
1648     TEST_EDIT_TRIGGER_LIST = 1,
1649     TEST_SAVE_SCREEN_FLOW_EDIT,
1650     TEST_CANCEL_SCREEN_FLOW_EDIT
1651 };
1652 
IMPLEMENT_DYNAMIC(screen_flow_edit_dlg,express_dialog)1653 IMPLEMENT_DYNAMIC(screen_flow_edit_dlg, express_dialog)
1654 
1655 BEGIN_MESSAGE_MAP(screen_flow_edit_dlg, express_dialog)
1656     ON_WM_SIZE()
1657     ON_WM_GETMINMAXINFO()
1658     ON_MESSAGE(STUDIO_TEST, &screen_flow_edit_dlg::OnTestMessage)
1659     ON_MESSAGE(USR_MSG_CHECK_STATE_CHANGE, &screen_flow_edit_dlg::OnShowHideScreenItem)
1660     ON_MESSAGE(USR_MSG_NODE_SELECT, &screen_flow_edit_dlg::OnNodeSelect)
1661 END_MESSAGE_MAP()
1662 
1663 ///////////////////////////////////////////////////////////////////////////////
1664 screen_flow_edit_dlg::screen_flow_edit_dlg(int display, CWnd* pParent /*=NULL*/)
1665     : express_dialog(screen_flow_edit_dlg::IDD, pParent)
1666 {
1667     SetTitleText("Edit Screen Flow");
1668     IconId = IDB_MACRO_PLAYBACK_ICON;
1669     mActiveDisplay = display;
1670 
1671     mpScreenFlow = NULL;
1672     mpOldScreenFlow = NULL;
1673     mpScreenFlowDiagram = NULL;
1674     mpButtonFrame = NULL;
1675 }
1676 
1677 ///////////////////////////////////////////////////////////////////////////////
~screen_flow_edit_dlg()1678 screen_flow_edit_dlg::~screen_flow_edit_dlg()
1679 {
1680     if (mpScreenFlowDiagram)
1681     {
1682         delete mpScreenFlowDiagram;
1683     }
1684 
1685     if (mpButtonFrame)
1686     {
1687         delete mpButtonFrame;
1688     }
1689 }
1690 
1691 ///////////////////////////////////////////////////////////////////////////////
DoDataExchange(CDataExchange * pDX)1692 void screen_flow_edit_dlg::DoDataExchange(CDataExchange* pDX)
1693 {
1694     express_dialog::DoDataExchange(pDX);
1695     studiox_project *project = GetOpenProject();
1696 
1697     if (!project)
1698     {
1699         return;
1700     }
1701 
1702     if (pDX->m_bSaveAndValidate)
1703     {
1704         // Delete old screen flow
1705         if (mpOldScreenFlow)
1706         {
1707             delete mpOldScreenFlow;
1708         }
1709     }
1710     DDX_Control(pDX, IDC_SCREEN_ITEM_TREE, mScreenItemView);
1711 }
1712 
1713 ///////////////////////////////////////////////////////////////////////////////
OnCancel()1714 void screen_flow_edit_dlg::OnCancel()
1715 {
1716     studiox_project *project = GetOpenProject();
1717 
1718     if (project)
1719     {
1720         // Revert back to old scren flow.
1721         project->mDisplays[mActiveDisplay].screenflow = mpOldScreenFlow;
1722         if (mpOldScreenFlow)
1723         {
1724             mpOldScreenFlow->RebuildAnimationIdDictionary(mActiveDisplay);
1725         }
1726     }
1727 
1728     // Delete new screen flow
1729     if (mpScreenFlow)
1730     {
1731         delete mpScreenFlow;
1732 		mpScreenFlow = NULL;
1733     }
1734 
1735     express_dialog::OnCancel();
1736 }
1737 
1738 ///////////////////////////////////////////////////////////////////////////////
InitScreenFlow(int diagram_width,int diagram_height)1739 void screen_flow_edit_dlg::InitScreenFlow(int diagram_width, int diagram_height)
1740 {
1741     studiox_project *project = GetOpenProject();
1742     CArray<widget_info *> screen_list;
1743     if (project)
1744     {
1745         if (project->mDisplays[mActiveDisplay].screenflow)
1746         {
1747             //Save old screen flow
1748             mpOldScreenFlow = new screen_flow(*project->mDisplays[mActiveDisplay].screenflow);
1749         }
1750         else
1751         {
1752             project->mDisplays[mActiveDisplay].screenflow = new screen_flow;
1753         }
1754         mpScreenFlow = project->mDisplays[mActiveDisplay].screenflow;
1755 
1756         mpScreenFlow->GetFlowListCount();
1757 
1758         GetProjectView()->GetTopLevelWidgetList(mActiveDisplay, &screen_list);
1759 
1760         widget_info *screen;
1761 
1762         for (int index = 0; index < screen_list.GetCount(); index++)
1763         {
1764             screen = screen_list.GetAt(index);
1765 
1766             if (!screen->is_template)
1767             {
1768                 mpScreenFlow->CheckAddFlowItem(screen->app_name, diagram_width, diagram_height);
1769             }
1770         }
1771     }
1772 }
1773 
1774 
1775 ///////////////////////////////////////////////////////////////////////////////
OnInitDialog()1776 BOOL screen_flow_edit_dlg::OnInitDialog()
1777 {
1778     express_dialog::OnInitDialog();
1779 
1780     CRect client;
1781     CRect listsize;
1782     CRect size;
1783 
1784     GetClientRect(&client);
1785 
1786     //Calculate screen flow diagram window size
1787     mScreenItemView.GetWindowRect(&listsize);
1788     ScreenToClient(&listsize);
1789 
1790     size.top = listsize.top;
1791     size.left = listsize.right + 5;
1792     size.right = client.right - 10;
1793     size.bottom = listsize.bottom;
1794 
1795     // init screen flow
1796     InitScreenFlow(size.Width(), size.Height());
1797 
1798     mpScreenFlowDiagram = new screen_flow_diagram_win(mActiveDisplay, mpScreenFlow);
1799     mpScreenFlowDiagram->Create(target_class_name, _T("screen flow diagram win"),
1800         WS_VISIBLE | WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_BORDER |WS_TABSTOP, CRect(0, 0, 0, 0), this, 0);
1801     mpScreenFlowDiagram->MoveWindow(&size);
1802     mpScreenFlowDiagram->ShowWindow(SW_SHOW);
1803     mpScreenFlowDiagram->UpdateDisplaySize();
1804 
1805     mScreenItemView.InitImageList();
1806     PopulateScreenItems();
1807 
1808     // create button frame
1809     GetDlgItem(IDC_INCLUDE_SCREEN_PROMPT)->GetWindowRect(&listsize);
1810     ScreenToClient(&listsize);
1811 
1812     size.top = listsize.top;
1813     size.left = listsize.right + 5;
1814     size.right = client.right - 10;
1815     size.bottom = listsize.bottom;
1816 
1817     mpButtonFrame = new screen_flow_button_frame(mpScreenFlow, this);
1818     mpButtonFrame->CreateEx(WS_EX_CONTROLPARENT, target_class_name, _T("screen flow button frame"), WS_VISIBLE | WS_CHILD, CRect(0, 0, 0, 0), this, 0);
1819     mpButtonFrame->SetWindowPos(&mScreenItemView, size.left, size.top, size.Width(), size.Height(), 0);
1820     mpButtonFrame->ShowWindow(SW_SHOW);
1821 
1822     //Add cancel button
1823     AddCancelButton();
1824 
1825     //add save button
1826     AddSaveButton();
1827 
1828     PositionChildren();
1829 
1830     return TRUE;
1831 }
1832 
1833 ///////////////////////////////////////////////////////////////////////////////
PositionChildren()1834 void screen_flow_edit_dlg::PositionChildren()
1835 {
1836     CRect client;
1837     CRect size;
1838 
1839     GetClientRect(&client);
1840 
1841     if (!mpScreenFlowDiagram)
1842     {
1843         return;
1844     }
1845 
1846     // Calculate screen flow diagram window size
1847     mScreenItemView.GetWindowRect(&size);
1848     ScreenToClient(&size);
1849 
1850     size.bottom = client.bottom - m_status_bar_height - 10;
1851 
1852     // position screen item view
1853     mScreenItemView.MoveWindow(&size);
1854 
1855     size.left = size.right + 5;
1856     size.right = client.right - 10;
1857 
1858     // position screen flow
1859     mpScreenFlowDiagram->MoveWindow(&size);
1860 
1861     // position button frame
1862     GetDlgItem(IDC_INCLUDE_SCREEN_PROMPT)->GetWindowRect(&size);
1863     ScreenToClient(&size);
1864 
1865     size.left = size.right + 5;
1866     size.right = client.right - 10;
1867 
1868     mpButtonFrame->MoveWindow(&size);
1869 
1870     Invalidate();
1871 }
1872 
1873 ///////////////////////////////////////////////////////////////////////////////
OnSize(UINT nType,int cx,int cy)1874 void screen_flow_edit_dlg::OnSize(UINT nType, int cx, int cy)
1875 {
1876     express_dialog::OnSize(nType, cx, cy);
1877 
1878     PositionChildren();
1879 }
1880 
1881 ///////////////////////////////////////////////////////////////////////////////
OnGetMinMaxInfo(MINMAXINFO * lpMMI)1882 void screen_flow_edit_dlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
1883 {
1884     express_dialog::OnGetMinMaxInfo(lpMMI);
1885 
1886     lpMMI->ptMinTrackSize.x = MIN_SCREEN_FLOW_EDIT_DLG_WIDTH;
1887     lpMMI->ptMinTrackSize.y = MIN_SCREEN_FLOW_EDIT_DLG_HEIGHT;
1888 }
1889 
1890 ///////////////////////////////////////////////////////////////////////////////
PopulateScreenItems()1891 VOID screen_flow_edit_dlg::PopulateScreenItems()
1892 {
1893     if (!mpScreenFlow)
1894     {
1895         return;
1896     }
1897 
1898     flow_item *flow;
1899     int state;
1900     HTREEITEM hParent;
1901     HTREEITEM hItem;
1902 
1903     studiox_project *project = GetOpenProject();
1904 
1905     folder_info *folder = project->mDisplays[mActiveDisplay].GetFirstChildFolder();
1906     widget_info *info;
1907 
1908     while (folder)
1909     {
1910         hParent = mScreenItemView.InsertItem(folder->folder_name);
1911 
1912         info = folder->GetFirstChildWidget();
1913 
1914         while (info)
1915         {
1916             flow = mpScreenFlow->GetFlowItem(info->app_name);
1917 
1918             if (flow)
1919             {
1920                 if (flow->enabled)
1921                 {
1922                     state = CUSTOM_TV_STATE_CHECKED;
1923                 }
1924                 else
1925                 {
1926                     state = CUSTOM_TV_STATE_UNCHECKED;
1927                 }
1928 
1929                 hItem = mScreenItemView.InsertItem(flow->screen_name, hParent);
1930                 mScreenItemView.SetItemState(hItem, state);
1931             }
1932 
1933             info = info->GetNextWidgetInfo();
1934         }
1935 
1936         mScreenItemView.Expand(hParent, TVE_EXPAND);
1937         state = mScreenItemView.GetChildrenState(hParent);
1938         mScreenItemView.SetItemState(hParent, state);
1939 
1940         folder = folder->GetNextFolder();
1941     }
1942 }
1943 
1944 ///////////////////////////////////////////////////////////////////////////////
OnShowHideScreenItem(WPARAM wParam,LPARAM lParam)1945 LRESULT screen_flow_edit_dlg::OnShowHideScreenItem(WPARAM wParam, LPARAM lParam)
1946 {
1947     HTREEITEM hItem = (HTREEITEM)lParam;
1948 
1949     UINT state = wParam;
1950 
1951     CString name = mScreenItemView.GetItemText(hItem);
1952     HTREEITEM parent = mScreenItemView.GetParentItem(hItem);
1953     flow_item *item;
1954 
1955     BOOL enabled;
1956 
1957     if (state == CUSTOM_TV_STATE_CHECKED)
1958     {
1959         enabled = TRUE;
1960     }
1961     else
1962     {
1963         enabled = FALSE;
1964     }
1965 
1966     CRect client;
1967     mpScreenFlowDiagram->GetClientRect(&client);
1968 
1969     if (parent)
1970     {
1971         //top level screen
1972         item = mpScreenFlow->GetFlowItem(name);
1973 
1974         if (item)
1975         {
1976             item->enabled = enabled;
1977 
1978             if (enabled)
1979             {
1980                 mpScreenFlow->UpdateFlowItemRect(item, client.Width(), client.Height());
1981                 mpScreenFlowDiagram->UpdateConnectionPos(item);
1982                 mpScreenFlowDiagram->SelectFlowItem(item);
1983             }
1984             else
1985             {
1986                 mpScreenFlowDiagram->HideFlowItem(item);
1987             }
1988         }
1989     }
1990     else
1991     {
1992         //folder
1993         studiox_project *project = GetOpenProject();
1994 
1995         if (!project)
1996         {
1997             return -1;
1998         }
1999         folder_info *folder = project->FindFolderInfo(mActiveDisplay, name);
2000         widget_info *info;
2001 
2002         if (folder)
2003         {
2004             info = folder->GetFirstChildWidget();
2005 
2006 
2007             while (info)
2008             {
2009                 item = mpScreenFlow->GetFlowItem(info->app_name);
2010 
2011                 if (item)
2012                 {
2013                     item->enabled = enabled;
2014 
2015                     if (enabled)
2016                     {
2017                         mpScreenFlow->UpdateFlowItemRect(item, client.Width(), client.Height());
2018                         mpScreenFlowDiagram->UpdateConnectionPos(item);
2019                     }
2020                     else
2021                     {
2022                         mpScreenFlowDiagram->HideFlowItem(item);
2023                     }
2024                 }
2025                 info = info->GetNextWidgetInfo();
2026             }
2027         }
2028     }
2029 
2030     mpScreenFlowDiagram->UpdateDisplaySize();
2031     mpScreenFlowDiagram->Invalidate();
2032 
2033     return 0;
2034 }
2035 
2036 ///////////////////////////////////////////////////////////////////////////////
OnNodeSelect(WPARAM wParam,LPARAM lParam)2037 LRESULT screen_flow_edit_dlg::OnNodeSelect(WPARAM wParam, LPARAM lParam)
2038 {
2039     HTREEITEM hItem = (HTREEITEM)lParam;
2040     HTREEITEM parent = mScreenItemView.GetParentItem(hItem);
2041 
2042     if (parent)
2043     {
2044         //top level screen
2045         CString name = mScreenItemView.GetItemText(hItem);
2046         flow_item *item = mpScreenFlow->GetFlowItem(name);
2047         mpScreenFlowDiagram->SelectFlowItem(item);
2048     }
2049 
2050     return 0;
2051 }
2052 
2053 ///////////////////////////////////////////////////////////////////////////////
PreTranslateMessage(MSG * pMsg)2054 BOOL screen_flow_edit_dlg::PreTranslateMessage(MSG* pMsg)
2055 {
2056     // TODO: Add your specialized code here and/or call the base class
2057     if (pMsg->message == WM_KEYDOWN)
2058     {
2059         if (pMsg->wParam == VK_RETURN && GetFocus() == &mScreenItemView)
2060         {
2061             HTREEITEM hItem = mScreenItemView.GetSelectedItem();
2062             HTREEITEM parent = mScreenItemView.GetParentItem(hItem);
2063 
2064             if (parent)
2065             {
2066                 if (mScreenItemView.GetItemCheckState(hItem) == CUSTOM_TV_STATE_CHECKED)
2067                 {
2068                     mpScreenFlowDiagram->HandleKeydown(VK_RETURN);
2069                 }
2070             }
2071             else
2072             {
2073                 if (mScreenItemView.GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED)
2074                 {
2075                     mScreenItemView.Expand(hItem, TVE_COLLAPSE);
2076                 }
2077                 else
2078                 {
2079                     mScreenItemView.Expand(hItem, TVE_EXPAND);
2080                 }
2081             }
2082 
2083             return TRUE;
2084         }
2085     }
2086 
2087     return express_dialog::PreTranslateMessage(pMsg);
2088 }
2089 
2090 ///////////////////////////////////////////////////////////////////////////////
OnTestMessage(WPARAM wParam,LPARAM lParam)2091 LRESULT screen_flow_edit_dlg::OnTestMessage(WPARAM wParam, LPARAM lParam)
2092 {
2093     flow_item *item;
2094     CString screen_name;
2095     //int scale;
2096 
2097     switch (wParam)
2098     {
2099     case TEST_EDIT_TRIGGER_LIST:
2100         screen_name = GetTestingParam(1);
2101         item = mpScreenFlow->GetFlowItem(screen_name);
2102         if (item && mpScreenFlowDiagram)
2103         {
2104             mpScreenFlowDiagram->EditFlowItem(item);
2105 /*            scale = mpScreenFlowDiagram->GetScale();
2106             mpScreenFlowDiagram->SendMessage(WM_RBUTTONDOWN, MK_RBUTTON,
2107                 MAKELPARAM(MulDiv(item->rect.left, scale, 100), MulDiv(item->rect.top, scale, 100)));
2108             mpScreenFlowDiagram->SendMessage(WM_RBUTTONUP, MK_RBUTTON,
2109                 MAKELPARAM(MulDiv(item->rect.left, scale, 100), MulDiv(item->rect.top, scale, 100)));
2110 */
2111         }
2112         break;
2113 
2114     case TEST_SAVE_SCREEN_FLOW_EDIT:
2115         OnOK();
2116         break;
2117 
2118     case TEST_CANCEL_SCREEN_FLOW_EDIT:
2119         OnCancel();
2120         break;
2121     }
2122 
2123     return 0;
2124 }
2125