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), ',', ¶m);
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), ',', ¶m);
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), ',', ¶m);
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), ',', ¶m);
3277 }
3278 else
3279 {
3280 SplitString(GetTestingParam(0), ',', ¶m);
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