1 
2 #include "studiox_includes.h"
3 
4 #ifdef _DEBUG
5 #define new DEBUG_NEW
6 #endif
7 
8 #define SELECT_BOX_LINE_WIDTH 1
9 #define SELECT_HANDLE_SIZE 5
10 #define DEFAULT_CROSSHAIR_SIZE 10
11 
12 int vsnap_line_list[SNAP_LINE_TYPE_COUNT / 2] = {
13     SNAP_LINE_TYPE_LEFT,
14     SNAP_LINE_TYPE_VERTICAL,
15     SNAP_LINE_TYPE_RIGHT
16 };
17 
18 int hsnap_line_list[SNAP_LINE_TYPE_COUNT / 2] = {
19     SNAP_LINE_TYPE_TOP,
20     SNAP_LINE_TYPE_HORIZONTAL,
21     SNAP_LINE_TYPE_BOTTOM
22 };
23 
24 CArray<WIDGET_SELECT_ENTRY> SelectedWidgets;
25 #define DRAG_ALL        NUM_SIZE_HANDLES
26 ULONG select_pattern = 0xf0f0f0f0;
27 
28 enum drag_modes {
29     DRAG_NONE = 0,
30     DRAG_TOP_LEFT,
31     DRAG_TOP,
32     DRAG_TOP_RIGHT,
33     DRAG_RIGHT,
34     DRAG_BOTTOM_RIGHT,
35     DRAG_BOTTOM,
36     DRAG_BOTTOM_LEFT,
37     DRAG_LEFT,
38     DRAG_ALL
39 };
40 
41 enum target_screen_test_commands{
42     TEST_GENERATE_CHECKSUM = 1,
43     TEST_GENERATE_SCREENSHOT,
44     TEST_DESELECT,
45     TEST_DIRTY_ROOT_WINDOW,
46     TEST_MOVE_WINDOW,
47     TEST_MOVE_SELECTED,
48     TEST_ADD_WIDGET,
49     TEST_ADD_TEMPLATE,
50     TEST_ZOOM_IN,
51     TEST_LBUTTON_DOWN,
52     TEST_LBUTTON_UP,
53     TEST_MOUSEMOVE,
54     TEST_MOUSEMOVE_POST
55 };
56 
57 ///////////////////////////////////////////////////////////////////////////////
58 // the custom drawing function for my GUI selection box:
59 extern "C" {
SelectBoxDraw(GX_WIDGET * widget)60 VOID SelectBoxDraw(GX_WIDGET *widget)
61 {
62     int count = SelectedWidgets.GetCount();
63     int index;
64 
65     for (index = 0; index < count; index++)
66     {
67         WIDGET_SELECT_ENTRY selected = SelectedWidgets.GetAt(index);
68         if (selected.info->widget == widget)
69         {
70             // we found the widget, call it's original draw function
71             selected.draw_func(widget);
72 
73             // draw the outer outline
74             gx_context_raw_brush_define(0x00ffffff, 0x00000000, GX_BRUSH_OUTLINE);
75             gx_context_brush_width_set(1);
76             gx_context_brush_pattern_set(select_pattern);
77             gx_canvas_rectangle_draw(&widget->gx_widget_size);
78             gx_context_brush_pattern_set(0);
79             break;
80         }
81     }
82 }
83 }
84 ///////////////////////////////////////////////////////////////////////////////
RefreshSelectedWidgets()85 void RefreshSelectedWidgets()
86 {
87     int index;
88     int count = SelectedWidgets.GetCount();
89 
90     if ((!count) || IsGuixCanvasRefreshBlocked())
91     {
92         return;
93     }
94 
95     ULONG temp = select_pattern  & 0x03;
96     select_pattern >>= 2;
97     temp <<= 30;
98     select_pattern |= temp;
99 
100     GX_RECTANGLE invalid;
101 
102     invalid = SelectedWidgets[0].info->widget->gx_widget_size;
103 
104     for (index = 1; index < count; index++)
105     {
106         gx_utility_rectangle_combine(&invalid, &SelectedWidgets[index].info->widget->gx_widget_size);
107     }
108     GX_CANVAS *canvas;
109     gx_widget_canvas_get(SelectedWidgets[0].info->widget, &canvas);
110 
111     GX_ENTER_CRITICAL
112     _gx_canvas_drawing_initiate(canvas,
113         (GX_WIDGET *) get_root_window(), &invalid);
114 
115     gx_context_raw_brush_define(0x00ffffff, 0x00000000, GX_BRUSH_OUTLINE);
116     gx_context_brush_width_set(1);
117 
118     for (index = 0; index < count; index++)
119     {
120         WIDGET_SELECT_ENTRY entry = SelectedWidgets[index];
121         _gx_canvas_drawing_initiate(canvas,
122             entry.info->widget, &entry.info->widget->gx_widget_size);
123         gx_context_brush_pattern_set(select_pattern);
124         gx_canvas_rectangle_draw(&entry.info->widget->gx_widget_size);
125         _gx_canvas_drawing_complete(canvas, GX_FALSE);
126     }
127     gx_context_brush_pattern_set(0);
128 
129     /* Indicate that drawing on this canvas is complete.  */
130     _gx_canvas_drawing_complete(canvas, GX_TRUE);
131     GX_EXIT_CRITICAL
132 
133     WPARAM wparam = MAKEWPARAM(invalid.gx_rectangle_left, invalid.gx_rectangle_top);
134     LPARAM lparam = MAKELPARAM(invalid.gx_rectangle_right, invalid.gx_rectangle_bottom);
135     PostMessage(get_target_win_handle(), GUIX_DIRTY, wparam, lparam);
136 }
137 
138 
139 ///////////////////////////////////////////////////////////////////////////////
140 VOID  _gx_system_timer_update(VOID);
141 
TimerProc(_In_ HWND hwnd,_In_ UINT uMsg,_In_ UINT_PTR idEvent,_In_ DWORD dwTime)142 VOID CALLBACK TimerProc(
143   _In_  HWND hwnd,
144   _In_  UINT uMsg,
145   _In_  UINT_PTR idEvent,
146   _In_  DWORD dwTime)
147 {
148     //_gx_system_timer_update();
149     RefreshSelectedWidgets();
150 }
151 
BEGIN_MESSAGE_MAP(target_screen,CWnd)152 BEGIN_MESSAGE_MAP(target_screen, CWnd)
153 	ON_WM_PAINT()
154     ON_WM_ERASEBKGND()
155     ON_WM_CREATE()
156     ON_WM_LBUTTONDOWN()
157     ON_WM_LBUTTONUP()
158     ON_WM_MOUSEMOVE()
159     ON_WM_RBUTTONDOWN()
160     ON_MESSAGE(GUIX_READY, target_screen::OnGuixReady)
161     ON_MESSAGE(GUIX_DIRTY, target_screen::OnGuixDirty)
162     ON_MESSAGE(STUDIO_TEST, OnTestMessage)
163 END_MESSAGE_MAP()
164 
165 ///////////////////////////////////////////////////////////////////////////////
166 target_screen::target_screen()
167 {
168     GX_RECTANGLE size;
169     gx_utility_rectangle_define(&size, 0, 0, 0, 0);
170     SelectedWidgets.RemoveAll();
171     mpSelectedParent = NULL;
172     m_display_index = -1;
173     mDragMode = DRAG_NONE;
174     mpDragSelected = NULL;
175     mFoldUndo = FALSE;
176     mZoomScale = 100;
177     mGridSnapInfo.crosshair_enabled = FALSE;
178     mGridSnapInfo.crosshair_size = DEFAULT_CROSSHAIR_SIZE;
179     mGridSnapInfo.snap_line_count = 0;
180 }
181 
182 ///////////////////////////////////////////////////////////////////////////////
PreCreateWindow(CREATESTRUCT & cs)183 BOOL target_screen::PreCreateWindow(CREATESTRUCT& cs)
184 {
185 	if( !CWnd::PreCreateWindow(cs) )
186 		return FALSE;
187 	// TODO: Modify the Window class or styles here by modifying
188 	//  the CREATESTRUCT cs
189 
190 	return TRUE;
191 }
192 
193 ///////////////////////////////////////////////////////////////////////////////
UpdateWindowPos()194 void target_screen::UpdateWindowPos()
195 {
196     target_frame *frame = (target_frame *)GetParent();
197     CRect frame_size;
198     CRect size;
199     int width;
200     int height;
201 
202     GetClientRect(&size);
203     width = size.Width();
204     height = size.Height();
205 
206     frame->GetClientRect(&frame_size);
207 
208     if (size.Width() > frame_size.Width())
209     {
210         size.left -= frame->GetScrollPos(SB_HORZ);
211     }
212     else
213     {
214         size.left = (frame_size.Width() - width) >> 1;
215     }
216 
217     if (size.Height() > frame_size.Height())
218     {
219         size.top = -frame->GetScrollPos(SB_VERT);
220     }
221     else
222     {
223         size.top = (frame_size.Height() - height) >> 1;
224     }
225 
226     size.right = size.left + width;
227     size.bottom = size.top + height;
228 
229     MoveWindow(&size);
230     GX_WIDGET *root = (GX_WIDGET *) get_root_window();
231     gx_system_dirty_mark(root);
232 }
233 
234 ///////////////////////////////////////////////////////////////////////////////
OnCreate(LPCREATESTRUCT lpCreateStruct)235 int target_screen::OnCreate(LPCREATESTRUCT lpCreateStruct)
236 {
237     CWnd::OnCreate(lpCreateStruct);
238     SetWindowText(_T("Target Screen"));
239     CenterWindow();
240     EnableWindow(TRUE);
241     initialize_guix(m_hWnd);
242     SetTimer(1, 500, TimerProc);
243     return 0;
244 }
245 
246 ///////////////////////////////////////////////////////////////////////////////
OnCloseProject(void)247 void target_screen::OnCloseProject(void)
248 {
249     GX_DISPLAY *target_display = get_target_view_display();
250     SwitchTopWidget(NULL);
251     GetResourceView()->CleanupDisplayResources(target_display);
252     GetTargetScreen()->ConfigureDisplay(-1);
253     guix_cleanup_target_win_canvas();
254 }
255 
256 ///////////////////////////////////////////////////////////////////////////////
FindSelectedWidget(GX_POINT point)257 GX_WIDGET *target_screen::FindSelectedWidget(GX_POINT point)
258 {
259     for (int index = 0; index < SelectedWidgets.GetCount(); index++)
260     {
261         if (gx_utility_rectangle_point_detect(&SelectedWidgets[index].info->widget->gx_widget_size, point))
262         {
263             return SelectedWidgets[index].info->widget;
264         }
265     }
266     return NULL;
267 }
268 ///////////////////////////////////////////////////////////////////////////////
269 /*return parent type. return 0 while do not have parent or pointer is wrong.*/
GetWidgetParentType(widget_info * info)270 USHORT target_screen::GetWidgetParentType(widget_info *info)
271 {
272     GX_WIDGET *parent = NULL;
273     USHORT type = 0;
274 
275     if (info)
276     {
277         if (info->widget)
278         {
279             parent = info->widget->gx_widget_parent;
280             if (parent)
281             {
282                 type = parent->gx_widget_type;
283             }
284         }
285     }
286     return type;
287 }
288 
289 ///////////////////////////////////////////////////////////////////////////////
290 // is this moving of child widget of horizontal/vertical list allowed?
IsWidgetResizable(USHORT parent_type,widget_info * info,GX_RECTANGLE & new_size)291 BOOL target_screen::IsWidgetResizable(USHORT parent_type, widget_info *info, GX_RECTANGLE &new_size)
292 {
293 
294     studiox_project *project = GetOpenProject();
295 
296     if (!project)
297     {
298         return FALSE;
299     }
300 
301     if (project->IsWidgetPositionLocked())
302     {
303         if (info->size.gx_rectangle_left != new_size.gx_rectangle_left ||
304             info->size.gx_rectangle_top != new_size.gx_rectangle_top ||
305             info->size.gx_rectangle_right != new_size.gx_rectangle_right ||
306             info->size.gx_rectangle_bottom != new_size.gx_rectangle_bottom)
307         {
308             Notify("Widget position is locked, resize is not allowed!");
309             return FALSE;
310         }
311     }
312 
313     switch (parent_type)
314     {
315     case GX_TYPE_HORIZONTAL_LIST:
316         if ((info->size.gx_rectangle_left != new_size.gx_rectangle_left) ||
317             (info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
318             (info->size.gx_rectangle_bottom != new_size.gx_rectangle_bottom))
319         {
320             Notify("Only right-side size change of horizontal list child widget is allowed.");
321             return FALSE;
322         }
323         break;
324 
325     case GX_TYPE_VERTICAL_LIST:
326         if ((info->size.gx_rectangle_left != new_size.gx_rectangle_left) ||
327             (info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
328             (info->size.gx_rectangle_right != new_size.gx_rectangle_right))
329         {
330             Notify("Only bottom-side size change of vertical list child widget is allowed.");
331             return FALSE;
332         }
333         break;
334 
335     case GX_TYPE_ACCORDION_MENU:
336         if ((info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
337             (info->size.gx_rectangle_left != new_size.gx_rectangle_left) ||
338             (info->size.gx_rectangle_right != new_size.gx_rectangle_right))
339         {
340             Notify("Only bottom-side size change of accordion menu child widget is allowed.");
341             return FALSE;
342         }
343         break;
344 
345     case GX_TYPE_MENU_LIST:
346         if ((info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
347             (info->size.gx_rectangle_left != new_size.gx_rectangle_left))
348         {
349             Notify("Only bottom and right side size change of menu list child widget is allowed.");
350             return FALSE;
351         }
352         break;
353 
354     case GX_TYPE_TREE_VIEW:
355         if ((info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
356             (info->size.gx_rectangle_left != new_size.gx_rectangle_left))
357         {
358             Notify("Only bottom and right side size change of tree view child widget is allowed.");
359             return FALSE;
360         }
361         break;
362 
363     case GX_TYPE_GENERIC_SCROLL_WHEEL:
364         return FALSE;
365     }
366 
367     return TRUE;
368 }
369 
370 ///////////////////////////////////////////////////////////////////////////////
SelectedWidgetsCanBeMoved()371 BOOL target_screen::SelectedWidgetsCanBeMoved()
372 {
373     GX_WIDGET *selected;
374     studiox_project *project;
375 
376     project = GetOpenProject();
377     if (!project)
378     {
379         return FALSE;
380     }
381 
382     if (project->IsWidgetPositionLocked())
383     {
384         return FALSE;
385     }
386 
387     for (int index = 0; index < SelectedWidgets.GetCount(); index++)
388     {
389         selected = SelectedWidgets[index].info->widget;
390 
391         switch(selected->gx_widget_type)
392         {
393         case GX_TYPE_VERTICAL_SCROLL:
394         case GX_TYPE_HORIZONTAL_SCROLL:
395             return FALSE;
396 
397         default:
398             break;
399         }
400 
401         if (selected->gx_widget_parent)
402         {
403             switch (selected->gx_widget_parent->gx_widget_type)
404             {
405             case GX_TYPE_VERTICAL_LIST:
406             case GX_TYPE_HORIZONTAL_LIST:
407             case GX_TYPE_ACCORDION_MENU:
408             case GX_TYPE_MENU_LIST:
409             case GX_TYPE_TREE_VIEW:
410             case GX_TYPE_GENERIC_SCROLL_WHEEL:
411                 return FALSE;
412             }
413         }
414     }
415     return TRUE;
416 }
417 
418 ///////////////////////////////////////////////////////////////////////////////
OnLButtonDown(UINT nFlags,CPoint point)419 void target_screen::OnLButtonDown(UINT nFlags, CPoint point)
420 {
421     GX_POINT gxp;
422     int scale = GetZoomScale();
423 
424     point.x = point.x * 100 / scale;
425     point.y = point.y * 100 / scale;
426 
427     gxp.gx_point_x = (GX_VALUE)point.x;
428     gxp.gx_point_y = (GX_VALUE)point.y;
429 
430     mFoldUndo = FALSE;
431 
432     if (nFlags & MK_CONTROL)
433     {
434         SelectWidget(gxp, TRUE);
435         return;
436     }
437 
438     mDragMode = CheckResizeCursor(point);
439 
440     if (mDragMode != DRAG_NONE)
441     {
442         mDragStart = gxp;
443     }
444     else
445     {
446         if (!SelectWidget(gxp))
447         {
448             // Add a check here to see if the click is inside one of multiple:
449             GX_WIDGET* find = FindSelectedWidget(gxp);
450             if (find && SelectedWidgetsCanBeMoved())
451             {
452                 mDragMode = DRAG_ALL;
453                 mDragStart = gxp;
454                 mpDragSelected = find;
455             }
456         }
457     }
458 
459     if ((nFlags & MK_LBUTTON) && (mDragMode != DRAG_NONE))
460     {
461         int delta_x = 0;
462         int delta_y = 0;
463         CalSnapDelta(delta_x, delta_y, 0);
464     }
465 }
466 
467 ///////////////////////////////////////////////////////////////////////////////
OnRButtonDown(UINT nFlags,CPoint pos)468 void target_screen::OnRButtonDown(UINT nFlags, CPoint pos)
469 {
470     OnLButtonDown(nFlags, pos);
471 
472     widget_info *selected = GetSingleSelect();
473 
474     if (selected)
475     {
476         CMenu menu;
477         CMenu* pPopup;
478 
479         //Load top level menu
480         menu.LoadMenu(IDR_WIDGET_MENU);
481         pPopup = menu.GetSubMenu(0);
482         ClientToScreen(&pos);
483 
484         CMainFrame *pMain = (CMainFrame *)AfxGetMainWnd();
485         CMenu insert_menu;
486         CMenu base_menu;
487         CMenu *pInsertMenu;
488 
489         insert_menu.LoadMenu(IDR_INSERT_MENU);
490         pInsertMenu = insert_menu.GetSubMenu(0);
491 
492         if (pInsertMenu)
493         {
494             pInsertMenu->RemoveMenu(ID_INSERT_FOLDER, MF_BYCOMMAND);
495 
496             if (GetProjectView()->CreateBaseMenu(&base_menu))
497             {
498                 pInsertMenu->AppendMenu(MF_POPUP, (UINT)base_menu.m_hMenu, _T("Template"));
499             }
500 
501             pPopup->AppendMenu(MF_POPUP, (UINT)pInsertMenu->m_hMenu, _T("Insert"));
502         }
503 
504         //show pop up menu
505         pPopup->TrackPopupMenu(TPM_LEFTALIGN, pos.x, pos.y, (CMainFrame *) AfxGetMainWnd());
506     }
507 }
508 
509 ///////////////////////////////////////////////////////////////////////////////
OnLButtonUp(UINT nFlags,CPoint point)510 void target_screen::OnLButtonUp(UINT nFlags, CPoint point)
511 {
512     mDragMode = DRAG_NONE;
513     mFoldUndo = FALSE;
514 
515     if (mGridSnapInfo.crosshair_enabled)
516     {
517         InvalidateCrosshairArea();
518         mGridSnapInfo.crosshair_enabled = FALSE;
519     }
520 
521     if (mGridSnapInfo.snap_line_count)
522     {
523         InvalidateSnapLineArea();
524         mGridSnapInfo.snap_line_count = 0;
525     }
526 
527     mpDragSelected = NULL;
528 }
529 
530 ///////////////////////////////////////////////////////////////////////////////
531 /*The following two functions will reposition the neibor widget.*/
RepositionListChildren(widget_info * info)532 void target_screen::RepositionListChildren(widget_info *info)
533 {
534     widget_info *neighbor_info;
535     USHORT type = GetWidgetParentType(info);
536     GX_RECTANGLE newsize;
537 
538     if ((type == GX_TYPE_VERTICAL_LIST) ||
539         (type == GX_TYPE_ACCORDION_MENU))
540     {
541         if (info->GetNextWidgetInfo())
542         {
543             neighbor_info = info->GetNextWidgetInfo();
544             int shift = neighbor_info->size.gx_rectangle_top - info->size.gx_rectangle_bottom;
545             while (neighbor_info)
546             {
547                 /*Reposition the nether neighbor widgets(if has one). */
548                 newsize = neighbor_info->size;
549                 newsize.gx_rectangle_top -= shift;
550                 newsize.gx_rectangle_bottom -= shift;
551 
552                 widget_factory::MoveWidget(neighbor_info, newsize);
553                 neighbor_info = neighbor_info->GetNextWidgetInfo();
554             }
555         }
556     }
557     else
558     {
559         if (type == GX_TYPE_HORIZONTAL_LIST)
560         {
561             if (info->GetNextWidgetInfo())
562             {
563                 neighbor_info = info->GetNextWidgetInfo();
564                 INT shift = neighbor_info->size.gx_rectangle_left - info->size.gx_rectangle_right;
565                 /*Reposition the right neighbor widgets(if has one).*/
566                 while (neighbor_info)
567                 {
568                     newsize = neighbor_info->size;
569                     newsize.gx_rectangle_left -= shift;
570                     newsize.gx_rectangle_right -= shift;
571                     widget_factory::MoveWidget(neighbor_info, newsize);
572                     neighbor_info = neighbor_info->GetNextWidgetInfo();
573                 }
574             }
575         }
576     }
577 }
578 
579 
580 ///////////////////////////////////////////////////////////////////////////////
WidgetWasMoved(widget_info * info)581 void target_screen::WidgetWasMoved(widget_info *info)
582 {
583     /*Check the basetype of the widget and its parent to
584       see if we need to reposition the parent widget.*/
585 
586     if (!info)
587     {
588         return;
589     }
590 
591     USHORT parent_type = GetWidgetParentType(info);
592     widget_info *menu_info;
593 
594     switch (info->basetype)
595     {
596     case GX_TYPE_VERTICAL_LIST:
597     case GX_TYPE_HORIZONTAL_LIST:
598     case GX_TYPE_ACCORDION_MENU:
599     case GX_TYPE_TREE_VIEW:
600     case GX_TYPE_GENERIC_SCROLL_WHEEL:
601         GetProjectView()->CheckParentRefresh(info);
602         break;
603 
604     default:
605         switch (parent_type)
606         {
607         case GX_TYPE_HORIZONTAL_LIST:
608         case GX_TYPE_VERTICAL_LIST:
609             RepositionListChildren(info);
610             break;
611 
612         case GX_TYPE_ACCORDION_MENU:
613         case GX_TYPE_TREE_VIEW:
614             menu_info = GetOpenProject()->FindWidgetInfo(info->widget->gx_widget_parent);
615             gx_system_dirty_mark(menu_info->widget);
616             GetProjectView()->CheckParentRefresh(menu_info);
617             break;
618 
619         case GX_TYPE_MENU_LIST:
620             {
621                 GX_MENU_LIST *menu_list = (GX_MENU_LIST *)info->widget->gx_widget_parent;
622 
623                 menu_info = GetOpenProject()->FindWidgetInfo(menu_list->gx_menu_list_owner);
624                 GetProjectView()->CheckParentRefresh(menu_info);
625             }
626             break;
627         }
628         break;
629     }
630 }
631 
632 ///////////////////////////////////////////////////////////////////////////////
GetSingleSelect()633 widget_info *target_screen::GetSingleSelect()
634 {
635     if (SelectedWidgets.GetCount() == 1)
636     {
637         return SelectedWidgets.GetAt(0).info;
638     }
639     return NULL;
640 }
641 
642 ///////////////////////////////////////////////////////////////////////////////
IsWidgetSelected(GX_WIDGET * widget)643 BOOL target_screen::IsWidgetSelected(GX_WIDGET *widget)
644 {
645     for (int index = 0; index < SelectedWidgets.GetCount(); index++)
646     {
647         if (SelectedWidgets.GetAt(index).info->widget == widget)
648         {
649             return TRUE;
650         }
651     }
652     return FALSE;
653 }
654 
655 ///////////////////////////////////////////////////////////////////////////////
CopySelectedWidgets()656 void target_screen::CopySelectedWidgets()
657 {
658     widget_info *selected;
659     CArray<widget_info *> info_list;
660     int index;
661     studiox_project *project = GetOpenProject();
662 
663     if (!project)
664     {
665         return;
666     }
667 
668     for (index = 0; index < SelectedWidgets.GetCount(); index++)
669     {
670         selected = SelectedWidgets[index].info;
671 
672         if (selected)
673         {
674             info_list.Add(selected);
675         }
676     }
677 
678     if (info_list.GetCount())
679     {
680         copy_paste_engine cpe;
681         cpe.CopyToClipboard(info_list, m_hWnd);
682     }
683 }
684 
685 ///////////////////////////////////////////////////////////////////////////////
ShiftSelectedWidgets(int delta_x,int delta_y)686 void target_screen::ShiftSelectedWidgets(int delta_x, int delta_y)
687 {
688     widget_info *selected;
689     GX_RECTANGLE size;
690     int index;
691 
692     UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets, mFoldUndo);
693     mFoldUndo = TRUE;
694 
695     for (index = 0; index < SelectedWidgets.GetCount(); index++)
696     {
697         selected = SelectedWidgets[index].info;
698 
699         if (selected)
700         {
701             size = selected->widget->gx_widget_size;
702             gx_utility_rectangle_shift(&size, delta_x, delta_y);
703             widget_factory::MoveWidget(selected, size);
704         }
705     }
706 
707     GetPropsWin()->WidgetWasMoved();
708 }
709 
710 ///////////////////////////////////////////////////////////////////////////////
CheckResizeCursor(CPoint point)711 int target_screen::CheckResizeCursor(CPoint point)
712 {
713     GX_RECTANGLE select_outer;
714     GX_RECTANGLE select_inner;
715     GX_POINT test;
716     int drag_mode = DRAG_NONE;
717 
718     widget_info *selected = GetSingleSelect();
719     if (!selected)
720     {
721        ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
722         return DRAG_NONE;
723     }
724 
725     if (selected->widget->gx_widget_type == GX_TYPE_HORIZONTAL_SCROLL ||
726         selected->widget->gx_widget_type == GX_TYPE_VERTICAL_SCROLL)
727     {
728        ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
729         return DRAG_NONE;
730     }
731 
732     select_outer = selected->widget->gx_widget_size;
733     select_inner = select_outer;
734     gx_utility_rectangle_resize(&select_outer, 5);
735     test.gx_point_x = (GX_VALUE)point.x;
736     test.gx_point_y = (GX_VALUE)point.y;
737 
738     if (gx_utility_rectangle_point_detect(&select_outer, test))
739     {
740         if (gx_utility_rectangle_point_detect(&select_inner, test))
741         {
742             ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
743             return DRAG_NONE;
744         }
745 
746         // we are between two rectangles, figure out where:
747         if (test.gx_point_y < select_inner.gx_rectangle_top)
748         {
749             if (test.gx_point_x < select_inner.gx_rectangle_left)
750             {
751                 // top left corner
752                 drag_mode = DRAG_TOP_LEFT;
753             }
754             else
755             {
756                 if (test.gx_point_x > select_inner.gx_rectangle_right)
757                 {
758                     // top right corner
759                     drag_mode = DRAG_TOP_RIGHT;
760                 }
761                 else
762                 {
763                     // top
764                     drag_mode = DRAG_TOP;
765                 }
766             }
767         }
768         else
769         {
770             if (test.gx_point_y > select_inner.gx_rectangle_bottom)
771             {
772                 if (test.gx_point_x < select_inner.gx_rectangle_left)
773                 {
774                     // bottom left corner
775                     drag_mode = DRAG_BOTTOM_LEFT;
776                 }
777                 else
778                 {
779                     if (test.gx_point_x > select_inner.gx_rectangle_right)
780                     {
781                         // bottom right corner
782                         drag_mode = DRAG_BOTTOM_RIGHT;
783                     }
784                     else
785                     {
786                         // bottom
787                         drag_mode = DRAG_BOTTOM;
788                     }
789                 }
790             }
791             else
792             {
793                 if (test.gx_point_x < select_inner.gx_rectangle_left)
794                 {
795                     drag_mode = DRAG_LEFT;
796                 }
797                 else
798                 {
799                     drag_mode = DRAG_RIGHT;
800                 }
801             }
802         }
803 
804         if (selected->basetype == GX_TYPE_RADIAL_PROGRESS_BAR)
805         {
806             drag_mode = ConvertRadialProgressDragMode(drag_mode, select_inner, test);
807         }
808 
809         switch (drag_mode)
810         {
811         case DRAG_LEFT:
812         case DRAG_RIGHT:
813             ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
814             break;
815 
816         case DRAG_TOP:
817         case DRAG_BOTTOM:
818             ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
819             break;
820 
821         case DRAG_TOP_LEFT:
822         case DRAG_BOTTOM_RIGHT:
823             ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE));
824             break;
825 
826         case DRAG_TOP_RIGHT:
827         case DRAG_BOTTOM_LEFT:
828             ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENESW));
829             break;
830         }
831     }
832     else
833     {
834        ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
835         drag_mode = DRAG_NONE;
836     }
837     return drag_mode;
838 }
839 
840 ///////////////////////////////////////////////////////////////////////////////
CalSnap2GridDelta(int value,int & delta)841 int target_screen::CalSnap2GridDelta(int value, int &delta)
842 {
843     if (!delta)
844     {
845         return 0;
846     }
847 
848     int spacing = GetOpenProject()->mHeader.grid_spacing;
849     int half_spacing = spacing / 2;
850     int dist;
851     int snap_dist = 0;
852 
853     // Calculate the distance from the new position to the grid line.
854     dist = (value + delta) % spacing;
855 
856     if (dist != 0)
857     {
858         // Snap to grid.
859         if (abs(dist) < half_spacing)
860         {
861             snap_dist = -dist;
862         }
863         else
864         {
865             int sign = abs(dist) / dist;
866             snap_dist = (spacing * sign - dist);
867         }
868     }
869 
870     delta += snap_dist;
871 
872     return snap_dist;
873 }
874 
875 ///////////////////////////////////////////////////////////////////////////////
OnAltKeyDown()876 BOOL target_screen::OnAltKeyDown()
877 {
878     BOOL result = FALSE;
879     if (mGridSnapInfo.crosshair_enabled)
880     {
881         InvalidateCrosshairArea();
882         mGridSnapInfo.crosshair_enabled = FALSE;
883         result = TRUE;
884     }
885 
886     if (mGridSnapInfo.snap_line_count)
887     {
888         InvalidateSnapLineArea();
889         mGridSnapInfo.snap_line_count = 0;
890         result = TRUE;
891     }
892 
893     if (result)
894     {
895         CPoint pt;
896         GetCursorPos(&pt);
897         ScreenToClient(&pt);
898 
899         int x, y;
900         x = pt.x;
901         y = pt.y;
902         SendMessage(WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(x, y));
903     }
904 
905     return result;
906 }
907 
908 ///////////////////////////////////////////////////////////////////////////////
InvalidateCrosshairArea()909 void target_screen::InvalidateCrosshairArea()
910 {
911     CRect rect;
912     int scale;
913 
914     if (mGridSnapInfo.crosshair_enabled)
915     {
916         scale = GetZoomScale();
917 
918         rect.left = mGridSnapInfo.crosshair_cx - mGridSnapInfo.crosshair_size;
919         rect.right = mGridSnapInfo.crosshair_cx + mGridSnapInfo.crosshair_size;
920         rect.top = mGridSnapInfo.crosshair_cy - mGridSnapInfo.crosshair_size;
921         rect.bottom = mGridSnapInfo.crosshair_cy + mGridSnapInfo.crosshair_size;
922 
923         scale = GetZoomScale();
924 
925         rect.left = rect.left * scale / 100;
926         rect.top = rect.top * scale / 100;
927         rect.right = (rect.right + 1) * scale / 100;
928         rect.bottom = (rect.bottom + 1) * scale / 100;
929 
930         InvalidateRect(&rect);
931     }
932 }
933 
934 ///////////////////////////////////////////////////////////////////////////////
InvalidateSnapLineArea()935 void target_screen::InvalidateSnapLineArea()
936 {
937     SNAPLINE_INFO *snapline;
938     CRect rect;
939     INT scale;
940 
941     // Invalidate snap line areas.
942     for (int index = 0; index < mGridSnapInfo.snap_line_count; index++)
943     {
944         snapline = &mGridSnapInfo.snap_lines[index];
945 
946         if (snapline->direction == SNAP_LINE_DIRECTION_VERTICAL)
947         {
948             rect.left = snapline->target_x_y;
949             rect.top = snapline->target_top_left;
950             rect.right = snapline->target_x_y + 1;
951             rect.bottom = snapline->target_bottom_right + 1;
952         }
953         else
954         {
955             rect.left = snapline->target_top_left;
956             rect.top = snapline->target_x_y;
957             rect.right = snapline->target_bottom_right + 1;
958             rect.bottom = snapline->target_x_y + 1;
959         }
960 
961         scale = GetZoomScale();
962 
963         rect.left = rect.left * scale / 100;
964         rect.top = rect.top * scale / 100;
965         rect.right = rect.right * scale / 100;
966         rect.bottom = rect.bottom * scale / 100;
967 
968         InvalidateRect(&rect);
969     }
970 }
971 
972 ///////////////////////////////////////////////////////////////////////////////
UpdateSnapLines(int delta_x,int delta_y)973 void target_screen::UpdateSnapLines(int delta_x, int delta_y)
974 {
975     SNAPLINE_INFO *snapline;
976 
977     for (int index = 0; index < mGridSnapInfo.snap_line_count; index++)
978     {
979         snapline = &mGridSnapInfo.snap_lines[index];
980 
981         if (snapline->direction == SNAP_LINE_DIRECTION_VERTICAL)
982         {
983             // Update source snap line.
984             snapline->source_top_left += delta_y;
985             snapline->source_bottom_right += delta_y;
986 
987             // Combine source and target snaplines.
988             if (snapline->source_top_left < snapline->target_top_left)
989             {
990                 snapline->target_top_left = snapline->source_top_left;
991             }
992 
993             if (snapline->source_bottom_right > snapline->target_bottom_right)
994             {
995                 snapline->target_bottom_right = snapline->source_bottom_right;
996             }
997         }
998         else
999         {
1000             // Update source snapline.
1001             snapline->source_top_left += delta_x;
1002             snapline->source_bottom_right += delta_x;
1003 
1004             // Combine source and target snaplines.
1005             if (snapline->source_top_left < snapline->target_top_left)
1006             {
1007                 snapline->target_top_left = snapline->source_top_left;
1008             }
1009 
1010             if(snapline->source_bottom_right > snapline->target_bottom_right)
1011             {
1012                 snapline->target_bottom_right = snapline->source_bottom_right;
1013             }
1014         }
1015     }
1016 }
1017 
1018 ///////////////////////////////////////////////////////////////////////////////
GetSnapLineVal(GX_RECTANGLE & size,int snap_line_type)1019 int target_screen::GetSnapLineVal(GX_RECTANGLE &size, int snap_line_type)
1020 {
1021     switch (snap_line_type)
1022     {
1023     case SNAP_LINE_TYPE_LEFT:
1024         return size.gx_rectangle_left;
1025 
1026     case SNAP_LINE_TYPE_RIGHT:
1027         return size.gx_rectangle_right;
1028 
1029     case SNAP_LINE_TYPE_VERTICAL:
1030         return ((size.gx_rectangle_left + size.gx_rectangle_right) >> 1);
1031 
1032     case SNAP_LINE_TYPE_TOP:
1033         return size.gx_rectangle_top;
1034 
1035     case SNAP_LINE_TYPE_BOTTOM:
1036         return size.gx_rectangle_bottom;
1037 
1038     case SNAP_LINE_TYPE_HORIZONTAL:
1039         return ((size.gx_rectangle_top + size.gx_rectangle_bottom) >> 1);
1040 
1041     default:
1042         return 0;
1043     }
1044 
1045     return 0;
1046 }
1047 
1048 ///////////////////////////////////////////////////////////////////////////////
IsVerticalSnapLineType(int snap_line_type)1049 BOOL target_screen::IsVerticalSnapLineType(int snap_line_type)
1050 {
1051     switch (snap_line_type)
1052     {
1053     case SNAP_LINE_TYPE_LEFT:
1054     case SNAP_LINE_TYPE_RIGHT:
1055     case SNAP_LINE_TYPE_VERTICAL:
1056         return TRUE;
1057 
1058     default:
1059         return FALSE;
1060     }
1061 
1062     return FALSE;
1063 }
1064 
1065 ///////////////////////////////////////////////////////////////////////////////
TestAddSnapLine(SNAPLINE_INFO & test)1066 void target_screen::TestAddSnapLine(SNAPLINE_INFO &test)
1067 {
1068     SNAPLINE_INFO *snapline;
1069 
1070     for (int index = 0; index < mGridSnapInfo.snap_line_count; index++)
1071     {
1072         snapline = &mGridSnapInfo.snap_lines[index];
1073 
1074         if ((snapline->direction == test.direction) &&
1075             (snapline->target_x_y == test.target_x_y))
1076         {
1077             if (test.target_top_left < snapline->target_top_left)
1078             {
1079                 snapline->target_top_left = test.target_top_left;
1080             }
1081 
1082             if (test.target_bottom_right > snapline->target_bottom_right)
1083             {
1084                 snapline->target_bottom_right = test.target_bottom_right;
1085             }
1086 
1087             return;
1088         }
1089     }
1090 
1091     if (mGridSnapInfo.snap_line_count < MAX_SNAP_LINES)
1092     {
1093         mGridSnapInfo.snap_lines[mGridSnapInfo.snap_line_count++] = test;
1094     }
1095 }
1096 
1097 ///////////////////////////////////////////////////////////////////////////////
ClearSnapLine(int snapline_direction)1098 void target_screen::ClearSnapLine(int snapline_direction)
1099 {
1100     SNAPLINE_INFO *snapline;
1101 
1102     for (int index = 0; index < mGridSnapInfo.snap_line_count; index++)
1103     {
1104         snapline = &mGridSnapInfo.snap_lines[index];
1105 
1106         if (snapline->direction == snapline_direction)
1107         {
1108             mGridSnapInfo.snap_line_count--;
1109             for (int loop = index; loop < mGridSnapInfo.snap_line_count; loop++)
1110             {
1111                 mGridSnapInfo.snap_lines[loop] = mGridSnapInfo.snap_lines[loop + 1];
1112             }
1113             index--;
1114         }
1115     }
1116 }
1117 
1118 ///////////////////////////////////////////////////////////////////////////////
Snap2Widget(GX_RECTANGLE & src_size,GX_RECTANGLE & target_size,int src_snap_line_type,int direction,int & snap_dist)1119 BOOL target_screen::Snap2Widget(GX_RECTANGLE &src_size, GX_RECTANGLE &target_size,
1120                                 int src_snap_line_type, int direction,
1121                                 int &snap_dist)
1122 {
1123     BOOL result = FALSE;
1124     int  src_val;
1125     int *src_type_list;
1126     int  src_type_count;
1127     int  target_val;
1128     int  target_snap_line_type;
1129     int *target_type_list;
1130     int  target_type_count;
1131     int  dist;
1132 
1133     if (src_snap_line_type >= 0)
1134     {
1135         src_type_list = &src_snap_line_type;
1136         src_type_count = 1;
1137     }
1138     else
1139     {
1140         src_type_count = (SNAP_LINE_TYPE_COUNT / 2);
1141     }
1142 
1143     if (direction == SNAP_LINE_DIRECTION_VERTICAL)
1144     {
1145         target_type_list = vsnap_line_list;
1146 
1147         if (src_snap_line_type < 0)
1148         {
1149             src_type_list = vsnap_line_list;
1150         }
1151     }
1152     else
1153     {
1154         target_type_list = hsnap_line_list;
1155 
1156         if (src_snap_line_type < 0)
1157         {
1158             src_type_list = hsnap_line_list;
1159         }
1160     }
1161 
1162     SNAPLINE_INFO snapline;
1163     target_type_count = (SNAP_LINE_TYPE_COUNT / 2);
1164 
1165     for (int src_index = 0; src_index < src_type_count; src_index++)
1166     {
1167         src_snap_line_type = src_type_list[src_index];
1168         src_val = GetSnapLineVal(src_size, src_snap_line_type);
1169 
1170         for (int target_index = 0; target_index < target_type_count; target_index++)
1171         {
1172             target_snap_line_type = target_type_list[target_index];
1173             target_val = GetSnapLineVal(target_size, target_snap_line_type);
1174 
1175             dist = target_val - src_val;
1176             if (GX_ABS(dist) <= GX_ABS(snap_dist))
1177             {
1178                 if ((GX_ABS(dist) < GX_ABS(snap_dist)) || ((dist * snap_dist) < 0))
1179                 {
1180                     ClearSnapLine(direction);
1181                 }
1182 
1183                 snap_dist = target_val - src_val;
1184 
1185                 snapline.target_x_y = target_val;
1186                 snapline.direction = direction;
1187 
1188                 if (direction == SNAP_LINE_DIRECTION_VERTICAL)
1189                 {
1190                     snapline.target_top_left = target_size.gx_rectangle_top;
1191                     snapline.target_bottom_right = target_size.gx_rectangle_bottom;
1192 
1193                     snapline.source_top_left = src_size.gx_rectangle_top;
1194                     snapline.source_bottom_right = src_size.gx_rectangle_bottom;
1195                 }
1196                 else
1197                 {
1198                     snapline.target_top_left = target_size.gx_rectangle_left;
1199                     snapline.target_bottom_right = target_size.gx_rectangle_right;
1200 
1201                     snapline.source_top_left = src_size.gx_rectangle_left;
1202                     snapline.source_bottom_right = src_size.gx_rectangle_right;
1203                 }
1204 
1205                 TestAddSnapLine(snapline);
1206 
1207                 result = TRUE;
1208             }
1209         }
1210     }
1211 
1212     return result;
1213 }
1214 
1215 ///////////////////////////////////////////////////////////////////////////////
CalSnap2WidgetDelta(GX_WIDGET * selected,int & delta,int direction,int snap_dist,int src_snap_line_type)1216 BOOL target_screen::CalSnap2WidgetDelta(GX_WIDGET *selected, int &delta, int direction, int snap_dist, int src_snap_line_type)
1217 {
1218     GX_WIDGET *parent = selected->gx_widget_parent;
1219     studiox_project *project = GetOpenProject();
1220 
1221     if ((!parent) || (!project))
1222     {
1223         return FALSE;
1224     }
1225 
1226     GX_RECTANGLE src_size = selected->gx_widget_size;
1227 
1228     if (direction == SNAP_LINE_DIRECTION_VERTICAL)
1229     {
1230         gx_utility_rectangle_shift(&src_size, delta, 0);
1231     }
1232     else
1233     {
1234         gx_utility_rectangle_shift(&src_size, 0, delta);
1235     }
1236 
1237     if (GX_ABS(snap_dist) > project->mHeader.snap_spacing)
1238     {
1239         snap_dist = project->mHeader.snap_spacing;
1240     }
1241 
1242     BOOL find = FALSE;
1243 
1244     if (Snap2Widget(src_size, parent->gx_widget_size, src_snap_line_type, direction, snap_dist))
1245     {
1246         find = TRUE;
1247     }
1248 
1249 
1250     GX_WIDGET *child = parent->gx_widget_first_child;
1251 
1252     while (child)
1253     {
1254         if ((child != selected) &&
1255             Snap2Widget(src_size, child->gx_widget_size, src_snap_line_type, direction, snap_dist))
1256         {
1257             find = TRUE;
1258         }
1259 
1260         child = child->gx_widget_next;
1261     }
1262 
1263     if (find)
1264     {
1265         delta += snap_dist;
1266     }
1267 
1268     return find;
1269 }
1270 
1271 ///////////////////////////////////////////////////////////////////////////////
ConvertRadialProgressDragMode(int drag_mode,GX_RECTANGLE rect,GX_POINT point)1272 int target_screen::ConvertRadialProgressDragMode(int drag_mode, GX_RECTANGLE rect, GX_POINT point)
1273 {
1274     switch (drag_mode)
1275     {
1276     case DRAG_TOP_LEFT:
1277         if (abs(point.gx_point_x - rect.gx_rectangle_left) < abs(point.gx_point_y - rect.gx_rectangle_top))
1278         {
1279             // Mouse cursor is near to left margin
1280             drag_mode = DRAG_LEFT;
1281         }
1282         else
1283         {
1284             drag_mode = DRAG_TOP;
1285         }
1286         break;
1287 
1288     case DRAG_TOP_RIGHT:
1289         if (abs(point.gx_point_x - rect.gx_rectangle_right) < abs(point.gx_point_y - rect.gx_rectangle_top))
1290         {
1291             // Mouse cursor is near to right margin
1292             drag_mode = DRAG_RIGHT;
1293         }
1294         else
1295         {
1296             drag_mode = DRAG_TOP;
1297         }
1298         break;
1299 
1300     case DRAG_BOTTOM_LEFT:
1301         if (abs(point.gx_point_x - rect.gx_rectangle_left) < abs(point.gx_point_y - rect.gx_rectangle_bottom))
1302         {
1303             drag_mode = DRAG_LEFT;
1304         }
1305         else
1306         {
1307             drag_mode = DRAG_BOTTOM;
1308         }
1309         break;
1310 
1311     case DRAG_BOTTOM_RIGHT:
1312         if (abs(point.gx_point_x - rect.gx_rectangle_right) < abs(point.gx_point_y - rect.gx_rectangle_bottom))
1313         {
1314             drag_mode = DRAG_RIGHT;
1315         }
1316         else
1317         {
1318             drag_mode = DRAG_BOTTOM;
1319         }
1320         break;;
1321     }
1322 
1323     return drag_mode;
1324 }
1325 
1326 ///////////////////////////////////////////////////////////////////////////////
UpdateRadialProgressSize(GX_RECTANGLE * size,int mDragMode,int delta_x,int delta_y)1327 void target_screen::UpdateRadialProgressSize(GX_RECTANGLE *size, int mDragMode, int delta_x, int delta_y)
1328 {
1329     switch (mDragMode)
1330     {
1331     case DRAG_LEFT:
1332         size->gx_rectangle_left += delta_x;
1333         size->gx_rectangle_right -= delta_x;
1334         size->gx_rectangle_top += delta_x;
1335         size->gx_rectangle_bottom -= delta_x;
1336         break;
1337 
1338     case DRAG_RIGHT:
1339         size->gx_rectangle_left -= delta_x;
1340         size->gx_rectangle_right += delta_x;
1341         size->gx_rectangle_top -= delta_x;
1342         size->gx_rectangle_bottom += delta_x;
1343         break;
1344 
1345     case DRAG_TOP:
1346         size->gx_rectangle_top += delta_y;
1347         size->gx_rectangle_bottom -= delta_y;
1348         size->gx_rectangle_left += delta_y;
1349         size->gx_rectangle_right -= delta_y;
1350         break;
1351 
1352     case DRAG_BOTTOM:
1353         size->gx_rectangle_top -= delta_y;
1354         size->gx_rectangle_bottom += delta_y;
1355         size->gx_rectangle_left -= delta_y;
1356         size->gx_rectangle_right += delta_y;
1357         break;
1358     }
1359 }
1360 
1361 ///////////////////////////////////////////////////////////////////////////////
UpdateWidgetSize(GX_RECTANGLE * size,int mDrawMode,int delta_x,int delta_y)1362 void target_screen::UpdateWidgetSize(GX_RECTANGLE *size, int mDrawMode, int delta_x, int delta_y)
1363 {
1364     switch (mDragMode)
1365     {
1366     case DRAG_TOP_LEFT:
1367         size->gx_rectangle_left += delta_x;
1368         size->gx_rectangle_top += delta_y;
1369         break;
1370 
1371     case DRAG_TOP_RIGHT:
1372         size->gx_rectangle_right += delta_x;
1373         size->gx_rectangle_top += delta_y;
1374         break;
1375 
1376     case DRAG_BOTTOM_RIGHT:
1377         size->gx_rectangle_right += delta_x;
1378         size->gx_rectangle_bottom += delta_y;
1379         break;
1380 
1381     case DRAG_BOTTOM_LEFT:
1382         size->gx_rectangle_left += delta_x;
1383         size->gx_rectangle_bottom += delta_y;
1384         break;
1385 
1386     case DRAG_LEFT:
1387         size->gx_rectangle_left += delta_x;
1388         break;
1389 
1390     case DRAG_RIGHT:
1391         size->gx_rectangle_right += delta_x;
1392         break;
1393 
1394     case DRAG_TOP:
1395         size->gx_rectangle_top += delta_y;
1396         break;
1397 
1398     case DRAG_BOTTOM:
1399         size->gx_rectangle_bottom += delta_y;
1400         break;
1401     }
1402 }
1403 
1404 ///////////////////////////////////////////////////////////////////////////////
CalSnapDelta(int & delta_x,int & delta_y,int snap_dist)1405 void target_screen::CalSnapDelta(int &delta_x, int &delta_y, int snap_dist)
1406 {
1407     int nAltKey = GetKeyState(VK_MENU);
1408 
1409     if (nAltKey & KEY_STATE_DOWN)
1410     {
1411         // Disable snap feature when ALT key is down.
1412         return;
1413     }
1414 
1415     studiox_project *project = GetOpenProject();
1416     project_header *header = &project->mHeader;
1417 
1418     if ((!header->snap_enabled) && (!header->snap_to_widget_enabled))
1419     {
1420         return;
1421     }
1422 
1423     GX_WIDGET *selected = SelectedWidgets[0].info->widget;
1424     GX_RECTANGLE size = selected->gx_widget_size;
1425 
1426     int snap_delta_x = delta_x;
1427     int snap_delta_y = delta_y;
1428     int snap_dist_x = snap_dist;
1429     int snap_dist_y = snap_dist;
1430     BOOL snap_result_x = FALSE;
1431     BOOL snap_result_y = FALSE;
1432 
1433     if (header->snap_enabled)
1434     {
1435         if (mGridSnapInfo.crosshair_enabled)
1436         {
1437             InvalidateCrosshairArea();
1438             mGridSnapInfo.crosshair_enabled = FALSE;
1439         }
1440 
1441         // Calculate snap to grid delta and snap distance
1442 
1443         switch (mDragMode)
1444         {
1445         case DRAG_ALL:
1446             if (mpDragSelected)
1447             {
1448                 size = mpDragSelected->gx_widget_size;
1449 
1450                 // Calculate center point of drag selected widget.
1451                 mGridSnapInfo.crosshair_cx = ((size.gx_rectangle_left + size.gx_rectangle_right) >> 1);
1452                 mGridSnapInfo.crosshair_cy = ((size.gx_rectangle_top + size.gx_rectangle_bottom) >> 1);
1453 
1454                 // Adjust delta value to make selected center point snap to grid
1455                 snap_dist_x = CalSnap2GridDelta(mGridSnapInfo.crosshair_cx, delta_x);
1456                 snap_dist_y = CalSnap2GridDelta(mGridSnapInfo.crosshair_cy, delta_y);
1457 
1458                 mGridSnapInfo.crosshair_enabled = TRUE;
1459             }
1460             break;
1461 
1462         case DRAG_TOP_LEFT:
1463             snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_left, delta_x);
1464             snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_top, delta_y);
1465             break;
1466 
1467         case DRAG_TOP_RIGHT:
1468             snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_right, delta_x);
1469             snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_top, delta_y);
1470             break;
1471 
1472         case DRAG_BOTTOM_RIGHT:
1473             snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_right, delta_x);
1474             snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_bottom, delta_y);
1475             break;
1476 
1477         case DRAG_BOTTOM_LEFT:
1478             snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_left, delta_x);
1479             snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_bottom, delta_y);
1480             break;
1481 
1482         case DRAG_LEFT:
1483             snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_left, delta_x);
1484             break;
1485 
1486         case DRAG_RIGHT:
1487             snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_right, delta_x);
1488             break;
1489 
1490         case DRAG_TOP:
1491             snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_top, delta_y);
1492             break;
1493 
1494         case DRAG_BOTTOM:
1495             snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_bottom, delta_y);
1496             break;
1497         }
1498     }
1499 
1500     if (header->snap_to_widget_enabled)
1501     {
1502         if (mGridSnapInfo.snap_line_count)
1503         {
1504             // Invalidate old snap line area.
1505             InvalidateSnapLineArea();
1506             mGridSnapInfo.snap_line_count = 0;
1507         }
1508 
1509         // Calculate snap to widget delta.
1510 
1511         switch (mDragMode)
1512         {
1513         case DRAG_ALL:
1514             if (mpDragSelected)
1515             {
1516                 snap_result_x = CalSnap2WidgetDelta(mpDragSelected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x);
1517                 snap_result_y = CalSnap2WidgetDelta(mpDragSelected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y);
1518             }
1519             break;
1520 
1521         case DRAG_TOP_LEFT:
1522             snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_LEFT);
1523             snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_TOP);
1524             break;
1525 
1526         case DRAG_TOP_RIGHT:
1527             snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_RIGHT);
1528             snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_TOP);
1529             break;
1530 
1531         case DRAG_BOTTOM_RIGHT:
1532             snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_RIGHT);
1533             snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_BOTTOM);
1534             break;
1535 
1536         case DRAG_BOTTOM_LEFT:
1537             snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_LEFT);
1538             snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_BOTTOM);
1539             break;
1540 
1541         case DRAG_LEFT:
1542             snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_LEFT);
1543             break;
1544 
1545         case DRAG_RIGHT:
1546             snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_RIGHT);
1547             break;
1548 
1549         case DRAG_TOP:
1550             snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_TOP);
1551             break;
1552 
1553         case DRAG_BOTTOM:
1554             snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_BOTTOM);
1555             break;
1556         }
1557 
1558         if (snap_result_x)
1559         {
1560             delta_x = snap_delta_x;
1561         }
1562 
1563         if (snap_result_y)
1564         {
1565             delta_y = snap_delta_y;
1566         }
1567     }
1568 
1569     if (header->snap_enabled && mGridSnapInfo.crosshair_enabled)
1570     {
1571         // Update crosshair coordinates
1572         if (header->snap_enabled)
1573         {
1574             mGridSnapInfo.crosshair_cx += delta_x;
1575             mGridSnapInfo.crosshair_cy += delta_y;
1576         }
1577 
1578         InvalidateCrosshairArea();
1579     }
1580 
1581     if (header->snap_to_widget_enabled && mGridSnapInfo.snap_line_count)
1582     {
1583         // Update snap lines.
1584         UpdateSnapLines(delta_x, delta_y);
1585 
1586         // Invalidate new snap line area
1587         InvalidateSnapLineArea();
1588     }
1589 }
1590 
1591 ///////////////////////////////////////////////////////////////////////////////
OnMouseMove(UINT nFlags,CPoint point)1592 void target_screen::OnMouseMove(UINT nFlags, CPoint point)
1593 {
1594     GX_RECTANGLE size;
1595     int delta_x;
1596     int delta_y;
1597 
1598     int scale = GetZoomScale();
1599     point.x = point.x * 100 / scale;
1600     point.y = point.y * 100 / scale;
1601 
1602     if (mDragMode == DRAG_NONE)
1603     {
1604         if ((nFlags & MK_LBUTTON) == 0)
1605         {
1606             CheckResizeCursor(point);
1607         }
1608         return;
1609     }
1610 
1611     if (nFlags & MK_LBUTTON && SelectedWidgets.GetCount())
1612     {
1613         delta_x = point.x - mDragStart.gx_point_x;
1614         delta_y = point.y - mDragStart.gx_point_y;
1615 
1616         if (!delta_x && !delta_y)
1617         {
1618             return;
1619         }
1620 
1621         studiox_project *project = GetOpenProject();
1622         project_header *header = &project->mHeader;
1623 
1624         GX_WIDGET *selected = SelectedWidgets[0].info->widget;
1625         size = selected->gx_widget_size;
1626 
1627         widget_info *info = project->FindWidgetInfo(selected);
1628 
1629         if (selected && (header->snap_enabled || header->snap_to_widget_enabled))
1630         {
1631             CalSnapDelta(delta_x, delta_y, header->snap_spacing);
1632         }
1633 
1634         if (!delta_x && !delta_y)
1635         {
1636             return;
1637         }
1638 
1639         if (mDragMode == DRAG_ALL)
1640         {
1641             mDragStart.gx_point_x += delta_x;
1642             mDragStart.gx_point_y += delta_y;
1643 
1644             ShiftSelectedWidgets(delta_x, delta_y);
1645         }
1646         else
1647         {
1648             if (info->basetype == GX_TYPE_RADIAL_PROGRESS_BAR)
1649             {
1650                 UpdateRadialProgressSize(&size, mDragMode, delta_x, delta_y);
1651             }
1652             else
1653             {
1654                 UpdateWidgetSize(&size, mDragMode, delta_x, delta_y);
1655             }
1656 
1657             mDragStart.gx_point_x += delta_x;
1658             mDragStart.gx_point_y += delta_y;
1659 
1660             UINT parent_type = GetWidgetParentType(info);
1661 
1662             /* Check if widget moving is allowed. */
1663             if (!IsWidgetResizable(parent_type, info, size))
1664             {
1665                 return;
1666             }
1667 
1668             if (info)
1669             {
1670                 UndoManager()->AddEntry(UNDO_TYPE_SIZE, info, 0, mFoldUndo);
1671                 widget_factory::MoveWidget(info, size);
1672 
1673                 WidgetWasMoved(info);
1674                 GetPropsWin()->WidgetWasMoved();
1675                 mFoldUndo = TRUE;
1676             }
1677             else
1678             {
1679                 ErrorMsg("Internal error: widget information is not available");
1680             }
1681         }
1682     }
1683 }
1684 
1685 ///////////////////////////////////////////////////////////////////////////////
OnGuixReady(WPARAM wp,LPARAM lp)1686 LRESULT target_screen::OnGuixReady(WPARAM wp, LPARAM lp)
1687 {
1688     Invalidate();
1689     return 0;
1690 }
1691 
1692 ///////////////////////////////////////////////////////////////////////////////
OnGuixDirty(WPARAM wp,LPARAM lp)1693 LRESULT target_screen::OnGuixDirty(WPARAM wp, LPARAM lp)
1694 {
1695     CRect rect;
1696 
1697     int scale = GetZoomScale();
1698 
1699     // In guix, rectangle.width = rectangle.right - rectangle.left + 1
1700     // In mfc, rectangle.width = rectangle.right - rectangle.left
1701     rect.left = GET_X_LPARAM(wp);
1702     rect.top = GET_Y_LPARAM(wp);
1703     rect.right = (GET_X_LPARAM(lp) + 1);
1704     rect.bottom = (GET_Y_LPARAM(lp) + 1);
1705 
1706     //scale the guix dirty area to get the screen dirty
1707     rect.left = rect.left * scale / 100;
1708     rect.top = rect.top * scale / 100;
1709     rect.right = rect.right * scale / 100;
1710     rect.bottom = rect.bottom * scale / 100;
1711 
1712     InvalidateRect(&rect);
1713     return 0;
1714 }
1715 
1716 
1717 ///////////////////////////////////////////////////////////////////////////////
OnPaint()1718 void target_screen::OnPaint()
1719 {
1720     GX_CANVAS *canvas = get_target_win_canvas();
1721 
1722     CPaintDC dc(this);
1723 
1724     if (canvas ->gx_canvas_memory)
1725     {
1726         CRect    rect;
1727         GX_RECTANGLE dirty;
1728         int scale = GetZoomScale();
1729 
1730         dc.GetClipBox(&rect);
1731 
1732         //convert screen dirty area to guix dirty area
1733         rect.left = rect.left * 100 / scale;
1734         rect.top = rect.top * 100 / scale;
1735         rect.right = rect.right * 100 / scale;
1736         rect.bottom = rect.bottom * 100 / scale;
1737 
1738         gx_utility_rectangle_define(&dirty,
1739             (GX_VALUE)rect.left,
1740             (GX_VALUE)rect.top,
1741             (GX_VALUE)rect.right,
1742             (GX_VALUE)rect.bottom);
1743 
1744         if (!IsGuixCanvasRefreshBlocked())
1745         {
1746             /* make sure our guix canvas is up to date */
1747             _gx_system_canvas_refresh();
1748         }
1749 
1750         studiox_project *project = GetOpenProject();
1751 
1752         if (project)
1753         {
1754             if (project->mHeader.grid_enabled)
1755             {
1756                 mGridSnapInfo.grid_space = project->mHeader.grid_spacing;
1757             }
1758             else
1759             {
1760                 mGridSnapInfo.grid_space = 0;
1761 
1762             }
1763 
1764             guix_canvas_paint(dc.GetSafeHdc(), dirty, scale, &mGridSnapInfo);
1765         }
1766     }
1767 }
1768 
1769 ///////////////////////////////////////////////////////////////////////////////
OnEraseBkgnd(CDC * pDC)1770 BOOL target_screen::OnEraseBkgnd(CDC *pDC)
1771 {
1772     return TRUE;
1773 }
1774 
1775 ///////////////////////////////////////////////////////////////////////////////
DeSelect()1776 void target_screen::DeSelect()
1777 {
1778     GX_WIDGET* parent;
1779 
1780     for (int index = 0; index < SelectedWidgets.GetCount(); index++)
1781     {
1782         /* replace the drawing functions replaced to draw the selection box */
1783         if (SelectedWidgets[index].info->widget)
1784         {
1785             SelectedWidgets[index].info->widget->gx_widget_draw_function = SelectedWidgets[index].draw_func;
1786 
1787             if (SelectedWidgets[index].info->widget->gx_widget_type == GX_TYPE_DROP_LIST)
1788             {
1789                 gx_drop_list_close((GX_DROP_LIST *) SelectedWidgets[index].info->widget);
1790             }
1791 
1792             parent = SelectedWidgets[index].info->widget->gx_widget_parent;
1793             while (parent)
1794             {
1795                 if (parent->gx_widget_type == GX_TYPE_DROP_LIST)
1796                 {
1797                     gx_drop_list_close((GX_DROP_LIST *)parent);
1798                     break;
1799                 }
1800                 parent = parent->gx_widget_parent;
1801             }
1802             gx_system_dirty_mark(SelectedWidgets[index].info->widget->gx_widget_parent);
1803         }
1804     }
1805     SelectedWidgets.RemoveAll();
1806     mpSelectedParent = NULL;
1807 }
1808 
1809 ///////////////////////////////////////////////////////////////////////////////
ConfigureDisplay(int display_index,BOOL bForce)1810 BOOL target_screen::ConfigureDisplay(int display_index, BOOL bForce)
1811 {
1812     GX_WIDGET *root = (GX_WIDGET *) get_root_window();
1813 
1814     if (root)
1815     {
1816         while(root->gx_widget_first_child)
1817         {
1818             gx_widget_detach(root->gx_widget_first_child);
1819         }
1820     }
1821 
1822     if (m_display_index == display_index && !bForce)
1823     {
1824         return TRUE;
1825     }
1826 
1827     m_display_index = display_index;
1828     studiox_project *project = GetOpenProject();
1829 
1830     if (display_index >= 0 && project)
1831     {
1832         display_info *info = &project->mDisplays[display_index];
1833 
1834         int canvas_xres = info->xres;
1835         int canvas_yres = info->yres;
1836 
1837         if (info->rotation_angle == GX_SCREEN_ROTATION_CW ||
1838             info->rotation_angle == GX_SCREEN_ROTATION_CCW)
1839         {
1840             GX_SWAP_VALS(canvas_xres, canvas_yres);
1841         }
1842 
1843         int active_theme = project->mDisplays[display_index].active_theme;
1844 
1845         // reconfigure the canvas and root window
1846         if (!guix_configure_target_win_canvas(canvas_xres,
1847             canvas_yres,
1848             info->colorformat,
1849             project->mHeader.target_cpu,
1850             IsRenesasDave2D(project),
1851             IsDave2dFontFormat(project, display_index),
1852             info->themes[active_theme].palette,
1853             info->themes[active_theme].palette_total_size,
1854             project->mHeader.palette_mode_aa_text_colors))
1855         {
1856             ErrorMsg("Internal Error: Unable to configure GUIX canvas");
1857             return FALSE;
1858         }
1859 
1860         int scale = GetZoomScale();
1861 
1862         // resize myself to match canvas size:
1863         SetWindowPos(NULL, 0, 0, canvas_xres * scale / 100, canvas_yres * scale / 100, SWP_NOMOVE);
1864 
1865         CenterWindow();
1866         target_frame *frame = (target_frame *) GetParent();
1867         frame->UpdateScrollSize();
1868         frame->Invalidate();
1869     }
1870     return TRUE;
1871 }
1872 
1873 ///////////////////////////////////////////////////////////////////////////////
SwitchTopWidget(widget_info * info)1874 void target_screen::SwitchTopWidget(widget_info *info)
1875 {
1876     int DisplayIndex = GetProjectView()->GetActiveDisplay();
1877     GX_WIDGET *root = (GX_WIDGET *) get_root_window();
1878     widget_info *old_info;
1879 
1880     if (!root && DisplayIndex >= 0)
1881     {
1882         // if there is an active display but no root window, it
1883         // means we haven't configured this display yet. Do it now.
1884 
1885         ConfigureDisplay(DisplayIndex);
1886         root = (GX_WIDGET *) get_root_window();
1887         DisplayIndex = -1;      // don't configure again
1888     }
1889     if (!root)
1890     {
1891         // something is badly wrong, but don't crash:
1892         ErrorMsg("Internal Error: Unable to configure selected display.");
1893         return;
1894     }
1895     if (info)
1896     {
1897         if (info->widget == NULL)
1898         {
1899             // top level screen has not been created, create it now:
1900 
1901             widget_factory::GenerateWidgets(NULL, info, TRUE, FALSE);
1902             if (info->widget == NULL)
1903             {
1904                 ErrorMsg("Internal Error: Unable to create selected screen.");
1905                 return;
1906             }
1907         }
1908         if (root -> gx_widget_first_child)
1909         {
1910             if (root->gx_widget_first_child == info->widget)
1911             {
1912                 // if the top-level window of this root is already the
1913                 // window we are switching to, then we are done:
1914                 return;
1915             }
1916             else
1917             {
1918                 // top-level child is changing, delete the old screen:
1919                 old_info = GetOpenProject()->FindWidgetInfo(root ->gx_widget_first_child);
1920                 if (old_info)
1921                 {
1922                     widget_factory::CleanupWidgets(old_info, TRUE, FALSE);
1923                 }
1924             }
1925         }
1926     }
1927 
1928     DeSelect();
1929 
1930     if (info)
1931     {
1932         // if I haven't checked my display configuration already, do it now:
1933         if (DisplayIndex >= 0)
1934         {
1935             ConfigureDisplay(DisplayIndex);
1936         }
1937 
1938         root = (GX_WIDGET *) get_root_window();
1939 
1940         if (info->widget)
1941         {
1942             gx_widget_attach(root, info->widget);
1943             gx_widget_show(info->widget);
1944         }
1945     }
1946 }
1947 
1948 
1949 ///////////////////////////////////////////////////////////////////////////////
MakeTopWindowVisible(widget_info * info)1950 void target_screen::MakeTopWindowVisible(widget_info *info)
1951 {
1952     widget_info *top_info = info;
1953     widget_info *parent_info = info;
1954     studiox_project *project = GetOpenProject();
1955 
1956     GX_WINDOW_ROOT *root = get_root_window();
1957 
1958     if (!root)
1959     {
1960         return;
1961     }
1962 
1963     if (root->gx_widget_first_child == NULL)
1964     {
1965         // No top screen visible right now, need to switch to the top screen of current selected widget
1966         // Show root window to make new top screen visible
1967         gx_widget_show(root);
1968     }
1969     else
1970     {
1971         if (!project || info->widget != NULL)
1972         {
1973             return;
1974         }
1975     }
1976 
1977     while(parent_info)
1978     {
1979         parent_info = project->FindParentInfo(parent_info);
1980         if (parent_info)
1981         {
1982             top_info = parent_info;
1983         }
1984     }
1985     if (top_info)
1986     {
1987         SwitchTopWidget(top_info);
1988     }
1989 }
1990 
1991 
1992 ///////////////////////////////////////////////////////////////////////////////
SelectWidget(widget_info * info,BOOL echo_to_project_view,BOOL multiple)1993 BOOL target_screen::SelectWidget(widget_info *info, BOOL echo_to_project_view, BOOL multiple)
1994 {
1995     //GX_WIDGET *top_win;
1996     widget_info *selected = GetSingleSelect();
1997 
1998     if (info == selected)
1999     {
2000         if (echo_to_project_view)
2001         {
2002             GetProjectView()->WidgetSelected(info);
2003         }
2004         return FALSE;
2005     }
2006     if (!multiple)
2007     {
2008         DeSelect();
2009     }
2010 
2011     if (info == NULL)
2012     {
2013         return FALSE;
2014     }
2015 
2016     if (!echo_to_project_view)
2017     {
2018         // this select came from project view,
2019         // check for switching top-level windows:
2020         MakeTopWindowVisible(info);
2021     }
2022 
2023     if (info->widget == NULL)
2024     {
2025         ErrorMsg("Internal Error: Selected widget has not been created");
2026         return FALSE;
2027     }
2028 
2029     GX_WIDGET *parent = info->widget->gx_widget_parent;
2030 
2031     if (parent && (parent->gx_widget_type == GX_TYPE_ACCORDION_MENU))
2032     {
2033         parent = parent->gx_widget_parent;
2034     }
2035 
2036     if (parent)
2037     {
2038         //check if the widget is a child of a menu list
2039         GX_WIDGET *menu = GX_NULL;
2040 
2041         switch (parent->gx_widget_type)
2042         {
2043 
2044         case GX_TYPE_MENU_LIST:
2045             menu = ((GX_MENU_LIST *)parent)->gx_menu_list_owner;
2046             break;
2047 
2048         case GX_TYPE_MENU:
2049             menu = parent;
2050             break;
2051         }
2052 
2053         //expand the menu if it's not expanded.
2054         if (menu)
2055         {
2056             menu_service_provider *provider = (menu_service_provider *)widget_factory::GetServiceProvider(menu->gx_widget_type);
2057             widget_info *menu_info = GetOpenProject()->FindWidgetInfo(menu);
2058             provider->AssignStyle(menu_info, menu_info->style | GX_STYLE_MENU_EXPANDED);
2059         }
2060     }
2061 
2062     // when the user selects a drop-list, open the drop list popoup:
2063     GX_WIDGET *drop_test = info->widget;
2064     while(drop_test)
2065     {
2066         if (drop_test->gx_widget_type == GX_TYPE_DROP_LIST)
2067         {
2068             GX_DROP_LIST *drop = (GX_DROP_LIST *) drop_test;
2069             gx_drop_list_open(drop);
2070             break;
2071         }
2072         drop_test = drop_test->gx_widget_parent;
2073     }
2074 
2075 
2076     WIDGET_SELECT_ENTRY new_select;
2077     new_select.draw_func = info->widget->gx_widget_draw_function;
2078     new_select.info = info;
2079 
2080     SelectedWidgets.Add(new_select);
2081     gx_system_dirty_mark(info->widget);
2082 
2083     mpSelectedParent = parent;
2084 
2085     if (echo_to_project_view)
2086     {
2087         if (SelectedWidgets.GetCount() <= 1)
2088         {
2089             GetProjectView()->WidgetSelected(info);
2090         }
2091         else
2092         {
2093             GetProjectView()->WidgetSelected(NULL);
2094         }
2095     }
2096 
2097     return TRUE;
2098 }
2099 
2100 ///////////////////////////////////////////////////////////////////////////////
SelectWidget(GX_POINT & point,BOOL bMultiple)2101 BOOL target_screen::SelectWidget(GX_POINT &point, BOOL bMultiple)
2102 {
2103     GX_WIDGET  *select;
2104     widget_info *info;
2105 
2106     GX_WIDGET *root = (GX_WIDGET *) get_root_window();
2107 
2108     if (!root)
2109     {
2110         return FALSE;
2111     }
2112     select = _gx_system_top_widget_find(root, point, 0);
2113 
2114 
2115     /* We must have widget information to select a widget
2116        (it could be a child of a template)
2117     */
2118     while(select)
2119     {
2120         info = GetOpenProject()->FindWidgetInfo(select);
2121         if (info)
2122         {
2123             break;
2124         }
2125         select = select->gx_widget_parent;
2126     }
2127 
2128     if (!select)
2129     {
2130         return FALSE;
2131     }
2132 
2133 
2134     if (select == root)
2135     {
2136         DeSelect();
2137         GetProjectView()->WidgetSelected(NULL);
2138     }
2139     else
2140     {
2141         // certain things we are not allowed to select
2142         if (select ->gx_widget_type == GX_TYPE_POPUP_LIST)
2143         {
2144             return FALSE;
2145         }
2146 
2147         if (select ->gx_widget_parent)
2148         {
2149             if (select->gx_widget_parent->gx_widget_type == GX_TYPE_VERTICAL_SCROLL ||
2150                 select->gx_widget_parent->gx_widget_type == GX_TYPE_HORIZONTAL_SCROLL ||
2151                 select->gx_widget_type == GX_TYPE_MENU_LIST)
2152             {
2153                 select = select->gx_widget_parent;
2154             }
2155         }
2156         if (!IsWidgetSelected(select))
2157         {
2158             if (bMultiple && SelectedWidgets.GetCount() > 0)
2159             {
2160                 if (select->gx_widget_parent !=
2161                     SelectedWidgets[0].info->widget->gx_widget_parent)
2162                 {
2163                     ErrorMsg("When selecting multiple widgets, all selected widgets must have the same parent.");
2164                     return FALSE;
2165                 }
2166             }
2167 
2168             SelectWidget(info, TRUE, bMultiple);
2169         }
2170     }
2171     return FALSE;
2172 }
2173 
2174 
2175 ///////////////////////////////////////////////////////////////////////////////
OnAddWidget(int type)2176 void target_screen::OnAddWidget(int type)
2177 {
2178     widget_info *info;
2179     folder_info *selected_folder = NULL;
2180     GX_WIDGET *parent = NULL;
2181     studiox_project *project = GetOpenProject();
2182 
2183     if (!project)
2184     {
2185         return;
2186     }
2187 
2188     widget_info *selected = GetSingleSelect();
2189 
2190     if (selected)
2191     {
2192         if (type == GX_TYPE_HORIZONTAL_SCROLL ||
2193             type == GX_TYPE_VERTICAL_SCROLL)
2194         {
2195             if (selected->basetype < GX_TYPE_WINDOW)
2196             {
2197                 ErrorMsg("Scroll bars can only be added to Window parents");
2198                 return;
2199             }
2200         }
2201         else if (type == GX_TYPE_MENU)
2202         {
2203             if ((selected->basetype != GX_TYPE_ACCORDION_MENU) &&
2204                 (selected->basetype != GX_TYPE_TREE_VIEW) &&
2205                 (selected->basetype != GX_TYPE_MENU))
2206             {
2207                 ErrorMsg("The menu widget can only be added to Menu, Accordion Menu and Tree View widgets.");
2208                 return;
2209             }
2210         }
2211         else if (type == GX_TYPE_GENERIC_SCROLL_WHEEL)
2212         {
2213             if (project_lib_version() < GX_VERSION_WITH_GENERIC_SCROLL_WHEEL)
2214             {
2215                 ErrorMsg("The project GUIX library version does not support this widget type.");
2216                 return;
2217             }
2218         }
2219 
2220         parent = selected->widget;
2221     }
2222     else
2223     {
2224         if (GetProjectView()->IsFolderSelected())
2225         {
2226             selected_folder = GetProjectView()->GetSelectedFolder();
2227             if (!selected_folder)
2228             {
2229                 return;
2230             }
2231             parent = (GX_WIDGET *) get_root_window();
2232         }
2233     }
2234 
2235     widget_service_provider *provider = widget_factory::GetServiceProvider(type);
2236 
2237     if (provider)
2238     {
2239         if (!parent)
2240         {
2241             return;
2242         }
2243 
2244         info = provider->CreateNewInstance(parent);
2245 
2246         if (project->mHeader.snap_enabled)
2247         {
2248             int grid_spacing = project->mHeader.grid_spacing;
2249             int xoff = (info->size.gx_rectangle_left) % grid_spacing;
2250             int yoff = (info->size.gx_rectangle_top) % grid_spacing;
2251 
2252             info->size.gx_rectangle_left -= xoff;
2253             info->size.gx_rectangle_top -= yoff;
2254             info->size.gx_rectangle_right -= xoff;
2255             info->size.gx_rectangle_bottom -= yoff;
2256 
2257             widget_factory::MoveWidget(info, info->size);
2258         }
2259 
2260         if (info)
2261         {
2262             if (parent == (GX_WIDGET *) get_root_window())
2263             {
2264                 project->AddWidgetToFolder(selected_folder, info);
2265             }
2266             else
2267             {
2268                 project->AddWidgetToParent(selected, info);
2269             }
2270             UndoManager()->AddEntry(UNDO_TYPE_INSERT_WIDGET, info);
2271 
2272             BOOL update_size = FALSE;
2273             switch(parent->gx_widget_type)
2274             {
2275             case GX_TYPE_VERTICAL_LIST:
2276             case GX_TYPE_POPUP_LIST:
2277                 gx_vertical_list_children_position((GX_VERTICAL_LIST *) parent);
2278                 update_size = TRUE;
2279                 break;
2280 
2281             case GX_TYPE_HORIZONTAL_LIST:
2282                 gx_horizontal_list_children_position((GX_HORIZONTAL_LIST *) parent);
2283                 update_size = TRUE;
2284                 break;
2285 
2286             case GX_TYPE_ACCORDION_MENU:
2287             case GX_TYPE_TREE_VIEW:
2288             case GX_TYPE_MENU:
2289                 GetProjectView()->CheckParentRefresh(parent);
2290                 update_size = TRUE;
2291                 break;
2292 
2293             case GX_TYPE_GENERIC_SCROLL_WHEEL:
2294                 gx_generic_scroll_wheel_children_position((GX_GENERIC_SCROLL_WHEEL*)parent);
2295                 update_size = TRUE;
2296                 break;
2297 
2298             default:
2299                 SelectWidget(info, TRUE, FALSE);
2300                 break;
2301             }
2302 
2303             if (update_size)
2304             {
2305                 memcpy_s(&info->size, sizeof(info->size), &info->widget->gx_widget_size, sizeof(GX_RECTANGLE));
2306                 GetPropsWin()->WidgetWasModified(info);
2307             }
2308         }
2309     }
2310     else
2311     {
2312         ErrorMsg("Internal error: Service provider is not available");
2313     }
2314 }
2315 
2316 ///////////////////////////////////////////////////////////////////////////////
OnAddTemplate(widget_info * base)2317 void target_screen::OnAddTemplate(widget_info *base)
2318 {
2319     GX_WIDGET *parent = NULL;
2320     folder_info *selected_folder = NULL;
2321     studiox_project *project = GetOpenProject();
2322 
2323     if (!project)
2324     {
2325         return;
2326     }
2327 
2328     widget_info *selected = GetSingleSelect();
2329 
2330     if (selected)
2331     {
2332         if (selected ->basetype == GX_TYPE_DROP_LIST)
2333         {
2334             ErrorMsg("Child widgets must be added to the drop-list popup using the gx_drop_list_popup_get API");
2335             return;
2336         }
2337         if (base->basetype == GX_TYPE_HORIZONTAL_SCROLL ||
2338             base->basetype == GX_TYPE_VERTICAL_SCROLL)
2339         {
2340             if (selected->basetype < GX_TYPE_WINDOW)
2341             {
2342                 ErrorMsg("Scroll bars can only be added to Window parents");
2343                 return;
2344             }
2345         }
2346         parent = selected->widget;
2347     }
2348     else
2349     {
2350         if (GetProjectView()->IsFolderSelected())
2351         {
2352             selected_folder = GetProjectView()->GetSelectedFolder();
2353             if (!selected_folder)
2354             {
2355                 return;
2356             }
2357             parent = (GX_WIDGET *) get_root_window();
2358         }
2359 
2360     }
2361 
2362     if (!parent)
2363     {
2364         return;
2365     }
2366     template_service_provider *provider = (template_service_provider *) widget_factory::GetServiceProvider(GX_TYPE_TEMPLATE);
2367 
2368     if (provider)
2369     {
2370         widget_info *info = provider->CreateNewInstance(parent, base);
2371 
2372         if (info)
2373         {
2374             if (parent == (GX_WIDGET *) get_root_window())
2375             {
2376                 project->AddWidgetToFolder(selected_folder, info);
2377             }
2378             else
2379             {
2380                 project->AddWidgetToParent(selected, info);
2381             }
2382             UndoManager()->AddEntry(UNDO_TYPE_INSERT_WIDGET, info);
2383 
2384             switch(parent->gx_widget_type)
2385             {
2386             case GX_TYPE_VERTICAL_LIST:
2387             case GX_TYPE_POPUP_LIST:
2388                 gx_vertical_list_children_position((GX_VERTICAL_LIST *) parent);
2389                 break;
2390 
2391             case GX_TYPE_HORIZONTAL_LIST:
2392                 gx_horizontal_list_children_position((GX_HORIZONTAL_LIST *) parent);
2393                 break;
2394 
2395             case GX_TYPE_ACCORDION_MENU:
2396             case GX_TYPE_TREE_VIEW:
2397                 GetProjectView()->CheckParentRefresh(parent);
2398                 break;
2399 
2400             default:
2401                 SelectWidget(info, TRUE, FALSE);
2402                 break;
2403             }
2404         }
2405     }
2406     else
2407     {
2408         ErrorMsg("Internal error: Service provider not available");
2409     }
2410 }
2411 
2412 ///////////////////////////////////////////////////////////////////////////////
TestDropItem(resource_item * item,CPoint InPoint,BOOL shifted)2413 void target_screen::TestDropItem(resource_item *item,
2414      CPoint InPoint, BOOL shifted)
2415 {
2416     int display;
2417     GX_POINT point;
2418     GX_WIDGET *root = (GX_WIDGET *) get_root_window();
2419 
2420     ScreenToClient(&InPoint);
2421 
2422     int scale = GetZoomScale();
2423 
2424     point.gx_point_x = (GX_VALUE)(InPoint.x * 100 / scale);
2425     point.gx_point_y = (GX_VALUE)(InPoint.y * 100 / scale);
2426     widget_info *info;
2427 
2428     studiox_project *project = GetOpenProject();
2429 
2430     if (!project)
2431     {
2432         return;
2433     }
2434     int DisplayIndex = GetProjectView()->GetActiveDisplay();
2435 
2436     GX_WIDGET *target = _gx_system_top_widget_find(root, point, 0);
2437 
2438     if (!target || target == root)
2439     {
2440         return;
2441     }
2442     info = project->FindWidgetInfo(target);
2443     widget_service_provider *provider = widget_factory::GetServiceProvider(target->gx_widget_type);
2444 
2445     if (!info || !provider)
2446     {
2447         return;
2448     }
2449 
2450     if (info->basetype == GX_TYPE_TEMPLATE)
2451     {
2452         // cannot change properties of item based on template
2453         return;
2454     }
2455 
2456     int type = RES_TYPE_STRING;
2457 
2458     if (item->mpRes)
2459     {
2460         type = item->mpRes->type;
2461     }
2462 
2463     switch(type)
2464     {
2465     case RES_TYPE_FONT:
2466         UndoManager()->AddEntry(UNDO_TYPE_FONT, info, 0);
2467         provider->AssignFont(info, 0, project->GetResourceId(DisplayIndex, item->mpRes));
2468         break;
2469 
2470     case RES_TYPE_COLOR:
2471         if (shifted)
2472         {
2473             UndoManager()->AddEntry(UNDO_TYPE_COLOR, info, 1);
2474             provider->AssignColor(info, 1, project->GetResourceId(DisplayIndex, item->mpRes));
2475         }
2476         else
2477         {
2478             UndoManager()->AddEntry(UNDO_TYPE_COLOR, info, 0);
2479             provider->AssignColor(info, 0, project->GetResourceId(DisplayIndex, item->mpRes));
2480         }
2481         break;
2482 
2483     case RES_TYPE_PIXELMAP:
2484         if (shifted)
2485         {
2486             UndoManager()->AddEntry(UNDO_TYPE_PIXELMAP, info, 1);
2487             provider->AssignPixelmap(info, 1, project->GetResourceId(DisplayIndex, item->mpRes));
2488         }
2489         else
2490         {
2491             UndoManager()->AddEntry(UNDO_TYPE_PIXELMAP, info, 0);
2492             provider->AssignPixelmap(info, 0, project->GetResourceId(DisplayIndex, item->mpRes));
2493         }
2494         break;
2495 
2496     case RES_TYPE_STRING:
2497         display = GetProjectView()->GetActiveDisplay();
2498         if (display >= 0)
2499         {
2500             UndoManager()->AddEntry(UNDO_TYPE_STRING, info, 0);
2501             string_table *pt = project->mDisplays[display].stable;
2502             provider->AssignText(info, 0, pt->GetResourceId(item->GetStringId()));
2503         }
2504         break;
2505 
2506     default:
2507         break;
2508     }
2509     // update the properties window
2510     GetPropsWin()->WidgetWasModified(info);
2511     project->SetModified();
2512 }
2513 
2514 
2515 ///////////////////////////////////////////////////////////////////////////////
OnAlignLeft()2516 void target_screen::OnAlignLeft()
2517 {
2518     int index;
2519     int left = 65535;
2520     GX_RECTANGLE newsize;
2521 
2522     if (!SelectedWidgetsCanBeMoved())
2523     {
2524         return;
2525     }
2526 
2527     if (SelectedWidgets.GetCount() > 1)
2528     {
2529         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2530         {
2531             if (SelectedWidgets[index].info->widget->gx_widget_size.gx_rectangle_left < left)
2532             {
2533                 left = SelectedWidgets[index].info->widget->gx_widget_size.gx_rectangle_left;
2534             }
2535         }
2536         UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
2537 
2538         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2539         {
2540             GX_WIDGET *selected = SelectedWidgets[index].info->widget;
2541 
2542             if (selected->gx_widget_size.gx_rectangle_left != left)
2543             {
2544                 newsize = selected->gx_widget_size;
2545                 gx_utility_rectangle_shift(&newsize, left - newsize.gx_rectangle_left, 0);
2546                 widget_factory::MoveWidget(SelectedWidgets[index].info, newsize);
2547             }
2548         }
2549     }
2550 }
2551 
2552 ///////////////////////////////////////////////////////////////////////////////
OnAlignTop()2553 void target_screen::OnAlignTop()
2554 {
2555     int index;
2556     int top = 65535;
2557     GX_RECTANGLE newsize;
2558     GX_WIDGET *selected;
2559 
2560     if (!SelectedWidgetsCanBeMoved())
2561     {
2562         return;
2563     }
2564 
2565     if (SelectedWidgets.GetCount() > 1)
2566     {
2567         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2568         {
2569             selected = SelectedWidgets[index].info->widget;
2570 
2571             if (selected->gx_widget_size.gx_rectangle_top < top)
2572             {
2573                 top = selected->gx_widget_size.gx_rectangle_top;
2574             }
2575         }
2576         UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
2577 
2578         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2579         {
2580             selected = SelectedWidgets[index].info->widget;
2581             if (selected->gx_widget_size.gx_rectangle_top != top)
2582             {
2583                 newsize = selected->gx_widget_size;
2584                 gx_utility_rectangle_shift(&newsize, 0, top - newsize.gx_rectangle_top);
2585                 widget_factory::MoveWidget(SelectedWidgets[index].info, newsize);
2586             }
2587         }
2588     }
2589 }
2590 
2591 ///////////////////////////////////////////////////////////////////////////////
OnAlignRight()2592 void target_screen::OnAlignRight()
2593 {
2594     int index;
2595     int right = -65535;
2596     GX_RECTANGLE newsize;
2597     GX_WIDGET *selected;
2598 
2599     if (!SelectedWidgetsCanBeMoved())
2600     {
2601         return;
2602     }
2603 
2604     if (SelectedWidgets.GetCount() > 1)
2605     {
2606         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2607         {
2608             selected = SelectedWidgets[index].info->widget;
2609 
2610             if (selected->gx_widget_size.gx_rectangle_right > right)
2611             {
2612                 right = selected->gx_widget_size.gx_rectangle_right;
2613             }
2614         }
2615         UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
2616 
2617         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2618         {
2619             selected = SelectedWidgets[index].info->widget;
2620             if (selected->gx_widget_size.gx_rectangle_right != right)
2621             {
2622                 newsize = selected->gx_widget_size;
2623                 gx_utility_rectangle_shift(&newsize, right - newsize.gx_rectangle_right, 0);
2624                 widget_factory::MoveWidget(SelectedWidgets[index].info, newsize);
2625             }
2626         }
2627     }
2628 
2629 }
2630 
2631 ///////////////////////////////////////////////////////////////////////////////
OnAlignBottom()2632 void target_screen::OnAlignBottom()
2633 {
2634     int index;
2635     int bottom = -65535;
2636     GX_RECTANGLE newsize;
2637     GX_WIDGET *selected;
2638 
2639     if (!SelectedWidgetsCanBeMoved())
2640     {
2641         return;
2642     }
2643 
2644     if (SelectedWidgets.GetCount() > 1)
2645     {
2646         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2647         {
2648             selected = SelectedWidgets[index].info->widget;
2649 
2650             if (selected->gx_widget_size.gx_rectangle_bottom > bottom)
2651             {
2652                 bottom = selected->gx_widget_size.gx_rectangle_bottom;
2653             }
2654         }
2655         UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
2656 
2657         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2658         {
2659             selected = SelectedWidgets[index].info->widget;
2660             if (selected->gx_widget_size.gx_rectangle_bottom != bottom)
2661             {
2662                 newsize = selected->gx_widget_size;
2663                 gx_utility_rectangle_shift(&newsize, 0, bottom - newsize.gx_rectangle_bottom);
2664                 widget_factory::MoveWidget(SelectedWidgets[index].info, newsize);
2665             }
2666         }
2667     }
2668 }
2669 
2670 ///////////////////////////////////////////////////////////////////////////////
OnHSpaceEqually()2671 void target_screen::OnHSpaceEqually()
2672 {
2673     GX_WIDGET *selected;
2674     GX_RECTANGLE size;
2675     int index;
2676     int used_space = 0;
2677     int left = 65535;
2678     int right = -65535;
2679     int total_space = 0;
2680     int inner_space = 0;
2681     int left_most_index;
2682     int right_neighbor_index;
2683 
2684     if (!SelectedWidgetsCanBeMoved())
2685     {
2686         return;
2687     }
2688 
2689     int count = SelectedWidgets.GetCount();
2690 
2691     if (count > 2)
2692     {
2693         for (index = 0; index < count; index++)
2694         {
2695             selected = SelectedWidgets[index].info->widget;
2696             if (selected->gx_widget_size.gx_rectangle_left < left)
2697             {
2698                 left = selected->gx_widget_size.gx_rectangle_left;
2699                 left_most_index = index;
2700             }
2701             if (selected->gx_widget_size.gx_rectangle_right > right)
2702             {
2703                 right = selected->gx_widget_size.gx_rectangle_right;
2704             }
2705             used_space += (selected->gx_widget_size.gx_rectangle_right - selected->gx_widget_size.gx_rectangle_left) + 1;
2706         }
2707 
2708         total_space = right - left + 1;
2709         inner_space = ((total_space - used_space) + count) / (count - 1);
2710 
2711         // OK, starting with the left-most index, find the widget that is nearest moving right. Use the left
2712         // edge to determine "nearest", if widgets are overlapped and wider than each other then some strange
2713         // things might happen, nothing we can do about that.
2714 
2715         right_neighbor_index = FindNearestSelected(left_most_index, FALSE);
2716         UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
2717 
2718         while (right_neighbor_index >= 0)
2719         {
2720             selected = SelectedWidgets[right_neighbor_index].info->widget;
2721             size = selected->gx_widget_size;
2722             left = SelectedWidgets[left_most_index].info->widget->gx_widget_size.gx_rectangle_right + inner_space;
2723 
2724             if (size.gx_rectangle_left != left)
2725             {
2726                 gx_utility_rectangle_shift(&size, left - size.gx_rectangle_left, 0);
2727                 widget_factory::MoveWidget(SelectedWidgets[right_neighbor_index].info, size);
2728             }
2729             left_most_index = right_neighbor_index;
2730             right_neighbor_index = FindNearestSelected(left_most_index, FALSE);
2731         }
2732     }
2733 }
2734 
2735 ///////////////////////////////////////////////////////////////////////////////
OnVSpaceEqually()2736 void target_screen::OnVSpaceEqually()
2737 {
2738     GX_WIDGET *selected;
2739     GX_RECTANGLE size;
2740     int index;
2741     int used_space = 0;
2742     int top = 65535;
2743     int bottom = -65535;
2744     int total_space = 0;
2745     int inner_space = 0;
2746     int top_most_index;
2747     int below_neighbor_index;
2748 
2749     if (!SelectedWidgetsCanBeMoved())
2750     {
2751         return;
2752     }
2753 
2754     int count = SelectedWidgets.GetCount();
2755 
2756     if (count > 2)
2757     {
2758         for (index = 0; index < count; index++)
2759         {
2760             selected = SelectedWidgets[index].info->widget;
2761             if (selected->gx_widget_size.gx_rectangle_top < top)
2762             {
2763                 top = selected->gx_widget_size.gx_rectangle_top;
2764                 top_most_index = index;
2765             }
2766             if (selected->gx_widget_size.gx_rectangle_bottom > bottom)
2767             {
2768                 bottom = selected->gx_widget_size.gx_rectangle_bottom;
2769             }
2770             used_space += (selected->gx_widget_size.gx_rectangle_bottom - selected->gx_widget_size.gx_rectangle_top) + 1;
2771         }
2772 
2773         total_space = bottom - top + 1;
2774         inner_space = ((total_space - used_space) + count) / (count - 1);
2775 
2776         // OK, starting with the left-most index, find the widget that is nearest moving right. Use the left
2777         // edge to determine "nearest", if widgets are overlapped and wider than each other then some strange
2778         // things might happen, nothing we can do about that.
2779 
2780         below_neighbor_index = FindNearestSelected(top_most_index, TRUE);
2781         UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
2782 
2783         while (below_neighbor_index >= 0)
2784         {
2785             selected = SelectedWidgets[below_neighbor_index].info->widget;
2786             size = selected->gx_widget_size;
2787             top = SelectedWidgets[top_most_index].info->widget->gx_widget_size.gx_rectangle_bottom + inner_space;
2788 
2789             if (size.gx_rectangle_top != top)
2790             {
2791                 gx_utility_rectangle_shift(&size, 0, top - size.gx_rectangle_top);
2792                 widget_factory::MoveWidget(SelectedWidgets[below_neighbor_index].info, size);
2793             }
2794             top_most_index = below_neighbor_index;
2795             below_neighbor_index = FindNearestSelected(top_most_index, TRUE);
2796         }
2797     }
2798 }
2799 
2800 ///////////////////////////////////////////////////////////////////////////////
OnMakeEqualWidth()2801 void target_screen::OnMakeEqualWidth()
2802 {
2803     int index;
2804     int widest = 0;
2805     int width;
2806     GX_RECTANGLE newsize;
2807     widget_info *selected;
2808 
2809     studiox_project *project = GetOpenProject();
2810     if (project && project->IsWidgetPositionLocked())
2811     {
2812         return;
2813     }
2814 
2815     if (SelectedWidgets.GetCount() > 1)
2816     {
2817         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2818         {
2819             selected = SelectedWidgets[index].info;
2820 
2821             width = selected->size.gx_rectangle_right - selected->size.gx_rectangle_left + 1;
2822             if (width > widest)
2823             {
2824                 widest = width;
2825             }
2826         }
2827         UndoManager()->AddEntry(UNDO_TYPE_SIZE, SelectedWidgets);
2828 
2829         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2830         {
2831             selected = SelectedWidgets[index].info;
2832             width = selected->size.gx_rectangle_right - selected->size.gx_rectangle_left + 1;
2833 
2834             if (width != widest)
2835             {
2836                 newsize = selected->size;
2837                 newsize.gx_rectangle_right = newsize.gx_rectangle_left + widest - 1;
2838 
2839                 if (selected->basetype == GX_TYPE_RADIAL_PROGRESS_BAR)
2840                 {
2841                     newsize.gx_rectangle_bottom = newsize.gx_rectangle_top + widest - 1;
2842                 }
2843 
2844                 widget_factory::MoveWidget(selected, newsize);
2845                 WidgetWasMoved(selected);
2846             }
2847         }
2848         project_view::CheckParentRefresh(SelectedWidgets[0].info->widget->gx_widget_parent);
2849     }
2850 }
2851 
2852 ///////////////////////////////////////////////////////////////////////////////
OnMakeEqualHeight()2853 void target_screen::OnMakeEqualHeight()
2854 {
2855     int index;
2856     int tallest = 0;
2857     int height;
2858     GX_RECTANGLE newsize;
2859     widget_info *selected;
2860 
2861     studiox_project *project = GetOpenProject();
2862     if (project && project->IsWidgetPositionLocked())
2863     {
2864         return;
2865     }
2866 
2867     if (SelectedWidgets.GetCount() > 1)
2868     {
2869         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2870         {
2871             selected = SelectedWidgets[index].info;
2872 
2873             height = selected->size.gx_rectangle_bottom - selected->size.gx_rectangle_top + 1;
2874             if (height > tallest)
2875             {
2876                 tallest = height;
2877             }
2878         }
2879         UndoManager()->AddEntry(UNDO_TYPE_SIZE, SelectedWidgets);
2880 
2881         for (index = 0; index < SelectedWidgets.GetCount(); index++)
2882         {
2883             selected = SelectedWidgets[index].info;
2884             height = selected->size.gx_rectangle_bottom - selected->size.gx_rectangle_top + 1;
2885 
2886             if (height != tallest)
2887             {
2888                 newsize = selected->size;
2889                 newsize.gx_rectangle_bottom = newsize.gx_rectangle_top + tallest - 1;
2890 
2891                 if (selected->basetype == GX_TYPE_RADIAL_PROGRESS_BAR)
2892                 {
2893                     newsize.gx_rectangle_right = newsize.gx_rectangle_left + tallest - 1;
2894                 }
2895 
2896                 widget_factory::MoveWidget(selected, newsize);
2897                 WidgetWasMoved(selected);
2898             }
2899         }
2900         project_view::CheckParentRefresh(SelectedWidgets[0].info->widget->gx_widget_parent);
2901     }
2902 }
2903 
2904 ///////////////////////////////////////////////////////////////////////////////
OnAutosize()2905 void target_screen::OnAutosize()
2906 {
2907     int index;
2908     widget_info *selected;
2909     studiox_project *project = GetOpenProject();
2910 
2911     if (project && project->IsWidgetPositionLocked())
2912     {
2913         return;
2914     }
2915 
2916     UndoManager()->AddEntry(UNDO_TYPE_SIZE, SelectedWidgets);
2917 
2918     for (index = 0; index < SelectedWidgets.GetCount(); index++)
2919     {
2920         selected = SelectedWidgets[index].info;
2921 
2922         if (selected && project)
2923         {
2924             widget_service_provider *provider = widget_factory::GetServiceProvider(selected->basetype);
2925 
2926             if (provider)
2927             {
2928                 provider->Autosize(selected);
2929             }
2930         }
2931     }
2932 }
2933 
2934 ///////////////////////////////////////////////////////////////////////////////
ZoomIn(int scale)2935 void target_screen::ZoomIn(int scale)
2936 {
2937     SetZoomScale(scale);
2938     studiox_project *project = GetOpenProject();
2939 
2940     if (!project)
2941     {
2942         return;
2943     }
2944     display_info *info = &project->mDisplays[m_display_index];
2945 
2946     int width;
2947     int height;
2948 
2949     if (project->mDisplays[m_display_index].rotation_angle == GX_SCREEN_ROTATION_CW ||
2950         project->mDisplays[m_display_index].rotation_angle == GX_SCREEN_ROTATION_CCW)
2951     {
2952         width = (info->yres - 1) * scale / 100;
2953         height = (info->xres - 1) * scale / 100;
2954     }
2955     else
2956     {
2957         width = (info->xres - 1) * scale / 100;
2958         height = (info->yres - 1) * scale / 100;
2959     }
2960 
2961     // resize target screen
2962     SetWindowPos(NULL, 0, 0, width, height, SWP_NOMOVE);
2963 
2964     target_frame *frame = (target_frame *)GetParent();
2965     frame->UpdateScrollSize();
2966     frame->Invalidate();
2967 
2968     UpdateWindowPos();
2969 }
2970 
2971 ///////////////////////////////////////////////////////////////////////////////
FindNearestSelected(int start_index,BOOL vertical)2972 int target_screen::FindNearestSelected(int start_index, BOOL vertical)
2973 {
2974     int count = SelectedWidgets.GetCount();
2975     int test_index;
2976     int test_dist;
2977     int start_edge;
2978     int least_index = -1;
2979     int least_dist = 65535;
2980 
2981     if (start_index >= 0 && start_index < count)
2982     {
2983         if (vertical)
2984         {
2985             start_edge = SelectedWidgets[start_index].info->size.gx_rectangle_top;
2986         }
2987         else
2988         {
2989             start_edge = SelectedWidgets[start_index].info->size.gx_rectangle_left;
2990         }
2991 
2992         for (test_index = 0; test_index < count; test_index++)
2993         {
2994             if (test_index != start_index)
2995             {
2996                 if (vertical)
2997                 {
2998                     test_dist = SelectedWidgets[test_index].info->size.gx_rectangle_top - start_edge;
2999                 }
3000                 else
3001                 {
3002                     test_dist = SelectedWidgets[test_index].info->size.gx_rectangle_left - start_edge;
3003                 }
3004 
3005                 if (test_dist > 0 && test_dist < least_dist)
3006                 {
3007                     least_dist = test_dist;
3008                     least_index = test_index;
3009                 }
3010             }
3011         }
3012     }
3013     return least_index;
3014 }
3015 
3016 #define QUOTIENT 0x04c11db7
3017 
3018 ///////////////////////////////////////////////////////////////////////////////
crc32_init(void)3019 void target_screen::crc32_init(void)
3020 {
3021     int i, j;
3022 
3023     unsigned int crc;
3024 
3025     for (i = 0; i < 256; i++)
3026     {
3027         crc = i << 24;
3028         for (j = 0; j < 8; j++)
3029         {
3030             if (crc & 0x80000000)
3031                 crc = (crc << 1) ^ QUOTIENT;
3032             else
3033                 crc = crc << 1;
3034         }
3035         crc_table[i] = crc;
3036     }
3037 }
3038 
3039 ///////////////////////////////////////////////////////////////////////////////
calc_crc(unsigned char * data,int len)3040 unsigned int target_screen::calc_crc(unsigned char *data, int len)
3041 {
3042     unsigned int        result;
3043     int                 i;
3044 
3045     crc32_init();
3046 
3047     result = *data++ << 24;
3048     result |= *data++ << 16;
3049     result |= *data++ << 8;
3050     result |= *data++;
3051     result = ~ result;
3052     len -=4;
3053 
3054     for (i=0; i<len; i++)
3055     {
3056         result = (result << 8 | *data++) ^ crc_table[result >> 24];
3057     }
3058 
3059     return ~result;
3060 }
3061 
3062 ///////////////////////////////////////////////////////////////////////////////
canvas_to_bitmap(CString filename,GX_CANVAS * canvas)3063 void target_screen::canvas_to_bitmap(CString filename, GX_CANVAS *canvas)
3064 {
3065     CFile *p_file = new CFile();
3066 
3067     if (!p_file->Open(filename, CFile::modeCreate | CFile::modeWrite))
3068     {
3069         CString msg;
3070         msg.Format(_T("Could not open bmp file:\n%s\nPlease check file path."), filename);
3071         ErrorMsg(msg);
3072         delete p_file;
3073         return;
3074     }
3075 
3076     BITMAPFILEHEADER file_header;
3077     GX_BMP_INFO info;
3078 
3079     GX_DISPLAY *display;
3080     GX_WIN32_DISPLAY_DRIVER_DATA *driver_instance;
3081 
3082     display = canvas->gx_canvas_display;
3083     driver_instance = (GX_WIN32_DISPLAY_DRIVER_DATA *)(display->gx_display_driver_data);
3084     info = driver_instance->win32_driver_bmpinfo;
3085     info.gx_bmp_header.biHeight *= -1;
3086 
3087     memset(&file_header, 0, sizeof(BITMAPFILEHEADER));
3088 
3089     file_header.bfType = 'MB';
3090     file_header.bfSize = canvas->gx_canvas_memory_size + sizeof(BITMAPFILEHEADER) + sizeof(GX_BMP_INFO);
3091     file_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(GX_BMP_INFO);
3092     p_file->Write(&file_header, sizeof(BITMAPFILEHEADER));
3093     p_file->Write(&info, sizeof(GX_BMP_INFO));
3094     p_file->Write(canvas->gx_canvas_memory, canvas->gx_canvas_memory_size);
3095 
3096     p_file->Close();
3097     delete p_file;
3098 }
3099 
3100 ///////////////////////////////////////////////////////////////////////////////
target_screen_to_bitmap(CString filename,GX_CANVAS * canvas)3101 void target_screen::target_screen_to_bitmap(CString filename, GX_CANVAS *canvas)
3102 {
3103     LPBYTE lpBits;              // memory pointer
3104     CDC *dc = GetDC();
3105     HDC hDC = dc->GetSafeHdc();
3106     CRect rect;
3107 
3108     GetClientRect(&rect);
3109 
3110     HDC hdcMem = CreateCompatibleDC(hDC);
3111     HBITMAP hbmMem = CreateCompatibleBitmap(hDC, rect.Width(), rect.Height());
3112 
3113     SelectObject(hdcMem, hbmMem);
3114 
3115     BitBlt(hdcMem, 0, 0, rect.Width(), rect.Height(), hDC, 0, 0, SRCCOPY);
3116 
3117     GX_BMP_INFO info;
3118     GX_DISPLAY *display;
3119     GX_WIN32_DISPLAY_DRIVER_DATA *driver_instance;
3120 
3121     display = canvas->gx_canvas_display;
3122     driver_instance = (GX_WIN32_DISPLAY_DRIVER_DATA *)(display->gx_display_driver_data);
3123 
3124     BITMAP bitmap;
3125     GetObject(hbmMem, sizeof(BITMAP), &bitmap);
3126 
3127     info = driver_instance->win32_driver_bmpinfo;
3128     info.gx_bmp_header.biWidth = bitmap.bmWidth;
3129     info.gx_bmp_header.biHeight = -bitmap.bmHeight;
3130     info.gx_bmp_header.biSizeImage = ((bitmap.bmWidth * info.gx_bmp_header.biBitCount + 31) / 32) * 4 * bitmap.bmHeight;
3131 
3132     lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, info.gx_bmp_header.biSizeImage);
3133 
3134     // Removed by Guo. This assert cannot be build by release.
3135     //assert(lpBits);
3136 
3137     // Retrieve the color table (RGBQUAD array) and the bits
3138     // (array of palette indices) from the DIB.
3139     GetDIBits(hdcMem, hbmMem, 0, info.gx_bmp_header.biHeight, lpBits, (LPBITMAPINFO)&info, DIB_RGB_COLORS);
3140 
3141     // Create the .BMP file.
3142     CFile *p_file = new CFile();
3143 
3144     if (!p_file->Open(filename, CFile::modeCreate | CFile::modeWrite))
3145     {
3146         CString msg;
3147         msg.Format(_T("Could not open bmp file:\n%s\nPlease check file path."), filename);
3148         ErrorMsg(msg);
3149         delete p_file;
3150         return;
3151     }
3152 
3153     BITMAPFILEHEADER file_header;
3154     memset(&file_header, 0, sizeof(BITMAPFILEHEADER));
3155 
3156     file_header.bfType = 'MB';
3157     file_header.bfSize = info.gx_bmp_header.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(GX_BMP_INFO);
3158     file_header.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(GX_BMP_INFO);
3159 
3160     p_file->Write(&file_header, sizeof(BITMAPFILEHEADER));
3161     p_file->Write(&info, sizeof(GX_BMP_INFO));
3162     p_file->Write(lpBits, info.gx_bmp_header.biSizeImage);
3163 
3164     p_file->Close();
3165     delete p_file;
3166 
3167     DeleteDC(hdcMem);
3168     DeleteObject(hbmMem);
3169     GlobalFree((HGLOBAL)lpBits);
3170 }
3171 
3172 ///////////////////////////////////////////////////////////////////////////////
OnTestMessage(WPARAM wParam,LPARAM lParam)3173 LRESULT target_screen::OnTestMessage(WPARAM wParam, LPARAM lParam)
3174 {
3175     GX_WINDOW_ROOT *root;
3176     GX_CANVAS *canvas;
3177     LRESULT result = 0;
3178     int xshift, yshift;
3179     GX_WIDGET *top;
3180     widget_info *base = NULL;
3181     studiox_project *project;
3182     CStringArray param;
3183     int x, y, display;
3184 
3185     switch(wParam)
3186     {
3187     case TEST_GENERATE_CHECKSUM:
3188         //SelectWidget(NULL, FALSE, FALSE);
3189         if(GetOpenProject())
3190         {
3191             DeSelect();
3192             GetProjectView()->DeSelect();
3193 
3194             _gx_system_canvas_refresh();
3195             root = get_root_window();
3196             canvas = root->gx_window_root_canvas;
3197             result = calc_crc((unsigned char *)canvas->gx_canvas_memory, canvas->gx_canvas_memory_size);
3198         }
3199         break;
3200 
3201     case TEST_GENERATE_SCREENSHOT:
3202         if (GetOpenProject())
3203         {
3204             root = get_root_window();
3205             canvas_to_bitmap(GetTestingParam(0), root->gx_window_root_canvas);
3206         }
3207         break;
3208 
3209     case TEST_DESELECT:
3210         DeSelect();
3211         GetProjectView()->DeSelect();
3212         break;
3213 
3214     case TEST_DIRTY_ROOT_WINDOW:
3215         root = get_root_window();
3216         gx_system_dirty_mark(root);
3217         break;
3218 
3219     case TEST_MOVE_WINDOW:
3220         project = GetOpenProject();
3221         xshift = yshift = lParam;
3222         root = get_root_window();
3223         top = root->gx_widget_first_child;
3224         SelectWidget(project->FindWidgetInfo(top), FALSE, FALSE);
3225         ShiftSelectedWidgets(xshift, yshift);
3226         break;
3227 
3228     case TEST_MOVE_SELECTED:
3229         xshift = yshift = lParam;
3230         ShiftSelectedWidgets(xshift, yshift);
3231         break;
3232 
3233     case TEST_ADD_WIDGET:
3234         OnAddWidget(lParam);
3235         break;
3236 
3237     case TEST_ADD_TEMPLATE:
3238         project = GetOpenProject();
3239         if (project)
3240         {
3241             SplitString(GetTestingParam(0), ',', &param);
3242             display = _tstoi(param.GetAt(1));
3243             if (display >= 0)
3244             {
3245                 base = project->FindWidgetInfo(project->mDisplays[display].GetFirstChildFolder(), (CString)param.GetAt(0), FALSE);
3246             }
3247             if (base)
3248             {
3249                 OnAddTemplate(base);
3250             }
3251         }
3252         break;
3253 
3254     case TEST_ZOOM_IN:
3255         ZoomIn(lParam);
3256         break;
3257 
3258     case TEST_LBUTTON_DOWN:
3259         SplitString(GetTestingParam(0), ',', &param);
3260         x = _tstoi(param.GetAt(0));
3261         y = _tstoi(param.GetAt(1));
3262         SendMessage(WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
3263         break;
3264 
3265     case TEST_LBUTTON_UP:
3266         SplitString(GetTestingParam(0), ',', &param);
3267         x = _tstoi(param.GetAt(0));
3268         y = _tstoi(param.GetAt(1));
3269         SendMessage(WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x, y));
3270         break;
3271 
3272     case TEST_MOUSEMOVE:
3273     case TEST_MOUSEMOVE_POST:
3274         if (wParam == TEST_MOUSEMOVE_POST)
3275         {
3276             SplitString(GetTestingParam(1), ',', &param);
3277         }
3278         else
3279         {
3280             SplitString(GetTestingParam(0), ',', &param);
3281         }
3282         x = _tstoi(param.GetAt(0));
3283         y = _tstoi(param.GetAt(1));
3284         SendMessage(WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(x, y));
3285         break;
3286 
3287     default:
3288         break;
3289     }
3290     return result;
3291 }
3292