mirror of
https://github.com/azure-rtos/guix.git
synced 2025-02-04 07:13:17 +08:00
3292 lines
93 KiB
C++
3292 lines
93 KiB
C++
|
|
#include "studiox_includes.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
#define SELECT_BOX_LINE_WIDTH 1
|
|
#define SELECT_HANDLE_SIZE 5
|
|
#define DEFAULT_CROSSHAIR_SIZE 10
|
|
|
|
int vsnap_line_list[SNAP_LINE_TYPE_COUNT / 2] = {
|
|
SNAP_LINE_TYPE_LEFT,
|
|
SNAP_LINE_TYPE_VERTICAL,
|
|
SNAP_LINE_TYPE_RIGHT
|
|
};
|
|
|
|
int hsnap_line_list[SNAP_LINE_TYPE_COUNT / 2] = {
|
|
SNAP_LINE_TYPE_TOP,
|
|
SNAP_LINE_TYPE_HORIZONTAL,
|
|
SNAP_LINE_TYPE_BOTTOM
|
|
};
|
|
|
|
CArray<WIDGET_SELECT_ENTRY> SelectedWidgets;
|
|
#define DRAG_ALL NUM_SIZE_HANDLES
|
|
ULONG select_pattern = 0xf0f0f0f0;
|
|
|
|
enum drag_modes {
|
|
DRAG_NONE = 0,
|
|
DRAG_TOP_LEFT,
|
|
DRAG_TOP,
|
|
DRAG_TOP_RIGHT,
|
|
DRAG_RIGHT,
|
|
DRAG_BOTTOM_RIGHT,
|
|
DRAG_BOTTOM,
|
|
DRAG_BOTTOM_LEFT,
|
|
DRAG_LEFT,
|
|
DRAG_ALL
|
|
};
|
|
|
|
enum target_screen_test_commands{
|
|
TEST_GENERATE_CHECKSUM = 1,
|
|
TEST_GENERATE_SCREENSHOT,
|
|
TEST_DESELECT,
|
|
TEST_DIRTY_ROOT_WINDOW,
|
|
TEST_MOVE_WINDOW,
|
|
TEST_MOVE_SELECTED,
|
|
TEST_ADD_WIDGET,
|
|
TEST_ADD_TEMPLATE,
|
|
TEST_ZOOM_IN,
|
|
TEST_LBUTTON_DOWN,
|
|
TEST_LBUTTON_UP,
|
|
TEST_MOUSEMOVE,
|
|
TEST_MOUSEMOVE_POST
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// the custom drawing function for my GUI selection box:
|
|
extern "C" {
|
|
VOID SelectBoxDraw(GX_WIDGET *widget)
|
|
{
|
|
int count = SelectedWidgets.GetCount();
|
|
int index;
|
|
|
|
for (index = 0; index < count; index++)
|
|
{
|
|
WIDGET_SELECT_ENTRY selected = SelectedWidgets.GetAt(index);
|
|
if (selected.info->widget == widget)
|
|
{
|
|
// we found the widget, call it's original draw function
|
|
selected.draw_func(widget);
|
|
|
|
// draw the outer outline
|
|
gx_context_raw_brush_define(0x00ffffff, 0x00000000, GX_BRUSH_OUTLINE);
|
|
gx_context_brush_width_set(1);
|
|
gx_context_brush_pattern_set(select_pattern);
|
|
gx_canvas_rectangle_draw(&widget->gx_widget_size);
|
|
gx_context_brush_pattern_set(0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void RefreshSelectedWidgets()
|
|
{
|
|
int index;
|
|
int count = SelectedWidgets.GetCount();
|
|
|
|
if ((!count) || IsGuixCanvasRefreshBlocked())
|
|
{
|
|
return;
|
|
}
|
|
|
|
ULONG temp = select_pattern & 0x03;
|
|
select_pattern >>= 2;
|
|
temp <<= 30;
|
|
select_pattern |= temp;
|
|
|
|
GX_RECTANGLE invalid;
|
|
|
|
invalid = SelectedWidgets[0].info->widget->gx_widget_size;
|
|
|
|
for (index = 1; index < count; index++)
|
|
{
|
|
gx_utility_rectangle_combine(&invalid, &SelectedWidgets[index].info->widget->gx_widget_size);
|
|
}
|
|
GX_CANVAS *canvas;
|
|
gx_widget_canvas_get(SelectedWidgets[0].info->widget, &canvas);
|
|
|
|
GX_ENTER_CRITICAL
|
|
_gx_canvas_drawing_initiate(canvas,
|
|
(GX_WIDGET *) get_root_window(), &invalid);
|
|
|
|
gx_context_raw_brush_define(0x00ffffff, 0x00000000, GX_BRUSH_OUTLINE);
|
|
gx_context_brush_width_set(1);
|
|
|
|
for (index = 0; index < count; index++)
|
|
{
|
|
WIDGET_SELECT_ENTRY entry = SelectedWidgets[index];
|
|
_gx_canvas_drawing_initiate(canvas,
|
|
entry.info->widget, &entry.info->widget->gx_widget_size);
|
|
gx_context_brush_pattern_set(select_pattern);
|
|
gx_canvas_rectangle_draw(&entry.info->widget->gx_widget_size);
|
|
_gx_canvas_drawing_complete(canvas, GX_FALSE);
|
|
}
|
|
gx_context_brush_pattern_set(0);
|
|
|
|
/* Indicate that drawing on this canvas is complete. */
|
|
_gx_canvas_drawing_complete(canvas, GX_TRUE);
|
|
GX_EXIT_CRITICAL
|
|
|
|
WPARAM wparam = MAKEWPARAM(invalid.gx_rectangle_left, invalid.gx_rectangle_top);
|
|
LPARAM lparam = MAKELPARAM(invalid.gx_rectangle_right, invalid.gx_rectangle_bottom);
|
|
PostMessage(get_target_win_handle(), GUIX_DIRTY, wparam, lparam);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
VOID _gx_system_timer_update(VOID);
|
|
|
|
VOID CALLBACK TimerProc(
|
|
_In_ HWND hwnd,
|
|
_In_ UINT uMsg,
|
|
_In_ UINT_PTR idEvent,
|
|
_In_ DWORD dwTime)
|
|
{
|
|
//_gx_system_timer_update();
|
|
RefreshSelectedWidgets();
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(target_screen, CWnd)
|
|
ON_WM_PAINT()
|
|
ON_WM_ERASEBKGND()
|
|
ON_WM_CREATE()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_MESSAGE(GUIX_READY, target_screen::OnGuixReady)
|
|
ON_MESSAGE(GUIX_DIRTY, target_screen::OnGuixDirty)
|
|
ON_MESSAGE(STUDIO_TEST, OnTestMessage)
|
|
END_MESSAGE_MAP()
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
target_screen::target_screen()
|
|
{
|
|
GX_RECTANGLE size;
|
|
gx_utility_rectangle_define(&size, 0, 0, 0, 0);
|
|
SelectedWidgets.RemoveAll();
|
|
mpSelectedParent = NULL;
|
|
m_display_index = -1;
|
|
mDragMode = DRAG_NONE;
|
|
mpDragSelected = NULL;
|
|
mFoldUndo = FALSE;
|
|
mZoomScale = 100;
|
|
mGridSnapInfo.crosshair_enabled = FALSE;
|
|
mGridSnapInfo.crosshair_size = DEFAULT_CROSSHAIR_SIZE;
|
|
mGridSnapInfo.snap_line_count = 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::PreCreateWindow(CREATESTRUCT& cs)
|
|
{
|
|
if( !CWnd::PreCreateWindow(cs) )
|
|
return FALSE;
|
|
// TODO: Modify the Window class or styles here by modifying
|
|
// the CREATESTRUCT cs
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::UpdateWindowPos()
|
|
{
|
|
target_frame *frame = (target_frame *)GetParent();
|
|
CRect frame_size;
|
|
CRect size;
|
|
int width;
|
|
int height;
|
|
|
|
GetClientRect(&size);
|
|
width = size.Width();
|
|
height = size.Height();
|
|
|
|
frame->GetClientRect(&frame_size);
|
|
|
|
if (size.Width() > frame_size.Width())
|
|
{
|
|
size.left -= frame->GetScrollPos(SB_HORZ);
|
|
}
|
|
else
|
|
{
|
|
size.left = (frame_size.Width() - width) >> 1;
|
|
}
|
|
|
|
if (size.Height() > frame_size.Height())
|
|
{
|
|
size.top = -frame->GetScrollPos(SB_VERT);
|
|
}
|
|
else
|
|
{
|
|
size.top = (frame_size.Height() - height) >> 1;
|
|
}
|
|
|
|
size.right = size.left + width;
|
|
size.bottom = size.top + height;
|
|
|
|
MoveWindow(&size);
|
|
GX_WIDGET *root = (GX_WIDGET *) get_root_window();
|
|
gx_system_dirty_mark(root);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
int target_screen::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
CWnd::OnCreate(lpCreateStruct);
|
|
SetWindowText(_T("Target Screen"));
|
|
CenterWindow();
|
|
EnableWindow(TRUE);
|
|
initialize_guix(m_hWnd);
|
|
SetTimer(1, 500, TimerProc);
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnCloseProject(void)
|
|
{
|
|
GX_DISPLAY *target_display = get_target_view_display();
|
|
SwitchTopWidget(NULL);
|
|
GetResourceView()->CleanupDisplayResources(target_display);
|
|
GetTargetScreen()->ConfigureDisplay(-1);
|
|
guix_cleanup_target_win_canvas();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
GX_WIDGET *target_screen::FindSelectedWidget(GX_POINT point)
|
|
{
|
|
for (int index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
if (gx_utility_rectangle_point_detect(&SelectedWidgets[index].info->widget->gx_widget_size, point))
|
|
{
|
|
return SelectedWidgets[index].info->widget;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*return parent type. return 0 while do not have parent or pointer is wrong.*/
|
|
USHORT target_screen::GetWidgetParentType(widget_info *info)
|
|
{
|
|
GX_WIDGET *parent = NULL;
|
|
USHORT type = 0;
|
|
|
|
if (info)
|
|
{
|
|
if (info->widget)
|
|
{
|
|
parent = info->widget->gx_widget_parent;
|
|
if (parent)
|
|
{
|
|
type = parent->gx_widget_type;
|
|
}
|
|
}
|
|
}
|
|
return type;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// is this moving of child widget of horizontal/vertical list allowed?
|
|
BOOL target_screen::IsWidgetResizable(USHORT parent_type, widget_info *info, GX_RECTANGLE &new_size)
|
|
{
|
|
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (!project)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (project->IsWidgetPositionLocked())
|
|
{
|
|
if (info->size.gx_rectangle_left != new_size.gx_rectangle_left ||
|
|
info->size.gx_rectangle_top != new_size.gx_rectangle_top ||
|
|
info->size.gx_rectangle_right != new_size.gx_rectangle_right ||
|
|
info->size.gx_rectangle_bottom != new_size.gx_rectangle_bottom)
|
|
{
|
|
Notify("Widget position is locked, resize is not allowed!");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
switch (parent_type)
|
|
{
|
|
case GX_TYPE_HORIZONTAL_LIST:
|
|
if ((info->size.gx_rectangle_left != new_size.gx_rectangle_left) ||
|
|
(info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
|
|
(info->size.gx_rectangle_bottom != new_size.gx_rectangle_bottom))
|
|
{
|
|
Notify("Only right-side size change of horizontal list child widget is allowed.");
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case GX_TYPE_VERTICAL_LIST:
|
|
if ((info->size.gx_rectangle_left != new_size.gx_rectangle_left) ||
|
|
(info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
|
|
(info->size.gx_rectangle_right != new_size.gx_rectangle_right))
|
|
{
|
|
Notify("Only bottom-side size change of vertical list child widget is allowed.");
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case GX_TYPE_ACCORDION_MENU:
|
|
if ((info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
|
|
(info->size.gx_rectangle_left != new_size.gx_rectangle_left) ||
|
|
(info->size.gx_rectangle_right != new_size.gx_rectangle_right))
|
|
{
|
|
Notify("Only bottom-side size change of accordion menu child widget is allowed.");
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case GX_TYPE_MENU_LIST:
|
|
if ((info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
|
|
(info->size.gx_rectangle_left != new_size.gx_rectangle_left))
|
|
{
|
|
Notify("Only bottom and right side size change of menu list child widget is allowed.");
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case GX_TYPE_TREE_VIEW:
|
|
if ((info->size.gx_rectangle_top != new_size.gx_rectangle_top) ||
|
|
(info->size.gx_rectangle_left != new_size.gx_rectangle_left))
|
|
{
|
|
Notify("Only bottom and right side size change of tree view child widget is allowed.");
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case GX_TYPE_GENERIC_SCROLL_WHEEL:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::SelectedWidgetsCanBeMoved()
|
|
{
|
|
GX_WIDGET *selected;
|
|
studiox_project *project;
|
|
|
|
project = GetOpenProject();
|
|
if (!project)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (project->IsWidgetPositionLocked())
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for (int index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info->widget;
|
|
|
|
switch(selected->gx_widget_type)
|
|
{
|
|
case GX_TYPE_VERTICAL_SCROLL:
|
|
case GX_TYPE_HORIZONTAL_SCROLL:
|
|
return FALSE;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (selected->gx_widget_parent)
|
|
{
|
|
switch (selected->gx_widget_parent->gx_widget_type)
|
|
{
|
|
case GX_TYPE_VERTICAL_LIST:
|
|
case GX_TYPE_HORIZONTAL_LIST:
|
|
case GX_TYPE_ACCORDION_MENU:
|
|
case GX_TYPE_MENU_LIST:
|
|
case GX_TYPE_TREE_VIEW:
|
|
case GX_TYPE_GENERIC_SCROLL_WHEEL:
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
GX_POINT gxp;
|
|
int scale = GetZoomScale();
|
|
|
|
point.x = point.x * 100 / scale;
|
|
point.y = point.y * 100 / scale;
|
|
|
|
gxp.gx_point_x = (GX_VALUE)point.x;
|
|
gxp.gx_point_y = (GX_VALUE)point.y;
|
|
|
|
mFoldUndo = FALSE;
|
|
|
|
if (nFlags & MK_CONTROL)
|
|
{
|
|
SelectWidget(gxp, TRUE);
|
|
return;
|
|
}
|
|
|
|
mDragMode = CheckResizeCursor(point);
|
|
|
|
if (mDragMode != DRAG_NONE)
|
|
{
|
|
mDragStart = gxp;
|
|
}
|
|
else
|
|
{
|
|
if (!SelectWidget(gxp))
|
|
{
|
|
// Add a check here to see if the click is inside one of multiple:
|
|
GX_WIDGET* find = FindSelectedWidget(gxp);
|
|
if (find && SelectedWidgetsCanBeMoved())
|
|
{
|
|
mDragMode = DRAG_ALL;
|
|
mDragStart = gxp;
|
|
mpDragSelected = find;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((nFlags & MK_LBUTTON) && (mDragMode != DRAG_NONE))
|
|
{
|
|
int delta_x = 0;
|
|
int delta_y = 0;
|
|
CalSnapDelta(delta_x, delta_y, 0);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnRButtonDown(UINT nFlags, CPoint pos)
|
|
{
|
|
OnLButtonDown(nFlags, pos);
|
|
|
|
widget_info *selected = GetSingleSelect();
|
|
|
|
if (selected)
|
|
{
|
|
CMenu menu;
|
|
CMenu* pPopup;
|
|
|
|
//Load top level menu
|
|
menu.LoadMenu(IDR_WIDGET_MENU);
|
|
pPopup = menu.GetSubMenu(0);
|
|
ClientToScreen(&pos);
|
|
|
|
CMainFrame *pMain = (CMainFrame *)AfxGetMainWnd();
|
|
CMenu insert_menu;
|
|
CMenu base_menu;
|
|
CMenu *pInsertMenu;
|
|
|
|
insert_menu.LoadMenu(IDR_INSERT_MENU);
|
|
pInsertMenu = insert_menu.GetSubMenu(0);
|
|
|
|
if (pInsertMenu)
|
|
{
|
|
pInsertMenu->RemoveMenu(ID_INSERT_FOLDER, MF_BYCOMMAND);
|
|
|
|
if (GetProjectView()->CreateBaseMenu(&base_menu))
|
|
{
|
|
pInsertMenu->AppendMenu(MF_POPUP, (UINT)base_menu.m_hMenu, _T("Template"));
|
|
}
|
|
|
|
pPopup->AppendMenu(MF_POPUP, (UINT)pInsertMenu->m_hMenu, _T("Insert"));
|
|
}
|
|
|
|
//show pop up menu
|
|
pPopup->TrackPopupMenu(TPM_LEFTALIGN, pos.x, pos.y, (CMainFrame *) AfxGetMainWnd());
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
mDragMode = DRAG_NONE;
|
|
mFoldUndo = FALSE;
|
|
|
|
if (mGridSnapInfo.crosshair_enabled)
|
|
{
|
|
InvalidateCrosshairArea();
|
|
mGridSnapInfo.crosshair_enabled = FALSE;
|
|
}
|
|
|
|
if (mGridSnapInfo.snap_line_count)
|
|
{
|
|
InvalidateSnapLineArea();
|
|
mGridSnapInfo.snap_line_count = 0;
|
|
}
|
|
|
|
mpDragSelected = NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*The following two functions will reposition the neibor widget.*/
|
|
void target_screen::RepositionListChildren(widget_info *info)
|
|
{
|
|
widget_info *neighbor_info;
|
|
USHORT type = GetWidgetParentType(info);
|
|
GX_RECTANGLE newsize;
|
|
|
|
if ((type == GX_TYPE_VERTICAL_LIST) ||
|
|
(type == GX_TYPE_ACCORDION_MENU))
|
|
{
|
|
if (info->GetNextWidgetInfo())
|
|
{
|
|
neighbor_info = info->GetNextWidgetInfo();
|
|
int shift = neighbor_info->size.gx_rectangle_top - info->size.gx_rectangle_bottom;
|
|
while (neighbor_info)
|
|
{
|
|
/*Reposition the nether neighbor widgets(if has one). */
|
|
newsize = neighbor_info->size;
|
|
newsize.gx_rectangle_top -= shift;
|
|
newsize.gx_rectangle_bottom -= shift;
|
|
|
|
widget_factory::MoveWidget(neighbor_info, newsize);
|
|
neighbor_info = neighbor_info->GetNextWidgetInfo();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (type == GX_TYPE_HORIZONTAL_LIST)
|
|
{
|
|
if (info->GetNextWidgetInfo())
|
|
{
|
|
neighbor_info = info->GetNextWidgetInfo();
|
|
INT shift = neighbor_info->size.gx_rectangle_left - info->size.gx_rectangle_right;
|
|
/*Reposition the right neighbor widgets(if has one).*/
|
|
while (neighbor_info)
|
|
{
|
|
newsize = neighbor_info->size;
|
|
newsize.gx_rectangle_left -= shift;
|
|
newsize.gx_rectangle_right -= shift;
|
|
widget_factory::MoveWidget(neighbor_info, newsize);
|
|
neighbor_info = neighbor_info->GetNextWidgetInfo();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::WidgetWasMoved(widget_info *info)
|
|
{
|
|
/*Check the basetype of the widget and its parent to
|
|
see if we need to reposition the parent widget.*/
|
|
|
|
if (!info)
|
|
{
|
|
return;
|
|
}
|
|
|
|
USHORT parent_type = GetWidgetParentType(info);
|
|
widget_info *menu_info;
|
|
|
|
switch (info->basetype)
|
|
{
|
|
case GX_TYPE_VERTICAL_LIST:
|
|
case GX_TYPE_HORIZONTAL_LIST:
|
|
case GX_TYPE_ACCORDION_MENU:
|
|
case GX_TYPE_TREE_VIEW:
|
|
case GX_TYPE_GENERIC_SCROLL_WHEEL:
|
|
GetProjectView()->CheckParentRefresh(info);
|
|
break;
|
|
|
|
default:
|
|
switch (parent_type)
|
|
{
|
|
case GX_TYPE_HORIZONTAL_LIST:
|
|
case GX_TYPE_VERTICAL_LIST:
|
|
RepositionListChildren(info);
|
|
break;
|
|
|
|
case GX_TYPE_ACCORDION_MENU:
|
|
case GX_TYPE_TREE_VIEW:
|
|
menu_info = GetOpenProject()->FindWidgetInfo(info->widget->gx_widget_parent);
|
|
gx_system_dirty_mark(menu_info->widget);
|
|
GetProjectView()->CheckParentRefresh(menu_info);
|
|
break;
|
|
|
|
case GX_TYPE_MENU_LIST:
|
|
{
|
|
GX_MENU_LIST *menu_list = (GX_MENU_LIST *)info->widget->gx_widget_parent;
|
|
|
|
menu_info = GetOpenProject()->FindWidgetInfo(menu_list->gx_menu_list_owner);
|
|
GetProjectView()->CheckParentRefresh(menu_info);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
widget_info *target_screen::GetSingleSelect()
|
|
{
|
|
if (SelectedWidgets.GetCount() == 1)
|
|
{
|
|
return SelectedWidgets.GetAt(0).info;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::IsWidgetSelected(GX_WIDGET *widget)
|
|
{
|
|
for (int index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
if (SelectedWidgets.GetAt(index).info->widget == widget)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::CopySelectedWidgets()
|
|
{
|
|
widget_info *selected;
|
|
CArray<widget_info *> info_list;
|
|
int index;
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (!project)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info;
|
|
|
|
if (selected)
|
|
{
|
|
info_list.Add(selected);
|
|
}
|
|
}
|
|
|
|
if (info_list.GetCount())
|
|
{
|
|
copy_paste_engine cpe;
|
|
cpe.CopyToClipboard(info_list, m_hWnd);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::ShiftSelectedWidgets(int delta_x, int delta_y)
|
|
{
|
|
widget_info *selected;
|
|
GX_RECTANGLE size;
|
|
int index;
|
|
|
|
UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets, mFoldUndo);
|
|
mFoldUndo = TRUE;
|
|
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info;
|
|
|
|
if (selected)
|
|
{
|
|
size = selected->widget->gx_widget_size;
|
|
gx_utility_rectangle_shift(&size, delta_x, delta_y);
|
|
widget_factory::MoveWidget(selected, size);
|
|
}
|
|
}
|
|
|
|
GetPropsWin()->WidgetWasMoved();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
int target_screen::CheckResizeCursor(CPoint point)
|
|
{
|
|
GX_RECTANGLE select_outer;
|
|
GX_RECTANGLE select_inner;
|
|
GX_POINT test;
|
|
int drag_mode = DRAG_NONE;
|
|
|
|
widget_info *selected = GetSingleSelect();
|
|
if (!selected)
|
|
{
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
|
return DRAG_NONE;
|
|
}
|
|
|
|
if (selected->widget->gx_widget_type == GX_TYPE_HORIZONTAL_SCROLL ||
|
|
selected->widget->gx_widget_type == GX_TYPE_VERTICAL_SCROLL)
|
|
{
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
|
return DRAG_NONE;
|
|
}
|
|
|
|
select_outer = selected->widget->gx_widget_size;
|
|
select_inner = select_outer;
|
|
gx_utility_rectangle_resize(&select_outer, 5);
|
|
test.gx_point_x = (GX_VALUE)point.x;
|
|
test.gx_point_y = (GX_VALUE)point.y;
|
|
|
|
if (gx_utility_rectangle_point_detect(&select_outer, test))
|
|
{
|
|
if (gx_utility_rectangle_point_detect(&select_inner, test))
|
|
{
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
|
return DRAG_NONE;
|
|
}
|
|
|
|
// we are between two rectangles, figure out where:
|
|
if (test.gx_point_y < select_inner.gx_rectangle_top)
|
|
{
|
|
if (test.gx_point_x < select_inner.gx_rectangle_left)
|
|
{
|
|
// top left corner
|
|
drag_mode = DRAG_TOP_LEFT;
|
|
}
|
|
else
|
|
{
|
|
if (test.gx_point_x > select_inner.gx_rectangle_right)
|
|
{
|
|
// top right corner
|
|
drag_mode = DRAG_TOP_RIGHT;
|
|
}
|
|
else
|
|
{
|
|
// top
|
|
drag_mode = DRAG_TOP;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (test.gx_point_y > select_inner.gx_rectangle_bottom)
|
|
{
|
|
if (test.gx_point_x < select_inner.gx_rectangle_left)
|
|
{
|
|
// bottom left corner
|
|
drag_mode = DRAG_BOTTOM_LEFT;
|
|
}
|
|
else
|
|
{
|
|
if (test.gx_point_x > select_inner.gx_rectangle_right)
|
|
{
|
|
// bottom right corner
|
|
drag_mode = DRAG_BOTTOM_RIGHT;
|
|
}
|
|
else
|
|
{
|
|
// bottom
|
|
drag_mode = DRAG_BOTTOM;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (test.gx_point_x < select_inner.gx_rectangle_left)
|
|
{
|
|
drag_mode = DRAG_LEFT;
|
|
}
|
|
else
|
|
{
|
|
drag_mode = DRAG_RIGHT;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selected->basetype == GX_TYPE_RADIAL_PROGRESS_BAR)
|
|
{
|
|
drag_mode = ConvertRadialProgressDragMode(drag_mode, select_inner, test);
|
|
}
|
|
|
|
switch (drag_mode)
|
|
{
|
|
case DRAG_LEFT:
|
|
case DRAG_RIGHT:
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
|
|
break;
|
|
|
|
case DRAG_TOP:
|
|
case DRAG_BOTTOM:
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
|
|
break;
|
|
|
|
case DRAG_TOP_LEFT:
|
|
case DRAG_BOTTOM_RIGHT:
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE));
|
|
break;
|
|
|
|
case DRAG_TOP_RIGHT:
|
|
case DRAG_BOTTOM_LEFT:
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENESW));
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
|
drag_mode = DRAG_NONE;
|
|
}
|
|
return drag_mode;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
int target_screen::CalSnap2GridDelta(int value, int &delta)
|
|
{
|
|
if (!delta)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int spacing = GetOpenProject()->mHeader.grid_spacing;
|
|
int half_spacing = spacing / 2;
|
|
int dist;
|
|
int snap_dist = 0;
|
|
|
|
// Calculate the distance from the new position to the grid line.
|
|
dist = (value + delta) % spacing;
|
|
|
|
if (dist != 0)
|
|
{
|
|
// Snap to grid.
|
|
if (abs(dist) < half_spacing)
|
|
{
|
|
snap_dist = -dist;
|
|
}
|
|
else
|
|
{
|
|
int sign = abs(dist) / dist;
|
|
snap_dist = (spacing * sign - dist);
|
|
}
|
|
}
|
|
|
|
delta += snap_dist;
|
|
|
|
return snap_dist;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::OnAltKeyDown()
|
|
{
|
|
BOOL result = FALSE;
|
|
if (mGridSnapInfo.crosshair_enabled)
|
|
{
|
|
InvalidateCrosshairArea();
|
|
mGridSnapInfo.crosshair_enabled = FALSE;
|
|
result = TRUE;
|
|
}
|
|
|
|
if (mGridSnapInfo.snap_line_count)
|
|
{
|
|
InvalidateSnapLineArea();
|
|
mGridSnapInfo.snap_line_count = 0;
|
|
result = TRUE;
|
|
}
|
|
|
|
if (result)
|
|
{
|
|
CPoint pt;
|
|
GetCursorPos(&pt);
|
|
ScreenToClient(&pt);
|
|
|
|
int x, y;
|
|
x = pt.x;
|
|
y = pt.y;
|
|
SendMessage(WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(x, y));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::InvalidateCrosshairArea()
|
|
{
|
|
CRect rect;
|
|
int scale;
|
|
|
|
if (mGridSnapInfo.crosshair_enabled)
|
|
{
|
|
scale = GetZoomScale();
|
|
|
|
rect.left = mGridSnapInfo.crosshair_cx - mGridSnapInfo.crosshair_size;
|
|
rect.right = mGridSnapInfo.crosshair_cx + mGridSnapInfo.crosshair_size;
|
|
rect.top = mGridSnapInfo.crosshair_cy - mGridSnapInfo.crosshair_size;
|
|
rect.bottom = mGridSnapInfo.crosshair_cy + mGridSnapInfo.crosshair_size;
|
|
|
|
scale = GetZoomScale();
|
|
|
|
rect.left = rect.left * scale / 100;
|
|
rect.top = rect.top * scale / 100;
|
|
rect.right = (rect.right + 1) * scale / 100;
|
|
rect.bottom = (rect.bottom + 1) * scale / 100;
|
|
|
|
InvalidateRect(&rect);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::InvalidateSnapLineArea()
|
|
{
|
|
SNAPLINE_INFO *snapline;
|
|
CRect rect;
|
|
INT scale;
|
|
|
|
// Invalidate snap line areas.
|
|
for (int index = 0; index < mGridSnapInfo.snap_line_count; index++)
|
|
{
|
|
snapline = &mGridSnapInfo.snap_lines[index];
|
|
|
|
if (snapline->direction == SNAP_LINE_DIRECTION_VERTICAL)
|
|
{
|
|
rect.left = snapline->target_x_y;
|
|
rect.top = snapline->target_top_left;
|
|
rect.right = snapline->target_x_y + 1;
|
|
rect.bottom = snapline->target_bottom_right + 1;
|
|
}
|
|
else
|
|
{
|
|
rect.left = snapline->target_top_left;
|
|
rect.top = snapline->target_x_y;
|
|
rect.right = snapline->target_bottom_right + 1;
|
|
rect.bottom = snapline->target_x_y + 1;
|
|
}
|
|
|
|
scale = GetZoomScale();
|
|
|
|
rect.left = rect.left * scale / 100;
|
|
rect.top = rect.top * scale / 100;
|
|
rect.right = rect.right * scale / 100;
|
|
rect.bottom = rect.bottom * scale / 100;
|
|
|
|
InvalidateRect(&rect);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::UpdateSnapLines(int delta_x, int delta_y)
|
|
{
|
|
SNAPLINE_INFO *snapline;
|
|
|
|
for (int index = 0; index < mGridSnapInfo.snap_line_count; index++)
|
|
{
|
|
snapline = &mGridSnapInfo.snap_lines[index];
|
|
|
|
if (snapline->direction == SNAP_LINE_DIRECTION_VERTICAL)
|
|
{
|
|
// Update source snap line.
|
|
snapline->source_top_left += delta_y;
|
|
snapline->source_bottom_right += delta_y;
|
|
|
|
// Combine source and target snaplines.
|
|
if (snapline->source_top_left < snapline->target_top_left)
|
|
{
|
|
snapline->target_top_left = snapline->source_top_left;
|
|
}
|
|
|
|
if (snapline->source_bottom_right > snapline->target_bottom_right)
|
|
{
|
|
snapline->target_bottom_right = snapline->source_bottom_right;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Update source snapline.
|
|
snapline->source_top_left += delta_x;
|
|
snapline->source_bottom_right += delta_x;
|
|
|
|
// Combine source and target snaplines.
|
|
if (snapline->source_top_left < snapline->target_top_left)
|
|
{
|
|
snapline->target_top_left = snapline->source_top_left;
|
|
}
|
|
|
|
if(snapline->source_bottom_right > snapline->target_bottom_right)
|
|
{
|
|
snapline->target_bottom_right = snapline->source_bottom_right;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
int target_screen::GetSnapLineVal(GX_RECTANGLE &size, int snap_line_type)
|
|
{
|
|
switch (snap_line_type)
|
|
{
|
|
case SNAP_LINE_TYPE_LEFT:
|
|
return size.gx_rectangle_left;
|
|
|
|
case SNAP_LINE_TYPE_RIGHT:
|
|
return size.gx_rectangle_right;
|
|
|
|
case SNAP_LINE_TYPE_VERTICAL:
|
|
return ((size.gx_rectangle_left + size.gx_rectangle_right) >> 1);
|
|
|
|
case SNAP_LINE_TYPE_TOP:
|
|
return size.gx_rectangle_top;
|
|
|
|
case SNAP_LINE_TYPE_BOTTOM:
|
|
return size.gx_rectangle_bottom;
|
|
|
|
case SNAP_LINE_TYPE_HORIZONTAL:
|
|
return ((size.gx_rectangle_top + size.gx_rectangle_bottom) >> 1);
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::IsVerticalSnapLineType(int snap_line_type)
|
|
{
|
|
switch (snap_line_type)
|
|
{
|
|
case SNAP_LINE_TYPE_LEFT:
|
|
case SNAP_LINE_TYPE_RIGHT:
|
|
case SNAP_LINE_TYPE_VERTICAL:
|
|
return TRUE;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::TestAddSnapLine(SNAPLINE_INFO &test)
|
|
{
|
|
SNAPLINE_INFO *snapline;
|
|
|
|
for (int index = 0; index < mGridSnapInfo.snap_line_count; index++)
|
|
{
|
|
snapline = &mGridSnapInfo.snap_lines[index];
|
|
|
|
if ((snapline->direction == test.direction) &&
|
|
(snapline->target_x_y == test.target_x_y))
|
|
{
|
|
if (test.target_top_left < snapline->target_top_left)
|
|
{
|
|
snapline->target_top_left = test.target_top_left;
|
|
}
|
|
|
|
if (test.target_bottom_right > snapline->target_bottom_right)
|
|
{
|
|
snapline->target_bottom_right = test.target_bottom_right;
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (mGridSnapInfo.snap_line_count < MAX_SNAP_LINES)
|
|
{
|
|
mGridSnapInfo.snap_lines[mGridSnapInfo.snap_line_count++] = test;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::ClearSnapLine(int snapline_direction)
|
|
{
|
|
SNAPLINE_INFO *snapline;
|
|
|
|
for (int index = 0; index < mGridSnapInfo.snap_line_count; index++)
|
|
{
|
|
snapline = &mGridSnapInfo.snap_lines[index];
|
|
|
|
if (snapline->direction == snapline_direction)
|
|
{
|
|
mGridSnapInfo.snap_line_count--;
|
|
for (int loop = index; loop < mGridSnapInfo.snap_line_count; loop++)
|
|
{
|
|
mGridSnapInfo.snap_lines[loop] = mGridSnapInfo.snap_lines[loop + 1];
|
|
}
|
|
index--;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::Snap2Widget(GX_RECTANGLE &src_size, GX_RECTANGLE &target_size,
|
|
int src_snap_line_type, int direction,
|
|
int &snap_dist)
|
|
{
|
|
BOOL result = FALSE;
|
|
int src_val;
|
|
int *src_type_list;
|
|
int src_type_count;
|
|
int target_val;
|
|
int target_snap_line_type;
|
|
int *target_type_list;
|
|
int target_type_count;
|
|
int dist;
|
|
|
|
if (src_snap_line_type >= 0)
|
|
{
|
|
src_type_list = &src_snap_line_type;
|
|
src_type_count = 1;
|
|
}
|
|
else
|
|
{
|
|
src_type_count = (SNAP_LINE_TYPE_COUNT / 2);
|
|
}
|
|
|
|
if (direction == SNAP_LINE_DIRECTION_VERTICAL)
|
|
{
|
|
target_type_list = vsnap_line_list;
|
|
|
|
if (src_snap_line_type < 0)
|
|
{
|
|
src_type_list = vsnap_line_list;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
target_type_list = hsnap_line_list;
|
|
|
|
if (src_snap_line_type < 0)
|
|
{
|
|
src_type_list = hsnap_line_list;
|
|
}
|
|
}
|
|
|
|
SNAPLINE_INFO snapline;
|
|
target_type_count = (SNAP_LINE_TYPE_COUNT / 2);
|
|
|
|
for (int src_index = 0; src_index < src_type_count; src_index++)
|
|
{
|
|
src_snap_line_type = src_type_list[src_index];
|
|
src_val = GetSnapLineVal(src_size, src_snap_line_type);
|
|
|
|
for (int target_index = 0; target_index < target_type_count; target_index++)
|
|
{
|
|
target_snap_line_type = target_type_list[target_index];
|
|
target_val = GetSnapLineVal(target_size, target_snap_line_type);
|
|
|
|
dist = target_val - src_val;
|
|
if (GX_ABS(dist) <= GX_ABS(snap_dist))
|
|
{
|
|
if ((GX_ABS(dist) < GX_ABS(snap_dist)) || ((dist * snap_dist) < 0))
|
|
{
|
|
ClearSnapLine(direction);
|
|
}
|
|
|
|
snap_dist = target_val - src_val;
|
|
|
|
snapline.target_x_y = target_val;
|
|
snapline.direction = direction;
|
|
|
|
if (direction == SNAP_LINE_DIRECTION_VERTICAL)
|
|
{
|
|
snapline.target_top_left = target_size.gx_rectangle_top;
|
|
snapline.target_bottom_right = target_size.gx_rectangle_bottom;
|
|
|
|
snapline.source_top_left = src_size.gx_rectangle_top;
|
|
snapline.source_bottom_right = src_size.gx_rectangle_bottom;
|
|
}
|
|
else
|
|
{
|
|
snapline.target_top_left = target_size.gx_rectangle_left;
|
|
snapline.target_bottom_right = target_size.gx_rectangle_right;
|
|
|
|
snapline.source_top_left = src_size.gx_rectangle_left;
|
|
snapline.source_bottom_right = src_size.gx_rectangle_right;
|
|
}
|
|
|
|
TestAddSnapLine(snapline);
|
|
|
|
result = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::CalSnap2WidgetDelta(GX_WIDGET *selected, int &delta, int direction, int snap_dist, int src_snap_line_type)
|
|
{
|
|
GX_WIDGET *parent = selected->gx_widget_parent;
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if ((!parent) || (!project))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
GX_RECTANGLE src_size = selected->gx_widget_size;
|
|
|
|
if (direction == SNAP_LINE_DIRECTION_VERTICAL)
|
|
{
|
|
gx_utility_rectangle_shift(&src_size, delta, 0);
|
|
}
|
|
else
|
|
{
|
|
gx_utility_rectangle_shift(&src_size, 0, delta);
|
|
}
|
|
|
|
if (GX_ABS(snap_dist) > project->mHeader.snap_spacing)
|
|
{
|
|
snap_dist = project->mHeader.snap_spacing;
|
|
}
|
|
|
|
BOOL find = FALSE;
|
|
|
|
if (Snap2Widget(src_size, parent->gx_widget_size, src_snap_line_type, direction, snap_dist))
|
|
{
|
|
find = TRUE;
|
|
}
|
|
|
|
|
|
GX_WIDGET *child = parent->gx_widget_first_child;
|
|
|
|
while (child)
|
|
{
|
|
if ((child != selected) &&
|
|
Snap2Widget(src_size, child->gx_widget_size, src_snap_line_type, direction, snap_dist))
|
|
{
|
|
find = TRUE;
|
|
}
|
|
|
|
child = child->gx_widget_next;
|
|
}
|
|
|
|
if (find)
|
|
{
|
|
delta += snap_dist;
|
|
}
|
|
|
|
return find;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
int target_screen::ConvertRadialProgressDragMode(int drag_mode, GX_RECTANGLE rect, GX_POINT point)
|
|
{
|
|
switch (drag_mode)
|
|
{
|
|
case DRAG_TOP_LEFT:
|
|
if (abs(point.gx_point_x - rect.gx_rectangle_left) < abs(point.gx_point_y - rect.gx_rectangle_top))
|
|
{
|
|
// Mouse cursor is near to left margin
|
|
drag_mode = DRAG_LEFT;
|
|
}
|
|
else
|
|
{
|
|
drag_mode = DRAG_TOP;
|
|
}
|
|
break;
|
|
|
|
case DRAG_TOP_RIGHT:
|
|
if (abs(point.gx_point_x - rect.gx_rectangle_right) < abs(point.gx_point_y - rect.gx_rectangle_top))
|
|
{
|
|
// Mouse cursor is near to right margin
|
|
drag_mode = DRAG_RIGHT;
|
|
}
|
|
else
|
|
{
|
|
drag_mode = DRAG_TOP;
|
|
}
|
|
break;
|
|
|
|
case DRAG_BOTTOM_LEFT:
|
|
if (abs(point.gx_point_x - rect.gx_rectangle_left) < abs(point.gx_point_y - rect.gx_rectangle_bottom))
|
|
{
|
|
drag_mode = DRAG_LEFT;
|
|
}
|
|
else
|
|
{
|
|
drag_mode = DRAG_BOTTOM;
|
|
}
|
|
break;
|
|
|
|
case DRAG_BOTTOM_RIGHT:
|
|
if (abs(point.gx_point_x - rect.gx_rectangle_right) < abs(point.gx_point_y - rect.gx_rectangle_bottom))
|
|
{
|
|
drag_mode = DRAG_RIGHT;
|
|
}
|
|
else
|
|
{
|
|
drag_mode = DRAG_BOTTOM;
|
|
}
|
|
break;;
|
|
}
|
|
|
|
return drag_mode;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::UpdateRadialProgressSize(GX_RECTANGLE *size, int mDragMode, int delta_x, int delta_y)
|
|
{
|
|
switch (mDragMode)
|
|
{
|
|
case DRAG_LEFT:
|
|
size->gx_rectangle_left += delta_x;
|
|
size->gx_rectangle_right -= delta_x;
|
|
size->gx_rectangle_top += delta_x;
|
|
size->gx_rectangle_bottom -= delta_x;
|
|
break;
|
|
|
|
case DRAG_RIGHT:
|
|
size->gx_rectangle_left -= delta_x;
|
|
size->gx_rectangle_right += delta_x;
|
|
size->gx_rectangle_top -= delta_x;
|
|
size->gx_rectangle_bottom += delta_x;
|
|
break;
|
|
|
|
case DRAG_TOP:
|
|
size->gx_rectangle_top += delta_y;
|
|
size->gx_rectangle_bottom -= delta_y;
|
|
size->gx_rectangle_left += delta_y;
|
|
size->gx_rectangle_right -= delta_y;
|
|
break;
|
|
|
|
case DRAG_BOTTOM:
|
|
size->gx_rectangle_top -= delta_y;
|
|
size->gx_rectangle_bottom += delta_y;
|
|
size->gx_rectangle_left -= delta_y;
|
|
size->gx_rectangle_right += delta_y;
|
|
break;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::UpdateWidgetSize(GX_RECTANGLE *size, int mDrawMode, int delta_x, int delta_y)
|
|
{
|
|
switch (mDragMode)
|
|
{
|
|
case DRAG_TOP_LEFT:
|
|
size->gx_rectangle_left += delta_x;
|
|
size->gx_rectangle_top += delta_y;
|
|
break;
|
|
|
|
case DRAG_TOP_RIGHT:
|
|
size->gx_rectangle_right += delta_x;
|
|
size->gx_rectangle_top += delta_y;
|
|
break;
|
|
|
|
case DRAG_BOTTOM_RIGHT:
|
|
size->gx_rectangle_right += delta_x;
|
|
size->gx_rectangle_bottom += delta_y;
|
|
break;
|
|
|
|
case DRAG_BOTTOM_LEFT:
|
|
size->gx_rectangle_left += delta_x;
|
|
size->gx_rectangle_bottom += delta_y;
|
|
break;
|
|
|
|
case DRAG_LEFT:
|
|
size->gx_rectangle_left += delta_x;
|
|
break;
|
|
|
|
case DRAG_RIGHT:
|
|
size->gx_rectangle_right += delta_x;
|
|
break;
|
|
|
|
case DRAG_TOP:
|
|
size->gx_rectangle_top += delta_y;
|
|
break;
|
|
|
|
case DRAG_BOTTOM:
|
|
size->gx_rectangle_bottom += delta_y;
|
|
break;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::CalSnapDelta(int &delta_x, int &delta_y, int snap_dist)
|
|
{
|
|
int nAltKey = GetKeyState(VK_MENU);
|
|
|
|
if (nAltKey & KEY_STATE_DOWN)
|
|
{
|
|
// Disable snap feature when ALT key is down.
|
|
return;
|
|
}
|
|
|
|
studiox_project *project = GetOpenProject();
|
|
project_header *header = &project->mHeader;
|
|
|
|
if ((!header->snap_enabled) && (!header->snap_to_widget_enabled))
|
|
{
|
|
return;
|
|
}
|
|
|
|
GX_WIDGET *selected = SelectedWidgets[0].info->widget;
|
|
GX_RECTANGLE size = selected->gx_widget_size;
|
|
|
|
int snap_delta_x = delta_x;
|
|
int snap_delta_y = delta_y;
|
|
int snap_dist_x = snap_dist;
|
|
int snap_dist_y = snap_dist;
|
|
BOOL snap_result_x = FALSE;
|
|
BOOL snap_result_y = FALSE;
|
|
|
|
if (header->snap_enabled)
|
|
{
|
|
if (mGridSnapInfo.crosshair_enabled)
|
|
{
|
|
InvalidateCrosshairArea();
|
|
mGridSnapInfo.crosshair_enabled = FALSE;
|
|
}
|
|
|
|
// Calculate snap to grid delta and snap distance
|
|
|
|
switch (mDragMode)
|
|
{
|
|
case DRAG_ALL:
|
|
if (mpDragSelected)
|
|
{
|
|
size = mpDragSelected->gx_widget_size;
|
|
|
|
// Calculate center point of drag selected widget.
|
|
mGridSnapInfo.crosshair_cx = ((size.gx_rectangle_left + size.gx_rectangle_right) >> 1);
|
|
mGridSnapInfo.crosshair_cy = ((size.gx_rectangle_top + size.gx_rectangle_bottom) >> 1);
|
|
|
|
// Adjust delta value to make selected center point snap to grid
|
|
snap_dist_x = CalSnap2GridDelta(mGridSnapInfo.crosshair_cx, delta_x);
|
|
snap_dist_y = CalSnap2GridDelta(mGridSnapInfo.crosshair_cy, delta_y);
|
|
|
|
mGridSnapInfo.crosshair_enabled = TRUE;
|
|
}
|
|
break;
|
|
|
|
case DRAG_TOP_LEFT:
|
|
snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_left, delta_x);
|
|
snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_top, delta_y);
|
|
break;
|
|
|
|
case DRAG_TOP_RIGHT:
|
|
snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_right, delta_x);
|
|
snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_top, delta_y);
|
|
break;
|
|
|
|
case DRAG_BOTTOM_RIGHT:
|
|
snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_right, delta_x);
|
|
snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_bottom, delta_y);
|
|
break;
|
|
|
|
case DRAG_BOTTOM_LEFT:
|
|
snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_left, delta_x);
|
|
snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_bottom, delta_y);
|
|
break;
|
|
|
|
case DRAG_LEFT:
|
|
snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_left, delta_x);
|
|
break;
|
|
|
|
case DRAG_RIGHT:
|
|
snap_dist_x = CalSnap2GridDelta(size.gx_rectangle_right, delta_x);
|
|
break;
|
|
|
|
case DRAG_TOP:
|
|
snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_top, delta_y);
|
|
break;
|
|
|
|
case DRAG_BOTTOM:
|
|
snap_dist_y = CalSnap2GridDelta(size.gx_rectangle_bottom, delta_y);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (header->snap_to_widget_enabled)
|
|
{
|
|
if (mGridSnapInfo.snap_line_count)
|
|
{
|
|
// Invalidate old snap line area.
|
|
InvalidateSnapLineArea();
|
|
mGridSnapInfo.snap_line_count = 0;
|
|
}
|
|
|
|
// Calculate snap to widget delta.
|
|
|
|
switch (mDragMode)
|
|
{
|
|
case DRAG_ALL:
|
|
if (mpDragSelected)
|
|
{
|
|
snap_result_x = CalSnap2WidgetDelta(mpDragSelected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x);
|
|
snap_result_y = CalSnap2WidgetDelta(mpDragSelected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y);
|
|
}
|
|
break;
|
|
|
|
case DRAG_TOP_LEFT:
|
|
snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_LEFT);
|
|
snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_TOP);
|
|
break;
|
|
|
|
case DRAG_TOP_RIGHT:
|
|
snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_RIGHT);
|
|
snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_TOP);
|
|
break;
|
|
|
|
case DRAG_BOTTOM_RIGHT:
|
|
snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_RIGHT);
|
|
snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_BOTTOM);
|
|
break;
|
|
|
|
case DRAG_BOTTOM_LEFT:
|
|
snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_LEFT);
|
|
snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_BOTTOM);
|
|
break;
|
|
|
|
case DRAG_LEFT:
|
|
snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_LEFT);
|
|
break;
|
|
|
|
case DRAG_RIGHT:
|
|
snap_result_x = CalSnap2WidgetDelta(selected, snap_delta_x, SNAP_LINE_DIRECTION_VERTICAL, snap_dist_x, SNAP_LINE_TYPE_RIGHT);
|
|
break;
|
|
|
|
case DRAG_TOP:
|
|
snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_TOP);
|
|
break;
|
|
|
|
case DRAG_BOTTOM:
|
|
snap_result_y = CalSnap2WidgetDelta(selected, snap_delta_y, SNAP_LINE_DIRECTION_HORIZONTAL, snap_dist_y, SNAP_LINE_TYPE_BOTTOM);
|
|
break;
|
|
}
|
|
|
|
if (snap_result_x)
|
|
{
|
|
delta_x = snap_delta_x;
|
|
}
|
|
|
|
if (snap_result_y)
|
|
{
|
|
delta_y = snap_delta_y;
|
|
}
|
|
}
|
|
|
|
if (header->snap_enabled && mGridSnapInfo.crosshair_enabled)
|
|
{
|
|
// Update crosshair coordinates
|
|
if (header->snap_enabled)
|
|
{
|
|
mGridSnapInfo.crosshair_cx += delta_x;
|
|
mGridSnapInfo.crosshair_cy += delta_y;
|
|
}
|
|
|
|
InvalidateCrosshairArea();
|
|
}
|
|
|
|
if (header->snap_to_widget_enabled && mGridSnapInfo.snap_line_count)
|
|
{
|
|
// Update snap lines.
|
|
UpdateSnapLines(delta_x, delta_y);
|
|
|
|
// Invalidate new snap line area
|
|
InvalidateSnapLineArea();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
GX_RECTANGLE size;
|
|
int delta_x;
|
|
int delta_y;
|
|
|
|
int scale = GetZoomScale();
|
|
point.x = point.x * 100 / scale;
|
|
point.y = point.y * 100 / scale;
|
|
|
|
if (mDragMode == DRAG_NONE)
|
|
{
|
|
if ((nFlags & MK_LBUTTON) == 0)
|
|
{
|
|
CheckResizeCursor(point);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (nFlags & MK_LBUTTON && SelectedWidgets.GetCount())
|
|
{
|
|
delta_x = point.x - mDragStart.gx_point_x;
|
|
delta_y = point.y - mDragStart.gx_point_y;
|
|
|
|
if (!delta_x && !delta_y)
|
|
{
|
|
return;
|
|
}
|
|
|
|
studiox_project *project = GetOpenProject();
|
|
project_header *header = &project->mHeader;
|
|
|
|
GX_WIDGET *selected = SelectedWidgets[0].info->widget;
|
|
size = selected->gx_widget_size;
|
|
|
|
widget_info *info = project->FindWidgetInfo(selected);
|
|
|
|
if (selected && (header->snap_enabled || header->snap_to_widget_enabled))
|
|
{
|
|
CalSnapDelta(delta_x, delta_y, header->snap_spacing);
|
|
}
|
|
|
|
if (!delta_x && !delta_y)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (mDragMode == DRAG_ALL)
|
|
{
|
|
mDragStart.gx_point_x += delta_x;
|
|
mDragStart.gx_point_y += delta_y;
|
|
|
|
ShiftSelectedWidgets(delta_x, delta_y);
|
|
}
|
|
else
|
|
{
|
|
if (info->basetype == GX_TYPE_RADIAL_PROGRESS_BAR)
|
|
{
|
|
UpdateRadialProgressSize(&size, mDragMode, delta_x, delta_y);
|
|
}
|
|
else
|
|
{
|
|
UpdateWidgetSize(&size, mDragMode, delta_x, delta_y);
|
|
}
|
|
|
|
mDragStart.gx_point_x += delta_x;
|
|
mDragStart.gx_point_y += delta_y;
|
|
|
|
UINT parent_type = GetWidgetParentType(info);
|
|
|
|
/* Check if widget moving is allowed. */
|
|
if (!IsWidgetResizable(parent_type, info, size))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (info)
|
|
{
|
|
UndoManager()->AddEntry(UNDO_TYPE_SIZE, info, 0, mFoldUndo);
|
|
widget_factory::MoveWidget(info, size);
|
|
|
|
WidgetWasMoved(info);
|
|
GetPropsWin()->WidgetWasMoved();
|
|
mFoldUndo = TRUE;
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg("Internal error: widget information is not available");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
LRESULT target_screen::OnGuixReady(WPARAM wp, LPARAM lp)
|
|
{
|
|
Invalidate();
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
LRESULT target_screen::OnGuixDirty(WPARAM wp, LPARAM lp)
|
|
{
|
|
CRect rect;
|
|
|
|
int scale = GetZoomScale();
|
|
|
|
// In guix, rectangle.width = rectangle.right - rectangle.left + 1
|
|
// In mfc, rectangle.width = rectangle.right - rectangle.left
|
|
rect.left = GET_X_LPARAM(wp);
|
|
rect.top = GET_Y_LPARAM(wp);
|
|
rect.right = (GET_X_LPARAM(lp) + 1);
|
|
rect.bottom = (GET_Y_LPARAM(lp) + 1);
|
|
|
|
//scale the guix dirty area to get the screen dirty
|
|
rect.left = rect.left * scale / 100;
|
|
rect.top = rect.top * scale / 100;
|
|
rect.right = rect.right * scale / 100;
|
|
rect.bottom = rect.bottom * scale / 100;
|
|
|
|
InvalidateRect(&rect);
|
|
return 0;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnPaint()
|
|
{
|
|
GX_CANVAS *canvas = get_target_win_canvas();
|
|
|
|
CPaintDC dc(this);
|
|
|
|
if (canvas ->gx_canvas_memory)
|
|
{
|
|
CRect rect;
|
|
GX_RECTANGLE dirty;
|
|
int scale = GetZoomScale();
|
|
|
|
dc.GetClipBox(&rect);
|
|
|
|
//convert screen dirty area to guix dirty area
|
|
rect.left = rect.left * 100 / scale;
|
|
rect.top = rect.top * 100 / scale;
|
|
rect.right = rect.right * 100 / scale;
|
|
rect.bottom = rect.bottom * 100 / scale;
|
|
|
|
gx_utility_rectangle_define(&dirty,
|
|
(GX_VALUE)rect.left,
|
|
(GX_VALUE)rect.top,
|
|
(GX_VALUE)rect.right,
|
|
(GX_VALUE)rect.bottom);
|
|
|
|
if (!IsGuixCanvasRefreshBlocked())
|
|
{
|
|
/* make sure our guix canvas is up to date */
|
|
_gx_system_canvas_refresh();
|
|
}
|
|
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (project)
|
|
{
|
|
if (project->mHeader.grid_enabled)
|
|
{
|
|
mGridSnapInfo.grid_space = project->mHeader.grid_spacing;
|
|
}
|
|
else
|
|
{
|
|
mGridSnapInfo.grid_space = 0;
|
|
|
|
}
|
|
|
|
guix_canvas_paint(dc.GetSafeHdc(), dirty, scale, &mGridSnapInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::OnEraseBkgnd(CDC *pDC)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::DeSelect()
|
|
{
|
|
GX_WIDGET* parent;
|
|
|
|
for (int index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
/* replace the drawing functions replaced to draw the selection box */
|
|
if (SelectedWidgets[index].info->widget)
|
|
{
|
|
SelectedWidgets[index].info->widget->gx_widget_draw_function = SelectedWidgets[index].draw_func;
|
|
|
|
if (SelectedWidgets[index].info->widget->gx_widget_type == GX_TYPE_DROP_LIST)
|
|
{
|
|
gx_drop_list_close((GX_DROP_LIST *) SelectedWidgets[index].info->widget);
|
|
}
|
|
|
|
parent = SelectedWidgets[index].info->widget->gx_widget_parent;
|
|
while (parent)
|
|
{
|
|
if (parent->gx_widget_type == GX_TYPE_DROP_LIST)
|
|
{
|
|
gx_drop_list_close((GX_DROP_LIST *)parent);
|
|
break;
|
|
}
|
|
parent = parent->gx_widget_parent;
|
|
}
|
|
gx_system_dirty_mark(SelectedWidgets[index].info->widget->gx_widget_parent);
|
|
}
|
|
}
|
|
SelectedWidgets.RemoveAll();
|
|
mpSelectedParent = NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::ConfigureDisplay(int display_index, BOOL bForce)
|
|
{
|
|
GX_WIDGET *root = (GX_WIDGET *) get_root_window();
|
|
|
|
if (root)
|
|
{
|
|
while(root->gx_widget_first_child)
|
|
{
|
|
gx_widget_detach(root->gx_widget_first_child);
|
|
}
|
|
}
|
|
|
|
if (m_display_index == display_index && !bForce)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
m_display_index = display_index;
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (display_index >= 0 && project)
|
|
{
|
|
display_info *info = &project->mDisplays[display_index];
|
|
|
|
int canvas_xres = info->xres;
|
|
int canvas_yres = info->yres;
|
|
|
|
if (info->rotation_angle == GX_SCREEN_ROTATION_CW ||
|
|
info->rotation_angle == GX_SCREEN_ROTATION_CCW)
|
|
{
|
|
GX_SWAP_VALS(canvas_xres, canvas_yres);
|
|
}
|
|
|
|
int active_theme = project->mDisplays[display_index].active_theme;
|
|
|
|
// reconfigure the canvas and root window
|
|
if (!guix_configure_target_win_canvas(canvas_xres,
|
|
canvas_yres,
|
|
info->colorformat,
|
|
project->mHeader.target_cpu,
|
|
IsRenesasDave2D(project),
|
|
IsDave2dFontFormat(project, display_index),
|
|
info->themes[active_theme].palette,
|
|
info->themes[active_theme].palette_total_size,
|
|
project->mHeader.palette_mode_aa_text_colors))
|
|
{
|
|
ErrorMsg("Internal Error: Unable to configure GUIX canvas");
|
|
return FALSE;
|
|
}
|
|
|
|
int scale = GetZoomScale();
|
|
|
|
// resize myself to match canvas size:
|
|
SetWindowPos(NULL, 0, 0, canvas_xres * scale / 100, canvas_yres * scale / 100, SWP_NOMOVE);
|
|
|
|
CenterWindow();
|
|
target_frame *frame = (target_frame *) GetParent();
|
|
frame->UpdateScrollSize();
|
|
frame->Invalidate();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::SwitchTopWidget(widget_info *info)
|
|
{
|
|
int DisplayIndex = GetProjectView()->GetActiveDisplay();
|
|
GX_WIDGET *root = (GX_WIDGET *) get_root_window();
|
|
widget_info *old_info;
|
|
|
|
if (!root && DisplayIndex >= 0)
|
|
{
|
|
// if there is an active display but no root window, it
|
|
// means we haven't configured this display yet. Do it now.
|
|
|
|
ConfigureDisplay(DisplayIndex);
|
|
root = (GX_WIDGET *) get_root_window();
|
|
DisplayIndex = -1; // don't configure again
|
|
}
|
|
if (!root)
|
|
{
|
|
// something is badly wrong, but don't crash:
|
|
ErrorMsg("Internal Error: Unable to configure selected display.");
|
|
return;
|
|
}
|
|
if (info)
|
|
{
|
|
if (info->widget == NULL)
|
|
{
|
|
// top level screen has not been created, create it now:
|
|
|
|
widget_factory::GenerateWidgets(NULL, info, TRUE, FALSE);
|
|
if (info->widget == NULL)
|
|
{
|
|
ErrorMsg("Internal Error: Unable to create selected screen.");
|
|
return;
|
|
}
|
|
}
|
|
if (root -> gx_widget_first_child)
|
|
{
|
|
if (root->gx_widget_first_child == info->widget)
|
|
{
|
|
// if the top-level window of this root is already the
|
|
// window we are switching to, then we are done:
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// top-level child is changing, delete the old screen:
|
|
old_info = GetOpenProject()->FindWidgetInfo(root ->gx_widget_first_child);
|
|
if (old_info)
|
|
{
|
|
widget_factory::CleanupWidgets(old_info, TRUE, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DeSelect();
|
|
|
|
if (info)
|
|
{
|
|
// if I haven't checked my display configuration already, do it now:
|
|
if (DisplayIndex >= 0)
|
|
{
|
|
ConfigureDisplay(DisplayIndex);
|
|
}
|
|
|
|
root = (GX_WIDGET *) get_root_window();
|
|
|
|
if (info->widget)
|
|
{
|
|
gx_widget_attach(root, info->widget);
|
|
gx_widget_show(info->widget);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::MakeTopWindowVisible(widget_info *info)
|
|
{
|
|
widget_info *top_info = info;
|
|
widget_info *parent_info = info;
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
GX_WINDOW_ROOT *root = get_root_window();
|
|
|
|
if (!root)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (root->gx_widget_first_child == NULL)
|
|
{
|
|
// No top screen visible right now, need to switch to the top screen of current selected widget
|
|
// Show root window to make new top screen visible
|
|
gx_widget_show(root);
|
|
}
|
|
else
|
|
{
|
|
if (!project || info->widget != NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
while(parent_info)
|
|
{
|
|
parent_info = project->FindParentInfo(parent_info);
|
|
if (parent_info)
|
|
{
|
|
top_info = parent_info;
|
|
}
|
|
}
|
|
if (top_info)
|
|
{
|
|
SwitchTopWidget(top_info);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::SelectWidget(widget_info *info, BOOL echo_to_project_view, BOOL multiple)
|
|
{
|
|
//GX_WIDGET *top_win;
|
|
widget_info *selected = GetSingleSelect();
|
|
|
|
if (info == selected)
|
|
{
|
|
if (echo_to_project_view)
|
|
{
|
|
GetProjectView()->WidgetSelected(info);
|
|
}
|
|
return FALSE;
|
|
}
|
|
if (!multiple)
|
|
{
|
|
DeSelect();
|
|
}
|
|
|
|
if (info == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!echo_to_project_view)
|
|
{
|
|
// this select came from project view,
|
|
// check for switching top-level windows:
|
|
MakeTopWindowVisible(info);
|
|
}
|
|
|
|
if (info->widget == NULL)
|
|
{
|
|
ErrorMsg("Internal Error: Selected widget has not been created");
|
|
return FALSE;
|
|
}
|
|
|
|
GX_WIDGET *parent = info->widget->gx_widget_parent;
|
|
|
|
if (parent && (parent->gx_widget_type == GX_TYPE_ACCORDION_MENU))
|
|
{
|
|
parent = parent->gx_widget_parent;
|
|
}
|
|
|
|
if (parent)
|
|
{
|
|
//check if the widget is a child of a menu list
|
|
GX_WIDGET *menu = GX_NULL;
|
|
|
|
switch (parent->gx_widget_type)
|
|
{
|
|
|
|
case GX_TYPE_MENU_LIST:
|
|
menu = ((GX_MENU_LIST *)parent)->gx_menu_list_owner;
|
|
break;
|
|
|
|
case GX_TYPE_MENU:
|
|
menu = parent;
|
|
break;
|
|
}
|
|
|
|
//expand the menu if it's not expanded.
|
|
if (menu)
|
|
{
|
|
menu_service_provider *provider = (menu_service_provider *)widget_factory::GetServiceProvider(menu->gx_widget_type);
|
|
widget_info *menu_info = GetOpenProject()->FindWidgetInfo(menu);
|
|
provider->AssignStyle(menu_info, menu_info->style | GX_STYLE_MENU_EXPANDED);
|
|
}
|
|
}
|
|
|
|
// when the user selects a drop-list, open the drop list popoup:
|
|
GX_WIDGET *drop_test = info->widget;
|
|
while(drop_test)
|
|
{
|
|
if (drop_test->gx_widget_type == GX_TYPE_DROP_LIST)
|
|
{
|
|
GX_DROP_LIST *drop = (GX_DROP_LIST *) drop_test;
|
|
gx_drop_list_open(drop);
|
|
break;
|
|
}
|
|
drop_test = drop_test->gx_widget_parent;
|
|
}
|
|
|
|
|
|
WIDGET_SELECT_ENTRY new_select;
|
|
new_select.draw_func = info->widget->gx_widget_draw_function;
|
|
new_select.info = info;
|
|
|
|
SelectedWidgets.Add(new_select);
|
|
gx_system_dirty_mark(info->widget);
|
|
|
|
mpSelectedParent = parent;
|
|
|
|
if (echo_to_project_view)
|
|
{
|
|
if (SelectedWidgets.GetCount() <= 1)
|
|
{
|
|
GetProjectView()->WidgetSelected(info);
|
|
}
|
|
else
|
|
{
|
|
GetProjectView()->WidgetSelected(NULL);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL target_screen::SelectWidget(GX_POINT &point, BOOL bMultiple)
|
|
{
|
|
GX_WIDGET *select;
|
|
widget_info *info;
|
|
|
|
GX_WIDGET *root = (GX_WIDGET *) get_root_window();
|
|
|
|
if (!root)
|
|
{
|
|
return FALSE;
|
|
}
|
|
select = _gx_system_top_widget_find(root, point, 0);
|
|
|
|
|
|
/* We must have widget information to select a widget
|
|
(it could be a child of a template)
|
|
*/
|
|
while(select)
|
|
{
|
|
info = GetOpenProject()->FindWidgetInfo(select);
|
|
if (info)
|
|
{
|
|
break;
|
|
}
|
|
select = select->gx_widget_parent;
|
|
}
|
|
|
|
if (!select)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (select == root)
|
|
{
|
|
DeSelect();
|
|
GetProjectView()->WidgetSelected(NULL);
|
|
}
|
|
else
|
|
{
|
|
// certain things we are not allowed to select
|
|
if (select ->gx_widget_type == GX_TYPE_POPUP_LIST)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (select ->gx_widget_parent)
|
|
{
|
|
if (select->gx_widget_parent->gx_widget_type == GX_TYPE_VERTICAL_SCROLL ||
|
|
select->gx_widget_parent->gx_widget_type == GX_TYPE_HORIZONTAL_SCROLL ||
|
|
select->gx_widget_type == GX_TYPE_MENU_LIST)
|
|
{
|
|
select = select->gx_widget_parent;
|
|
}
|
|
}
|
|
if (!IsWidgetSelected(select))
|
|
{
|
|
if (bMultiple && SelectedWidgets.GetCount() > 0)
|
|
{
|
|
if (select->gx_widget_parent !=
|
|
SelectedWidgets[0].info->widget->gx_widget_parent)
|
|
{
|
|
ErrorMsg("When selecting multiple widgets, all selected widgets must have the same parent.");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
SelectWidget(info, TRUE, bMultiple);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnAddWidget(int type)
|
|
{
|
|
widget_info *info;
|
|
folder_info *selected_folder = NULL;
|
|
GX_WIDGET *parent = NULL;
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (!project)
|
|
{
|
|
return;
|
|
}
|
|
|
|
widget_info *selected = GetSingleSelect();
|
|
|
|
if (selected)
|
|
{
|
|
if (type == GX_TYPE_HORIZONTAL_SCROLL ||
|
|
type == GX_TYPE_VERTICAL_SCROLL)
|
|
{
|
|
if (selected->basetype < GX_TYPE_WINDOW)
|
|
{
|
|
ErrorMsg("Scroll bars can only be added to Window parents");
|
|
return;
|
|
}
|
|
}
|
|
else if (type == GX_TYPE_MENU)
|
|
{
|
|
if ((selected->basetype != GX_TYPE_ACCORDION_MENU) &&
|
|
(selected->basetype != GX_TYPE_TREE_VIEW) &&
|
|
(selected->basetype != GX_TYPE_MENU))
|
|
{
|
|
ErrorMsg("The menu widget can only be added to Menu, Accordion Menu and Tree View widgets.");
|
|
return;
|
|
}
|
|
}
|
|
else if (type == GX_TYPE_GENERIC_SCROLL_WHEEL)
|
|
{
|
|
if (project_lib_version() < GX_VERSION_WITH_GENERIC_SCROLL_WHEEL)
|
|
{
|
|
ErrorMsg("The project GUIX library version does not support this widget type.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
parent = selected->widget;
|
|
}
|
|
else
|
|
{
|
|
if (GetProjectView()->IsFolderSelected())
|
|
{
|
|
selected_folder = GetProjectView()->GetSelectedFolder();
|
|
if (!selected_folder)
|
|
{
|
|
return;
|
|
}
|
|
parent = (GX_WIDGET *) get_root_window();
|
|
}
|
|
}
|
|
|
|
widget_service_provider *provider = widget_factory::GetServiceProvider(type);
|
|
|
|
if (provider)
|
|
{
|
|
if (!parent)
|
|
{
|
|
return;
|
|
}
|
|
|
|
info = provider->CreateNewInstance(parent);
|
|
|
|
if (project->mHeader.snap_enabled)
|
|
{
|
|
int grid_spacing = project->mHeader.grid_spacing;
|
|
int xoff = (info->size.gx_rectangle_left) % grid_spacing;
|
|
int yoff = (info->size.gx_rectangle_top) % grid_spacing;
|
|
|
|
info->size.gx_rectangle_left -= xoff;
|
|
info->size.gx_rectangle_top -= yoff;
|
|
info->size.gx_rectangle_right -= xoff;
|
|
info->size.gx_rectangle_bottom -= yoff;
|
|
|
|
widget_factory::MoveWidget(info, info->size);
|
|
}
|
|
|
|
if (info)
|
|
{
|
|
if (parent == (GX_WIDGET *) get_root_window())
|
|
{
|
|
project->AddWidgetToFolder(selected_folder, info);
|
|
}
|
|
else
|
|
{
|
|
project->AddWidgetToParent(selected, info);
|
|
}
|
|
UndoManager()->AddEntry(UNDO_TYPE_INSERT_WIDGET, info);
|
|
|
|
BOOL update_size = FALSE;
|
|
switch(parent->gx_widget_type)
|
|
{
|
|
case GX_TYPE_VERTICAL_LIST:
|
|
case GX_TYPE_POPUP_LIST:
|
|
gx_vertical_list_children_position((GX_VERTICAL_LIST *) parent);
|
|
update_size = TRUE;
|
|
break;
|
|
|
|
case GX_TYPE_HORIZONTAL_LIST:
|
|
gx_horizontal_list_children_position((GX_HORIZONTAL_LIST *) parent);
|
|
update_size = TRUE;
|
|
break;
|
|
|
|
case GX_TYPE_ACCORDION_MENU:
|
|
case GX_TYPE_TREE_VIEW:
|
|
case GX_TYPE_MENU:
|
|
GetProjectView()->CheckParentRefresh(parent);
|
|
update_size = TRUE;
|
|
break;
|
|
|
|
case GX_TYPE_GENERIC_SCROLL_WHEEL:
|
|
gx_generic_scroll_wheel_children_position((GX_GENERIC_SCROLL_WHEEL*)parent);
|
|
update_size = TRUE;
|
|
break;
|
|
|
|
default:
|
|
SelectWidget(info, TRUE, FALSE);
|
|
break;
|
|
}
|
|
|
|
if (update_size)
|
|
{
|
|
memcpy_s(&info->size, sizeof(info->size), &info->widget->gx_widget_size, sizeof(GX_RECTANGLE));
|
|
GetPropsWin()->WidgetWasModified(info);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg("Internal error: Service provider is not available");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnAddTemplate(widget_info *base)
|
|
{
|
|
GX_WIDGET *parent = NULL;
|
|
folder_info *selected_folder = NULL;
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (!project)
|
|
{
|
|
return;
|
|
}
|
|
|
|
widget_info *selected = GetSingleSelect();
|
|
|
|
if (selected)
|
|
{
|
|
if (selected ->basetype == GX_TYPE_DROP_LIST)
|
|
{
|
|
ErrorMsg("Child widgets must be added to the drop-list popup using the gx_drop_list_popup_get API");
|
|
return;
|
|
}
|
|
if (base->basetype == GX_TYPE_HORIZONTAL_SCROLL ||
|
|
base->basetype == GX_TYPE_VERTICAL_SCROLL)
|
|
{
|
|
if (selected->basetype < GX_TYPE_WINDOW)
|
|
{
|
|
ErrorMsg("Scroll bars can only be added to Window parents");
|
|
return;
|
|
}
|
|
}
|
|
parent = selected->widget;
|
|
}
|
|
else
|
|
{
|
|
if (GetProjectView()->IsFolderSelected())
|
|
{
|
|
selected_folder = GetProjectView()->GetSelectedFolder();
|
|
if (!selected_folder)
|
|
{
|
|
return;
|
|
}
|
|
parent = (GX_WIDGET *) get_root_window();
|
|
}
|
|
|
|
}
|
|
|
|
if (!parent)
|
|
{
|
|
return;
|
|
}
|
|
template_service_provider *provider = (template_service_provider *) widget_factory::GetServiceProvider(GX_TYPE_TEMPLATE);
|
|
|
|
if (provider)
|
|
{
|
|
widget_info *info = provider->CreateNewInstance(parent, base);
|
|
|
|
if (info)
|
|
{
|
|
if (parent == (GX_WIDGET *) get_root_window())
|
|
{
|
|
project->AddWidgetToFolder(selected_folder, info);
|
|
}
|
|
else
|
|
{
|
|
project->AddWidgetToParent(selected, info);
|
|
}
|
|
UndoManager()->AddEntry(UNDO_TYPE_INSERT_WIDGET, info);
|
|
|
|
switch(parent->gx_widget_type)
|
|
{
|
|
case GX_TYPE_VERTICAL_LIST:
|
|
case GX_TYPE_POPUP_LIST:
|
|
gx_vertical_list_children_position((GX_VERTICAL_LIST *) parent);
|
|
break;
|
|
|
|
case GX_TYPE_HORIZONTAL_LIST:
|
|
gx_horizontal_list_children_position((GX_HORIZONTAL_LIST *) parent);
|
|
break;
|
|
|
|
case GX_TYPE_ACCORDION_MENU:
|
|
case GX_TYPE_TREE_VIEW:
|
|
GetProjectView()->CheckParentRefresh(parent);
|
|
break;
|
|
|
|
default:
|
|
SelectWidget(info, TRUE, FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg("Internal error: Service provider not available");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::TestDropItem(resource_item *item,
|
|
CPoint InPoint, BOOL shifted)
|
|
{
|
|
int display;
|
|
GX_POINT point;
|
|
GX_WIDGET *root = (GX_WIDGET *) get_root_window();
|
|
|
|
ScreenToClient(&InPoint);
|
|
|
|
int scale = GetZoomScale();
|
|
|
|
point.gx_point_x = (GX_VALUE)(InPoint.x * 100 / scale);
|
|
point.gx_point_y = (GX_VALUE)(InPoint.y * 100 / scale);
|
|
widget_info *info;
|
|
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (!project)
|
|
{
|
|
return;
|
|
}
|
|
int DisplayIndex = GetProjectView()->GetActiveDisplay();
|
|
|
|
GX_WIDGET *target = _gx_system_top_widget_find(root, point, 0);
|
|
|
|
if (!target || target == root)
|
|
{
|
|
return;
|
|
}
|
|
info = project->FindWidgetInfo(target);
|
|
widget_service_provider *provider = widget_factory::GetServiceProvider(target->gx_widget_type);
|
|
|
|
if (!info || !provider)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (info->basetype == GX_TYPE_TEMPLATE)
|
|
{
|
|
// cannot change properties of item based on template
|
|
return;
|
|
}
|
|
|
|
int type = RES_TYPE_STRING;
|
|
|
|
if (item->mpRes)
|
|
{
|
|
type = item->mpRes->type;
|
|
}
|
|
|
|
switch(type)
|
|
{
|
|
case RES_TYPE_FONT:
|
|
UndoManager()->AddEntry(UNDO_TYPE_FONT, info, 0);
|
|
provider->AssignFont(info, 0, project->GetResourceId(DisplayIndex, item->mpRes));
|
|
break;
|
|
|
|
case RES_TYPE_COLOR:
|
|
if (shifted)
|
|
{
|
|
UndoManager()->AddEntry(UNDO_TYPE_COLOR, info, 1);
|
|
provider->AssignColor(info, 1, project->GetResourceId(DisplayIndex, item->mpRes));
|
|
}
|
|
else
|
|
{
|
|
UndoManager()->AddEntry(UNDO_TYPE_COLOR, info, 0);
|
|
provider->AssignColor(info, 0, project->GetResourceId(DisplayIndex, item->mpRes));
|
|
}
|
|
break;
|
|
|
|
case RES_TYPE_PIXELMAP:
|
|
if (shifted)
|
|
{
|
|
UndoManager()->AddEntry(UNDO_TYPE_PIXELMAP, info, 1);
|
|
provider->AssignPixelmap(info, 1, project->GetResourceId(DisplayIndex, item->mpRes));
|
|
}
|
|
else
|
|
{
|
|
UndoManager()->AddEntry(UNDO_TYPE_PIXELMAP, info, 0);
|
|
provider->AssignPixelmap(info, 0, project->GetResourceId(DisplayIndex, item->mpRes));
|
|
}
|
|
break;
|
|
|
|
case RES_TYPE_STRING:
|
|
display = GetProjectView()->GetActiveDisplay();
|
|
if (display >= 0)
|
|
{
|
|
UndoManager()->AddEntry(UNDO_TYPE_STRING, info, 0);
|
|
string_table *pt = project->mDisplays[display].stable;
|
|
provider->AssignText(info, 0, pt->GetResourceId(item->GetStringId()));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
// update the properties window
|
|
GetPropsWin()->WidgetWasModified(info);
|
|
project->SetModified();
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnAlignLeft()
|
|
{
|
|
int index;
|
|
int left = 65535;
|
|
GX_RECTANGLE newsize;
|
|
|
|
if (!SelectedWidgetsCanBeMoved())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (SelectedWidgets.GetCount() > 1)
|
|
{
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
if (SelectedWidgets[index].info->widget->gx_widget_size.gx_rectangle_left < left)
|
|
{
|
|
left = SelectedWidgets[index].info->widget->gx_widget_size.gx_rectangle_left;
|
|
}
|
|
}
|
|
UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
|
|
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
GX_WIDGET *selected = SelectedWidgets[index].info->widget;
|
|
|
|
if (selected->gx_widget_size.gx_rectangle_left != left)
|
|
{
|
|
newsize = selected->gx_widget_size;
|
|
gx_utility_rectangle_shift(&newsize, left - newsize.gx_rectangle_left, 0);
|
|
widget_factory::MoveWidget(SelectedWidgets[index].info, newsize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnAlignTop()
|
|
{
|
|
int index;
|
|
int top = 65535;
|
|
GX_RECTANGLE newsize;
|
|
GX_WIDGET *selected;
|
|
|
|
if (!SelectedWidgetsCanBeMoved())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (SelectedWidgets.GetCount() > 1)
|
|
{
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info->widget;
|
|
|
|
if (selected->gx_widget_size.gx_rectangle_top < top)
|
|
{
|
|
top = selected->gx_widget_size.gx_rectangle_top;
|
|
}
|
|
}
|
|
UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
|
|
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info->widget;
|
|
if (selected->gx_widget_size.gx_rectangle_top != top)
|
|
{
|
|
newsize = selected->gx_widget_size;
|
|
gx_utility_rectangle_shift(&newsize, 0, top - newsize.gx_rectangle_top);
|
|
widget_factory::MoveWidget(SelectedWidgets[index].info, newsize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnAlignRight()
|
|
{
|
|
int index;
|
|
int right = -65535;
|
|
GX_RECTANGLE newsize;
|
|
GX_WIDGET *selected;
|
|
|
|
if (!SelectedWidgetsCanBeMoved())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (SelectedWidgets.GetCount() > 1)
|
|
{
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info->widget;
|
|
|
|
if (selected->gx_widget_size.gx_rectangle_right > right)
|
|
{
|
|
right = selected->gx_widget_size.gx_rectangle_right;
|
|
}
|
|
}
|
|
UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
|
|
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info->widget;
|
|
if (selected->gx_widget_size.gx_rectangle_right != right)
|
|
{
|
|
newsize = selected->gx_widget_size;
|
|
gx_utility_rectangle_shift(&newsize, right - newsize.gx_rectangle_right, 0);
|
|
widget_factory::MoveWidget(SelectedWidgets[index].info, newsize);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnAlignBottom()
|
|
{
|
|
int index;
|
|
int bottom = -65535;
|
|
GX_RECTANGLE newsize;
|
|
GX_WIDGET *selected;
|
|
|
|
if (!SelectedWidgetsCanBeMoved())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (SelectedWidgets.GetCount() > 1)
|
|
{
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info->widget;
|
|
|
|
if (selected->gx_widget_size.gx_rectangle_bottom > bottom)
|
|
{
|
|
bottom = selected->gx_widget_size.gx_rectangle_bottom;
|
|
}
|
|
}
|
|
UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
|
|
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info->widget;
|
|
if (selected->gx_widget_size.gx_rectangle_bottom != bottom)
|
|
{
|
|
newsize = selected->gx_widget_size;
|
|
gx_utility_rectangle_shift(&newsize, 0, bottom - newsize.gx_rectangle_bottom);
|
|
widget_factory::MoveWidget(SelectedWidgets[index].info, newsize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnHSpaceEqually()
|
|
{
|
|
GX_WIDGET *selected;
|
|
GX_RECTANGLE size;
|
|
int index;
|
|
int used_space = 0;
|
|
int left = 65535;
|
|
int right = -65535;
|
|
int total_space = 0;
|
|
int inner_space = 0;
|
|
int left_most_index;
|
|
int right_neighbor_index;
|
|
|
|
if (!SelectedWidgetsCanBeMoved())
|
|
{
|
|
return;
|
|
}
|
|
|
|
int count = SelectedWidgets.GetCount();
|
|
|
|
if (count > 2)
|
|
{
|
|
for (index = 0; index < count; index++)
|
|
{
|
|
selected = SelectedWidgets[index].info->widget;
|
|
if (selected->gx_widget_size.gx_rectangle_left < left)
|
|
{
|
|
left = selected->gx_widget_size.gx_rectangle_left;
|
|
left_most_index = index;
|
|
}
|
|
if (selected->gx_widget_size.gx_rectangle_right > right)
|
|
{
|
|
right = selected->gx_widget_size.gx_rectangle_right;
|
|
}
|
|
used_space += (selected->gx_widget_size.gx_rectangle_right - selected->gx_widget_size.gx_rectangle_left) + 1;
|
|
}
|
|
|
|
total_space = right - left + 1;
|
|
inner_space = ((total_space - used_space) + count) / (count - 1);
|
|
|
|
// OK, starting with the left-most index, find the widget that is nearest moving right. Use the left
|
|
// edge to determine "nearest", if widgets are overlapped and wider than each other then some strange
|
|
// things might happen, nothing we can do about that.
|
|
|
|
right_neighbor_index = FindNearestSelected(left_most_index, FALSE);
|
|
UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
|
|
|
|
while (right_neighbor_index >= 0)
|
|
{
|
|
selected = SelectedWidgets[right_neighbor_index].info->widget;
|
|
size = selected->gx_widget_size;
|
|
left = SelectedWidgets[left_most_index].info->widget->gx_widget_size.gx_rectangle_right + inner_space;
|
|
|
|
if (size.gx_rectangle_left != left)
|
|
{
|
|
gx_utility_rectangle_shift(&size, left - size.gx_rectangle_left, 0);
|
|
widget_factory::MoveWidget(SelectedWidgets[right_neighbor_index].info, size);
|
|
}
|
|
left_most_index = right_neighbor_index;
|
|
right_neighbor_index = FindNearestSelected(left_most_index, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnVSpaceEqually()
|
|
{
|
|
GX_WIDGET *selected;
|
|
GX_RECTANGLE size;
|
|
int index;
|
|
int used_space = 0;
|
|
int top = 65535;
|
|
int bottom = -65535;
|
|
int total_space = 0;
|
|
int inner_space = 0;
|
|
int top_most_index;
|
|
int below_neighbor_index;
|
|
|
|
if (!SelectedWidgetsCanBeMoved())
|
|
{
|
|
return;
|
|
}
|
|
|
|
int count = SelectedWidgets.GetCount();
|
|
|
|
if (count > 2)
|
|
{
|
|
for (index = 0; index < count; index++)
|
|
{
|
|
selected = SelectedWidgets[index].info->widget;
|
|
if (selected->gx_widget_size.gx_rectangle_top < top)
|
|
{
|
|
top = selected->gx_widget_size.gx_rectangle_top;
|
|
top_most_index = index;
|
|
}
|
|
if (selected->gx_widget_size.gx_rectangle_bottom > bottom)
|
|
{
|
|
bottom = selected->gx_widget_size.gx_rectangle_bottom;
|
|
}
|
|
used_space += (selected->gx_widget_size.gx_rectangle_bottom - selected->gx_widget_size.gx_rectangle_top) + 1;
|
|
}
|
|
|
|
total_space = bottom - top + 1;
|
|
inner_space = ((total_space - used_space) + count) / (count - 1);
|
|
|
|
// OK, starting with the left-most index, find the widget that is nearest moving right. Use the left
|
|
// edge to determine "nearest", if widgets are overlapped and wider than each other then some strange
|
|
// things might happen, nothing we can do about that.
|
|
|
|
below_neighbor_index = FindNearestSelected(top_most_index, TRUE);
|
|
UndoManager()->AddEntry(UNDO_TYPE_POSITION, SelectedWidgets);
|
|
|
|
while (below_neighbor_index >= 0)
|
|
{
|
|
selected = SelectedWidgets[below_neighbor_index].info->widget;
|
|
size = selected->gx_widget_size;
|
|
top = SelectedWidgets[top_most_index].info->widget->gx_widget_size.gx_rectangle_bottom + inner_space;
|
|
|
|
if (size.gx_rectangle_top != top)
|
|
{
|
|
gx_utility_rectangle_shift(&size, 0, top - size.gx_rectangle_top);
|
|
widget_factory::MoveWidget(SelectedWidgets[below_neighbor_index].info, size);
|
|
}
|
|
top_most_index = below_neighbor_index;
|
|
below_neighbor_index = FindNearestSelected(top_most_index, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnMakeEqualWidth()
|
|
{
|
|
int index;
|
|
int widest = 0;
|
|
int width;
|
|
GX_RECTANGLE newsize;
|
|
widget_info *selected;
|
|
|
|
studiox_project *project = GetOpenProject();
|
|
if (project && project->IsWidgetPositionLocked())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (SelectedWidgets.GetCount() > 1)
|
|
{
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info;
|
|
|
|
width = selected->size.gx_rectangle_right - selected->size.gx_rectangle_left + 1;
|
|
if (width > widest)
|
|
{
|
|
widest = width;
|
|
}
|
|
}
|
|
UndoManager()->AddEntry(UNDO_TYPE_SIZE, SelectedWidgets);
|
|
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info;
|
|
width = selected->size.gx_rectangle_right - selected->size.gx_rectangle_left + 1;
|
|
|
|
if (width != widest)
|
|
{
|
|
newsize = selected->size;
|
|
newsize.gx_rectangle_right = newsize.gx_rectangle_left + widest - 1;
|
|
|
|
if (selected->basetype == GX_TYPE_RADIAL_PROGRESS_BAR)
|
|
{
|
|
newsize.gx_rectangle_bottom = newsize.gx_rectangle_top + widest - 1;
|
|
}
|
|
|
|
widget_factory::MoveWidget(selected, newsize);
|
|
WidgetWasMoved(selected);
|
|
}
|
|
}
|
|
project_view::CheckParentRefresh(SelectedWidgets[0].info->widget->gx_widget_parent);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnMakeEqualHeight()
|
|
{
|
|
int index;
|
|
int tallest = 0;
|
|
int height;
|
|
GX_RECTANGLE newsize;
|
|
widget_info *selected;
|
|
|
|
studiox_project *project = GetOpenProject();
|
|
if (project && project->IsWidgetPositionLocked())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (SelectedWidgets.GetCount() > 1)
|
|
{
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info;
|
|
|
|
height = selected->size.gx_rectangle_bottom - selected->size.gx_rectangle_top + 1;
|
|
if (height > tallest)
|
|
{
|
|
tallest = height;
|
|
}
|
|
}
|
|
UndoManager()->AddEntry(UNDO_TYPE_SIZE, SelectedWidgets);
|
|
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info;
|
|
height = selected->size.gx_rectangle_bottom - selected->size.gx_rectangle_top + 1;
|
|
|
|
if (height != tallest)
|
|
{
|
|
newsize = selected->size;
|
|
newsize.gx_rectangle_bottom = newsize.gx_rectangle_top + tallest - 1;
|
|
|
|
if (selected->basetype == GX_TYPE_RADIAL_PROGRESS_BAR)
|
|
{
|
|
newsize.gx_rectangle_right = newsize.gx_rectangle_left + tallest - 1;
|
|
}
|
|
|
|
widget_factory::MoveWidget(selected, newsize);
|
|
WidgetWasMoved(selected);
|
|
}
|
|
}
|
|
project_view::CheckParentRefresh(SelectedWidgets[0].info->widget->gx_widget_parent);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::OnAutosize()
|
|
{
|
|
int index;
|
|
widget_info *selected;
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (project && project->IsWidgetPositionLocked())
|
|
{
|
|
return;
|
|
}
|
|
|
|
UndoManager()->AddEntry(UNDO_TYPE_SIZE, SelectedWidgets);
|
|
|
|
for (index = 0; index < SelectedWidgets.GetCount(); index++)
|
|
{
|
|
selected = SelectedWidgets[index].info;
|
|
|
|
if (selected && project)
|
|
{
|
|
widget_service_provider *provider = widget_factory::GetServiceProvider(selected->basetype);
|
|
|
|
if (provider)
|
|
{
|
|
provider->Autosize(selected);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::ZoomIn(int scale)
|
|
{
|
|
SetZoomScale(scale);
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (!project)
|
|
{
|
|
return;
|
|
}
|
|
display_info *info = &project->mDisplays[m_display_index];
|
|
|
|
int width;
|
|
int height;
|
|
|
|
if (project->mDisplays[m_display_index].rotation_angle == GX_SCREEN_ROTATION_CW ||
|
|
project->mDisplays[m_display_index].rotation_angle == GX_SCREEN_ROTATION_CCW)
|
|
{
|
|
width = (info->yres - 1) * scale / 100;
|
|
height = (info->xres - 1) * scale / 100;
|
|
}
|
|
else
|
|
{
|
|
width = (info->xres - 1) * scale / 100;
|
|
height = (info->yres - 1) * scale / 100;
|
|
}
|
|
|
|
// resize target screen
|
|
SetWindowPos(NULL, 0, 0, width, height, SWP_NOMOVE);
|
|
|
|
target_frame *frame = (target_frame *)GetParent();
|
|
frame->UpdateScrollSize();
|
|
frame->Invalidate();
|
|
|
|
UpdateWindowPos();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
int target_screen::FindNearestSelected(int start_index, BOOL vertical)
|
|
{
|
|
int count = SelectedWidgets.GetCount();
|
|
int test_index;
|
|
int test_dist;
|
|
int start_edge;
|
|
int least_index = -1;
|
|
int least_dist = 65535;
|
|
|
|
if (start_index >= 0 && start_index < count)
|
|
{
|
|
if (vertical)
|
|
{
|
|
start_edge = SelectedWidgets[start_index].info->size.gx_rectangle_top;
|
|
}
|
|
else
|
|
{
|
|
start_edge = SelectedWidgets[start_index].info->size.gx_rectangle_left;
|
|
}
|
|
|
|
for (test_index = 0; test_index < count; test_index++)
|
|
{
|
|
if (test_index != start_index)
|
|
{
|
|
if (vertical)
|
|
{
|
|
test_dist = SelectedWidgets[test_index].info->size.gx_rectangle_top - start_edge;
|
|
}
|
|
else
|
|
{
|
|
test_dist = SelectedWidgets[test_index].info->size.gx_rectangle_left - start_edge;
|
|
}
|
|
|
|
if (test_dist > 0 && test_dist < least_dist)
|
|
{
|
|
least_dist = test_dist;
|
|
least_index = test_index;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return least_index;
|
|
}
|
|
|
|
#define QUOTIENT 0x04c11db7
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::crc32_init(void)
|
|
{
|
|
int i, j;
|
|
|
|
unsigned int crc;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
crc = i << 24;
|
|
for (j = 0; j < 8; j++)
|
|
{
|
|
if (crc & 0x80000000)
|
|
crc = (crc << 1) ^ QUOTIENT;
|
|
else
|
|
crc = crc << 1;
|
|
}
|
|
crc_table[i] = crc;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
unsigned int target_screen::calc_crc(unsigned char *data, int len)
|
|
{
|
|
unsigned int result;
|
|
int i;
|
|
|
|
crc32_init();
|
|
|
|
result = *data++ << 24;
|
|
result |= *data++ << 16;
|
|
result |= *data++ << 8;
|
|
result |= *data++;
|
|
result = ~ result;
|
|
len -=4;
|
|
|
|
for (i=0; i<len; i++)
|
|
{
|
|
result = (result << 8 | *data++) ^ crc_table[result >> 24];
|
|
}
|
|
|
|
return ~result;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::canvas_to_bitmap(CString filename, GX_CANVAS *canvas)
|
|
{
|
|
CFile *p_file = new CFile();
|
|
|
|
if (!p_file->Open(filename, CFile::modeCreate | CFile::modeWrite))
|
|
{
|
|
CString msg;
|
|
msg.Format(_T("Could not open bmp file:\n%s\nPlease check file path."), filename);
|
|
ErrorMsg(msg);
|
|
delete p_file;
|
|
return;
|
|
}
|
|
|
|
BITMAPFILEHEADER file_header;
|
|
GX_BMP_INFO info;
|
|
|
|
GX_DISPLAY *display;
|
|
GX_WIN32_DISPLAY_DRIVER_DATA *driver_instance;
|
|
|
|
display = canvas->gx_canvas_display;
|
|
driver_instance = (GX_WIN32_DISPLAY_DRIVER_DATA *)(display->gx_display_driver_data);
|
|
info = driver_instance->win32_driver_bmpinfo;
|
|
info.gx_bmp_header.biHeight *= -1;
|
|
|
|
memset(&file_header, 0, sizeof(BITMAPFILEHEADER));
|
|
|
|
file_header.bfType = 'MB';
|
|
file_header.bfSize = canvas->gx_canvas_memory_size + sizeof(BITMAPFILEHEADER) + sizeof(GX_BMP_INFO);
|
|
file_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(GX_BMP_INFO);
|
|
p_file->Write(&file_header, sizeof(BITMAPFILEHEADER));
|
|
p_file->Write(&info, sizeof(GX_BMP_INFO));
|
|
p_file->Write(canvas->gx_canvas_memory, canvas->gx_canvas_memory_size);
|
|
|
|
p_file->Close();
|
|
delete p_file;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void target_screen::target_screen_to_bitmap(CString filename, GX_CANVAS *canvas)
|
|
{
|
|
LPBYTE lpBits; // memory pointer
|
|
CDC *dc = GetDC();
|
|
HDC hDC = dc->GetSafeHdc();
|
|
CRect rect;
|
|
|
|
GetClientRect(&rect);
|
|
|
|
HDC hdcMem = CreateCompatibleDC(hDC);
|
|
HBITMAP hbmMem = CreateCompatibleBitmap(hDC, rect.Width(), rect.Height());
|
|
|
|
SelectObject(hdcMem, hbmMem);
|
|
|
|
BitBlt(hdcMem, 0, 0, rect.Width(), rect.Height(), hDC, 0, 0, SRCCOPY);
|
|
|
|
GX_BMP_INFO info;
|
|
GX_DISPLAY *display;
|
|
GX_WIN32_DISPLAY_DRIVER_DATA *driver_instance;
|
|
|
|
display = canvas->gx_canvas_display;
|
|
driver_instance = (GX_WIN32_DISPLAY_DRIVER_DATA *)(display->gx_display_driver_data);
|
|
|
|
BITMAP bitmap;
|
|
GetObject(hbmMem, sizeof(BITMAP), &bitmap);
|
|
|
|
info = driver_instance->win32_driver_bmpinfo;
|
|
info.gx_bmp_header.biWidth = bitmap.bmWidth;
|
|
info.gx_bmp_header.biHeight = -bitmap.bmHeight;
|
|
info.gx_bmp_header.biSizeImage = ((bitmap.bmWidth * info.gx_bmp_header.biBitCount + 31) / 32) * 4 * bitmap.bmHeight;
|
|
|
|
lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, info.gx_bmp_header.biSizeImage);
|
|
|
|
// Removed by Guo. This assert cannot be build by release.
|
|
//assert(lpBits);
|
|
|
|
// Retrieve the color table (RGBQUAD array) and the bits
|
|
// (array of palette indices) from the DIB.
|
|
GetDIBits(hdcMem, hbmMem, 0, info.gx_bmp_header.biHeight, lpBits, (LPBITMAPINFO)&info, DIB_RGB_COLORS);
|
|
|
|
// Create the .BMP file.
|
|
CFile *p_file = new CFile();
|
|
|
|
if (!p_file->Open(filename, CFile::modeCreate | CFile::modeWrite))
|
|
{
|
|
CString msg;
|
|
msg.Format(_T("Could not open bmp file:\n%s\nPlease check file path."), filename);
|
|
ErrorMsg(msg);
|
|
delete p_file;
|
|
return;
|
|
}
|
|
|
|
BITMAPFILEHEADER file_header;
|
|
memset(&file_header, 0, sizeof(BITMAPFILEHEADER));
|
|
|
|
file_header.bfType = 'MB';
|
|
file_header.bfSize = info.gx_bmp_header.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(GX_BMP_INFO);
|
|
file_header.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(GX_BMP_INFO);
|
|
|
|
p_file->Write(&file_header, sizeof(BITMAPFILEHEADER));
|
|
p_file->Write(&info, sizeof(GX_BMP_INFO));
|
|
p_file->Write(lpBits, info.gx_bmp_header.biSizeImage);
|
|
|
|
p_file->Close();
|
|
delete p_file;
|
|
|
|
DeleteDC(hdcMem);
|
|
DeleteObject(hbmMem);
|
|
GlobalFree((HGLOBAL)lpBits);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
LRESULT target_screen::OnTestMessage(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
GX_WINDOW_ROOT *root;
|
|
GX_CANVAS *canvas;
|
|
LRESULT result = 0;
|
|
int xshift, yshift;
|
|
GX_WIDGET *top;
|
|
widget_info *base = NULL;
|
|
studiox_project *project;
|
|
CStringArray param;
|
|
int x, y, display;
|
|
|
|
switch(wParam)
|
|
{
|
|
case TEST_GENERATE_CHECKSUM:
|
|
//SelectWidget(NULL, FALSE, FALSE);
|
|
if(GetOpenProject())
|
|
{
|
|
DeSelect();
|
|
GetProjectView()->DeSelect();
|
|
|
|
_gx_system_canvas_refresh();
|
|
root = get_root_window();
|
|
canvas = root->gx_window_root_canvas;
|
|
result = calc_crc((unsigned char *)canvas->gx_canvas_memory, canvas->gx_canvas_memory_size);
|
|
}
|
|
break;
|
|
|
|
case TEST_GENERATE_SCREENSHOT:
|
|
if (GetOpenProject())
|
|
{
|
|
root = get_root_window();
|
|
canvas_to_bitmap(GetTestingParam(0), root->gx_window_root_canvas);
|
|
}
|
|
break;
|
|
|
|
case TEST_DESELECT:
|
|
DeSelect();
|
|
GetProjectView()->DeSelect();
|
|
break;
|
|
|
|
case TEST_DIRTY_ROOT_WINDOW:
|
|
root = get_root_window();
|
|
gx_system_dirty_mark(root);
|
|
break;
|
|
|
|
case TEST_MOVE_WINDOW:
|
|
project = GetOpenProject();
|
|
xshift = yshift = lParam;
|
|
root = get_root_window();
|
|
top = root->gx_widget_first_child;
|
|
SelectWidget(project->FindWidgetInfo(top), FALSE, FALSE);
|
|
ShiftSelectedWidgets(xshift, yshift);
|
|
break;
|
|
|
|
case TEST_MOVE_SELECTED:
|
|
xshift = yshift = lParam;
|
|
ShiftSelectedWidgets(xshift, yshift);
|
|
break;
|
|
|
|
case TEST_ADD_WIDGET:
|
|
OnAddWidget(lParam);
|
|
break;
|
|
|
|
case TEST_ADD_TEMPLATE:
|
|
project = GetOpenProject();
|
|
if (project)
|
|
{
|
|
SplitString(GetTestingParam(0), ',', ¶m);
|
|
display = _tstoi(param.GetAt(1));
|
|
if (display >= 0)
|
|
{
|
|
base = project->FindWidgetInfo(project->mDisplays[display].GetFirstChildFolder(), (CString)param.GetAt(0), FALSE);
|
|
}
|
|
if (base)
|
|
{
|
|
OnAddTemplate(base);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TEST_ZOOM_IN:
|
|
ZoomIn(lParam);
|
|
break;
|
|
|
|
case TEST_LBUTTON_DOWN:
|
|
SplitString(GetTestingParam(0), ',', ¶m);
|
|
x = _tstoi(param.GetAt(0));
|
|
y = _tstoi(param.GetAt(1));
|
|
SendMessage(WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
|
|
break;
|
|
|
|
case TEST_LBUTTON_UP:
|
|
SplitString(GetTestingParam(0), ',', ¶m);
|
|
x = _tstoi(param.GetAt(0));
|
|
y = _tstoi(param.GetAt(1));
|
|
SendMessage(WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x, y));
|
|
break;
|
|
|
|
case TEST_MOUSEMOVE:
|
|
case TEST_MOUSEMOVE_POST:
|
|
if (wParam == TEST_MOUSEMOVE_POST)
|
|
{
|
|
SplitString(GetTestingParam(1), ',', ¶m);
|
|
}
|
|
else
|
|
{
|
|
SplitString(GetTestingParam(0), ',', ¶m);
|
|
}
|
|
x = _tstoi(param.GetAt(0));
|
|
y = _tstoi(param.GetAt(1));
|
|
SendMessage(WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(x, y));
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return result;
|
|
}
|