mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
1112 lines
29 KiB
C
1112 lines
29 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*
|
|
* $XConsortium: abobj_resize.c /main/4 1996/10/29 16:43:13 mustafa $
|
|
*
|
|
* @(#)abobj_resize.c 1.28 15 Feb 1994 cde_app_builder/src/ab
|
|
*
|
|
* RESTRICTED CONFIDENTIAL INFORMATION:
|
|
*
|
|
* The information in this document is subject to special
|
|
* restrictions in a confidential disclosure agreement between
|
|
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
|
|
* document outside HP, IBM, Sun, USL, SCO, or Univel without
|
|
* Sun's specific written approval. This document and all copies
|
|
* and derivative works thereof must be returned or destroyed at
|
|
* Sun's request.
|
|
*
|
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
*
|
|
* abobj_resize.c - Implements resizing of UI objects
|
|
*
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
#include <stdio.h>
|
|
#include <X11/cursorfont.h>
|
|
#include <Xm/ScrolledW.h>
|
|
#include "dtb_utils.h"
|
|
#include <ab_private/objxm.h>
|
|
#include <ab_private/prop.h>
|
|
#include <ab_private/x_util.h>
|
|
#include <ab_private/ui_util.h>
|
|
#include <ab_private/abobj_edit.h>
|
|
#include "abobjP.h"
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Private Function Declarations **
|
|
** **
|
|
**************************************************************************/
|
|
static void make_rect(
|
|
XRectangle *new_r,
|
|
XRectangle *r,
|
|
int x,
|
|
int y,
|
|
RESIZE_DIR dir
|
|
);
|
|
|
|
static void
|
|
make_rect_in_rect(
|
|
XRectangle *pr,
|
|
XRectangle *new_r,
|
|
XRectangle *r,
|
|
int x,
|
|
int y,
|
|
RESIZE_DIR dir
|
|
);
|
|
|
|
static void undo_resize(
|
|
ABUndoRec undo_rec
|
|
);
|
|
void resize_in_pixels(
|
|
ABObj obj,
|
|
int width,
|
|
int height,
|
|
int border_w
|
|
);
|
|
|
|
static void subtract_attached_label(
|
|
ABObj obj,
|
|
XRectangle *r_rect
|
|
);
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Private Data **
|
|
** **
|
|
**************************************************************************/
|
|
static Boolean first_move = TRUE;
|
|
static XRectangle resize_rect;
|
|
static ABObj xy_obj = NULL;
|
|
static Widget xy_widget = NULL;
|
|
static int border_w = 0;
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Function Definitions **
|
|
** **
|
|
**************************************************************************/
|
|
|
|
/*
|
|
* Return resize-direction corresponding to cursor x,y position
|
|
*/
|
|
RESIZE_DIR
|
|
abobjP_find_resize_direction (
|
|
ABObj obj,
|
|
Widget widget,
|
|
XEvent *event
|
|
)
|
|
{
|
|
ABObj rootObj;
|
|
XRectangle w_rect;
|
|
XRectangle temp;
|
|
int half_handle;
|
|
int half_width;
|
|
int half_height;
|
|
int x, y;
|
|
int orig_x, orig_y;
|
|
int grabbox_size;
|
|
|
|
if (event->type == MotionNotify)
|
|
{
|
|
orig_x = x = ((XMotionEvent*)event)->x;
|
|
orig_y = y = ((XMotionEvent*)event)->y;
|
|
}
|
|
else if (event->type == ButtonPress)
|
|
{
|
|
orig_x = x = ((XButtonEvent*)event)->x;
|
|
orig_y = y = ((XButtonEvent*)event)->y;
|
|
}
|
|
else
|
|
return NONE;
|
|
|
|
if (obj_is_item(obj))
|
|
obj = obj_get_parent(obj);
|
|
|
|
rootObj = obj_get_root(obj);
|
|
|
|
rect_zero_out(&w_rect);
|
|
|
|
if ((obj_is_drawing_area(obj) || obj_is_text_pane(obj)) &&
|
|
(obj_has_hscrollbar(obj) || obj_has_vscrollbar(obj)) )
|
|
{
|
|
ABObj swobj = objxm_comp_get_subobj(obj, AB_CFG_SIZE_OBJ);
|
|
Widget cwidget;
|
|
|
|
XtVaGetValues((Widget)swobj->ui_handle,
|
|
XmNclipWindow, &cwidget,
|
|
NULL);
|
|
|
|
if (cwidget)
|
|
x_get_widget_rect(cwidget, &w_rect);
|
|
}
|
|
else if (rootObj != obj)
|
|
{
|
|
Window win;
|
|
|
|
XTranslateCoordinates(XtDisplay(widget), XtWindow(widget),
|
|
XtWindow(objxm_get_widget(rootObj)), orig_x , orig_y, &x, &y,
|
|
&win);
|
|
|
|
widget = objxm_get_widget(rootObj);
|
|
}
|
|
|
|
if (w_rect.width == 0 || w_rect.height == 0)
|
|
x_get_widget_rect(widget, &w_rect);
|
|
|
|
/*
|
|
if (obj_is_control(obj))
|
|
grabbox_size = (AB_selected_rect_size / 2) + 1;
|
|
else
|
|
*/
|
|
grabbox_size = AB_selected_rect_size;
|
|
|
|
/* Readjust coordinates to remove offset within the parent window.
|
|
*/
|
|
w_rect.x = 0;
|
|
w_rect.y = 0;
|
|
|
|
/* Exit if we are not near the border.
|
|
*/
|
|
temp = w_rect;
|
|
x_adjust_rect_margin(&temp, 0 - grabbox_size);
|
|
if (obj_is_control_panel(rootObj) && rect_includespoint (&temp, x, y))
|
|
return (NONE);
|
|
|
|
if (!abobj_is_directly_resizable(rootObj))
|
|
return (MOVE);
|
|
|
|
half_handle = grabbox_size/ 2 + 1;
|
|
half_width = w_rect.width / 2;
|
|
half_height = w_rect.height / 2;
|
|
|
|
temp.width = temp.height = grabbox_size + 2;
|
|
|
|
/********************************
|
|
* SOUTH_EAST
|
|
* Most common ?
|
|
*********************************/
|
|
temp.x = w_rect.width - grabbox_size;
|
|
temp.y = w_rect.height - grabbox_size;
|
|
|
|
if (rect_includespoint (&temp, x, y))
|
|
return (SOUTH_EAST);
|
|
|
|
/********************************
|
|
* SOUTH_WEST
|
|
*********************************/
|
|
temp.x = 0;
|
|
temp.y = w_rect.height - grabbox_size;
|
|
|
|
if (rect_includespoint (&temp, x, y))
|
|
return (SOUTH_WEST);
|
|
|
|
/********************************
|
|
* NORTH
|
|
*********************************/
|
|
temp.x = half_width - half_handle;
|
|
temp.y = 0;
|
|
|
|
if (rect_includespoint (&temp, x, y))
|
|
return (NORTH);
|
|
|
|
|
|
/********************************
|
|
* SOUTH
|
|
*********************************/
|
|
temp.x = half_width - half_handle;
|
|
temp.y = w_rect.height - grabbox_size;
|
|
|
|
if (rect_includespoint (&temp, x, y))
|
|
return (SOUTH);
|
|
|
|
/********************************
|
|
* EAST
|
|
*********************************/
|
|
temp.x = w_rect.width - grabbox_size;
|
|
temp.y = half_height - half_handle;
|
|
|
|
if (rect_includespoint (&temp, x, y))
|
|
return (EAST);
|
|
|
|
/********************************
|
|
* WEST
|
|
*********************************/
|
|
temp.x = 0;
|
|
temp.y = half_height - half_handle;
|
|
|
|
if (rect_includespoint (&temp, x, y))
|
|
return (WEST);
|
|
|
|
/********************************
|
|
* NORTH_EAST
|
|
*********************************/
|
|
temp.x = w_rect.width - grabbox_size;
|
|
temp.y = 0;
|
|
|
|
if (rect_includespoint (&temp, x, y))
|
|
return (NORTH_EAST);
|
|
|
|
/********************************
|
|
* NORTH_WEST
|
|
*********************************/
|
|
temp.x = 0;
|
|
temp.y = 0;
|
|
|
|
if (rect_includespoint (&temp, x, y))
|
|
return (NORTH_WEST);
|
|
|
|
/********************************
|
|
* Must be a move.
|
|
*********************************/
|
|
return (MOVE);
|
|
}
|
|
|
|
|
|
/*
|
|
* Return correct font cursor for given Resize-direction
|
|
*/
|
|
Cursor
|
|
abobjP_get_resize_cursor(
|
|
Widget w,
|
|
RESIZE_DIR dir
|
|
)
|
|
{
|
|
static Cursor resize_cursor[10] =
|
|
{ 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0 };
|
|
unsigned int shape;
|
|
|
|
if (!resize_cursor[dir])
|
|
{
|
|
if (dir == MOVE)
|
|
{
|
|
resize_cursor[MOVE] = x_create_stencil_cursor(w,
|
|
AB_mv_cursor_pixmap, AB_mv_cursor_width,
|
|
AB_mv_cursor_height, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
switch(dir)
|
|
{
|
|
case SOUTH_EAST:
|
|
shape = XC_bottom_right_corner;
|
|
break;
|
|
case SOUTH_WEST:
|
|
shape = XC_bottom_left_corner;
|
|
break;
|
|
case NORTH_WEST:
|
|
shape = XC_top_left_corner;
|
|
break;
|
|
case NORTH_EAST:
|
|
shape = XC_top_right_corner;
|
|
break;
|
|
case SOUTH:
|
|
shape = XC_bottom_side;
|
|
break;
|
|
case NORTH:
|
|
shape = XC_top_side;
|
|
break;
|
|
case EAST:
|
|
shape = XC_right_side;
|
|
break;
|
|
case WEST:
|
|
shape = XC_left_side;
|
|
break;
|
|
case NONE:
|
|
default:
|
|
return 0;
|
|
}
|
|
resize_cursor[dir] = XCreateFontCursor(XtDisplay(w), shape);
|
|
}
|
|
}
|
|
return(resize_cursor[dir]);
|
|
|
|
}
|
|
|
|
/*
|
|
* Draw rubberbanding outline for resizing action
|
|
*/
|
|
int
|
|
abobjP_resize_object_outline(
|
|
ABObj obj,
|
|
XEvent *event,
|
|
RESIZE_DIR dir
|
|
)
|
|
{
|
|
ABObj s_obj;
|
|
static Widget parent;
|
|
static Window rootwin;
|
|
static Display *dpy;
|
|
static XRectangle orig_r, r, p_rect;
|
|
static int last_x, last_y;
|
|
int x, y, x_tmp, y_tmp;
|
|
char buf[80];
|
|
|
|
if (event->type == MotionNotify)
|
|
{
|
|
x = ((XMotionEvent*)event)->x_root;
|
|
y = ((XMotionEvent*)event)->y_root;
|
|
}
|
|
else if (event->type == ButtonPress)
|
|
{
|
|
x = ((XButtonEvent*)event)->x_root;
|
|
y = ((XButtonEvent*)event)->y_root;
|
|
}
|
|
else
|
|
return -1;
|
|
|
|
if (first_move)
|
|
{
|
|
Window win;
|
|
int orig_x, orig_y;
|
|
int trans_x, trans_y;
|
|
|
|
if (obj_is_item(obj))
|
|
obj = obj_get_parent(obj);
|
|
|
|
obj = obj_get_root(obj);
|
|
xy_obj = objxm_comp_get_subobj(obj, AB_CFG_POSITION_OBJ);
|
|
xy_widget = (Widget)xy_obj->ui_handle;
|
|
|
|
if (xy_widget == NULL)
|
|
{
|
|
if (util_get_verbosity() > 0)
|
|
fprintf(stderr,"abobjP_resize_object_outline: %s :no SIZE widget\n",
|
|
util_strsafe(obj_get_name(obj)));
|
|
return ERROR;
|
|
}
|
|
|
|
parent = XtParent(xy_widget);
|
|
dpy = XtDisplay(xy_widget);
|
|
rootwin = RootWindowOfScreen(XtScreen(xy_widget));
|
|
|
|
x_get_widget_rect(xy_widget, &orig_r);
|
|
|
|
x_get_widget_rect(parent, &p_rect);
|
|
|
|
XTranslateCoordinates(dpy, XtWindow(parent),
|
|
rootwin, p_rect.x, p_rect.y, &x_tmp, &y_tmp,
|
|
&win);
|
|
|
|
p_rect.x = x_tmp;
|
|
p_rect.y = y_tmp;
|
|
|
|
if (obj_has_border_frame(obj)) /* We have a border-frame to deal with */
|
|
{
|
|
XRectangle pane_r;
|
|
|
|
s_obj = objxm_comp_get_subobj(obj, AB_CFG_SIZE_OBJ);
|
|
|
|
/* Determine width of border */
|
|
x_get_widget_rect(objxm_get_widget(s_obj), &pane_r);
|
|
border_w = ((int)(orig_r.width - pane_r.width))/2;
|
|
}
|
|
else
|
|
border_w = 0;
|
|
|
|
if (orig_r.width > 0) orig_r.width--;
|
|
if (orig_r.height > 0) orig_r.height--;
|
|
|
|
r = orig_r;
|
|
|
|
orig_x = (int)orig_r.x;
|
|
orig_y = (int)orig_r.y;
|
|
|
|
XTranslateCoordinates(dpy, XtWindow(parent),
|
|
rootwin, orig_x , orig_y, &trans_x, &trans_y,
|
|
&win);
|
|
|
|
r.x = (short)trans_x;
|
|
r.y = (short)trans_y;
|
|
|
|
first_move = FALSE;
|
|
}
|
|
else /* erase previous outline */
|
|
{
|
|
make_rect_in_rect(&p_rect, &resize_rect, &r, last_x, last_y, dir);
|
|
x_fullscreen_box(xy_widget, rootwin,
|
|
resize_rect.x, resize_rect.y,
|
|
rect_right(&resize_rect),
|
|
rect_bottom(&resize_rect));
|
|
|
|
}
|
|
|
|
make_rect_in_rect(&p_rect, &resize_rect, &r, x, y, dir);
|
|
x_fullscreen_box(xy_widget, rootwin,
|
|
resize_rect.x, resize_rect.y,
|
|
rect_right(&resize_rect),
|
|
rect_bottom(&resize_rect));
|
|
|
|
sprintf(buf, "%3.3dx%3.3d", resize_rect.width,
|
|
resize_rect.height);
|
|
|
|
/* REMIND: aim, update status region on ab palette win */
|
|
|
|
last_x = x;
|
|
last_y = y;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
/*
|
|
* Resize object according to info in last resize rubberbanding
|
|
*/
|
|
int
|
|
abobj_resize(
|
|
ABObj obj,
|
|
XEvent *event
|
|
)
|
|
{
|
|
Widget parent;
|
|
Display *dpy;
|
|
XRectangle p_rect;
|
|
XRectangle adj_rect;
|
|
Window rootwin;
|
|
int orig_x, orig_y;
|
|
int trans_x, trans_y;
|
|
ABObj moveobj;
|
|
ABObj pobj;
|
|
|
|
if (!first_move) /* resize occurred */
|
|
{
|
|
Window win;
|
|
|
|
if (obj_is_item(obj))
|
|
obj = obj_get_parent(obj);
|
|
|
|
obj = obj_get_root(obj);
|
|
parent = XtParent(xy_widget);
|
|
dpy = XtDisplay(xy_widget);
|
|
|
|
orig_x = (int)resize_rect.x;
|
|
orig_y = (int)resize_rect.y;
|
|
|
|
first_move = TRUE;
|
|
|
|
x_get_widget_rect(parent, &p_rect);
|
|
|
|
rootwin = RootWindowOfScreen(XtScreen(xy_widget));
|
|
|
|
/* erase last rect outline
|
|
*/
|
|
x_fullscreen_box(xy_widget, rootwin,
|
|
resize_rect.x, resize_rect.y,
|
|
rect_right(&resize_rect),
|
|
rect_bottom(&resize_rect));
|
|
|
|
/* translate from root coordinates to parent's
|
|
*/
|
|
XTranslateCoordinates(dpy, rootwin, XtWindow(parent),
|
|
orig_x , orig_y, &trans_x, &trans_y, &win);
|
|
|
|
resize_rect.width++; if (!resize_rect.width) --resize_rect.width;
|
|
resize_rect.height++; if (!resize_rect.height) --resize_rect.height;
|
|
|
|
/* Ensure new geometry fits within parent
|
|
*/
|
|
if (trans_x < 0)
|
|
{
|
|
resize_rect.x = 0;
|
|
resize_rect.width += trans_x;
|
|
|
|
if (obj_is_pane(obj) || obj_is_separator(obj)) /* If a pane, attach to parent's edge */
|
|
obj_set_attachment(xy_obj, AB_CP_WEST, AB_ATTACH_OBJ, obj_get_parent(xy_obj), 0);
|
|
}
|
|
else
|
|
{
|
|
resize_rect.x = trans_x;
|
|
|
|
/* Break edge-attachment */
|
|
if ((obj_is_pane(obj) || obj_is_separator(obj)) &&
|
|
(obj_get_attach_type(xy_obj, AB_CP_WEST) == AB_ATTACH_OBJ &&
|
|
obj_get_attach_value(xy_obj, AB_CP_WEST) == (void*)obj_get_parent(xy_obj)))
|
|
obj_set_attachment(xy_obj, AB_CP_WEST, AB_ATTACH_POINT, (void*)0, trans_x);
|
|
}
|
|
|
|
if (trans_y < 0)
|
|
{
|
|
resize_rect.y = 0;
|
|
resize_rect.height += trans_y;
|
|
|
|
if (obj_is_pane(obj) || obj_is_separator(obj)) /* If a pane, attach to parent's edge */
|
|
obj_set_attachment(xy_obj, AB_CP_NORTH, AB_ATTACH_OBJ, obj_get_parent(xy_obj), 0);
|
|
}
|
|
else
|
|
{
|
|
resize_rect.y = trans_y;
|
|
|
|
/* Break edge-attachment */
|
|
if ((obj_is_pane(obj) || obj_is_separator(obj)) &&
|
|
(obj_get_attach_type(xy_obj, AB_CP_NORTH) == AB_ATTACH_OBJ &&
|
|
obj_get_attach_value(xy_obj, AB_CP_NORTH) == (void*)obj_get_parent(xy_obj)))
|
|
obj_set_attachment(xy_obj, AB_CP_NORTH, AB_ATTACH_POINT, (void*)0, trans_y);
|
|
}
|
|
|
|
if (resize_rect.x + (short)resize_rect.width >= (short)p_rect.width)
|
|
{
|
|
resize_rect.width = (short)p_rect.width - resize_rect.x - 1;
|
|
|
|
if (obj_is_pane(obj) || obj_is_separator(obj)) /* If a pane, attach to parent's edge */
|
|
obj_set_attachment(xy_obj, AB_CP_EAST, AB_ATTACH_OBJ, obj_get_parent(xy_obj), 0);
|
|
}
|
|
else
|
|
{
|
|
/* Break edge-attachment */
|
|
if ((obj_is_pane(obj) || obj_is_separator(obj)) &&
|
|
(obj_get_attach_type(xy_obj, AB_CP_EAST) == AB_ATTACH_OBJ &&
|
|
obj_get_attach_value(xy_obj, AB_CP_EAST) == (void*)obj_get_parent(xy_obj)))
|
|
obj_set_attachment(xy_obj, AB_CP_EAST, AB_ATTACH_NONE, (void*)0, 0);
|
|
}
|
|
|
|
if (resize_rect.y + (short)resize_rect.height > (short)p_rect.height)
|
|
{
|
|
resize_rect.height = (short)p_rect.height - resize_rect.y - 1;
|
|
|
|
if (obj_is_pane(obj) || obj_is_separator(obj)) /* If a pane, attach to parent's edge */
|
|
obj_set_attachment(xy_obj, AB_CP_SOUTH, AB_ATTACH_OBJ, obj_get_parent(xy_obj), 0);
|
|
}
|
|
else
|
|
{
|
|
/* Break edge-attachment */
|
|
if ((obj_is_pane(obj) || obj_is_separator(obj)) &&
|
|
(obj_get_attach_type(xy_obj, AB_CP_SOUTH) == AB_ATTACH_OBJ &&
|
|
obj_get_attach_value(xy_obj, AB_CP_SOUTH) == (void*)obj_get_parent(xy_obj)))
|
|
obj_set_attachment(xy_obj, AB_CP_SOUTH, AB_ATTACH_NONE, (void*)0, 0);
|
|
}
|
|
|
|
(void)abobj_set_undo(&obj, 1, undo_resize, AB_UNDO_RESIZE);
|
|
|
|
pobj = obj_get_parent(obj);
|
|
if (obj_is_layers(pobj))
|
|
moveobj = pobj;
|
|
else
|
|
moveobj = obj;
|
|
|
|
adj_rect = resize_rect;
|
|
if (abobj_has_attached_label(obj))
|
|
subtract_attached_label(obj, &adj_rect);
|
|
|
|
if (obj_is_drawing_area(obj) && obj_has_scrollbar(obj))
|
|
{
|
|
int new_d_w = -1;
|
|
int new_d_h = -1;
|
|
int d_w = obj_get_drawarea_width(obj);
|
|
int d_h = obj_get_drawarea_height(obj);
|
|
|
|
/* If the overall DrawArea dimension is now larger than the internal
|
|
* canvas dimension, resize the canvas dimension to be at least as large
|
|
* as the overall DrawArea.
|
|
*/
|
|
if ((int)resize_rect.width != obj_get_width(obj) &&
|
|
(int)resize_rect.width > d_w)
|
|
new_d_w = (int)resize_rect.width;
|
|
|
|
if ((int)resize_rect.height != obj_get_height(obj) &&
|
|
(int)resize_rect.height > d_h)
|
|
new_d_h = (int)resize_rect.height;
|
|
|
|
if (new_d_w != -1 || new_d_h != -1)
|
|
abobj_set_drawarea_size(obj,
|
|
new_d_w != -1? new_d_w : d_w, new_d_h != -1? new_d_h : d_h);
|
|
}
|
|
|
|
/*
|
|
* Resize the object !
|
|
*/
|
|
if (obj_is_layers(pobj))
|
|
abobj_layer_set_size(pobj, resize_rect.width, resize_rect.height);
|
|
|
|
else if ((obj_is_text(obj) || obj_is_term_pane(obj)) &&
|
|
obj_get_num_columns(obj) != -1)
|
|
/* TextPane, TermPane, TextField with Character-based Sizing */
|
|
abobj_set_text_size(obj, (int)adj_rect.width, (int)adj_rect.height);
|
|
|
|
else if (obj_is_list(obj) && obj_get_num_rows(obj) != -1)
|
|
{
|
|
/* List with Character-based height */
|
|
abobj_set_text_size(obj, (int)adj_rect.width, (int)adj_rect.height);
|
|
abobj_set_pixel_width(obj, (int)adj_rect.width, border_w);
|
|
}
|
|
else /* else size is Pixel-based...*/
|
|
resize_in_pixels(obj, (int)adj_rect.width, (int)adj_rect.height, border_w);
|
|
|
|
abobj_set_xy(moveobj, resize_rect.x, resize_rect.y);
|
|
|
|
if (xy_obj->attachments)
|
|
abobj_calculate_new_layout(xy_obj, resize_rect.x, resize_rect.y,
|
|
resize_rect.width, resize_rect.height);
|
|
|
|
/* Change obj size BEFORE changing attachments...*/
|
|
abobj_instantiate_changes(obj);
|
|
abobj_tree_instantiate_changes(moveobj);
|
|
|
|
/* WORKAROUND for Motif XmForm bug (it ignores child resize request
|
|
* if x,y have not also changed). So, we have to force it.
|
|
*/
|
|
abobj_force_dang_form_resize(xy_obj);
|
|
|
|
if (util_get_verbosity() > 3)
|
|
objxm_dump_widget_geometry(xy_widget);
|
|
|
|
return OK;
|
|
}
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
static void
|
|
subtract_attached_label(
|
|
ABObj obj,
|
|
XRectangle *r_rect
|
|
)
|
|
{
|
|
ABObj lblObj;
|
|
Widget lbl_widget;
|
|
Dimension lbl_w = 0;
|
|
Dimension lbl_h = 0;
|
|
Dimension margin = 0;
|
|
Dimension spacing = 0;
|
|
Dimension width, height;
|
|
|
|
if (!abobj_has_attached_label(obj))
|
|
return;
|
|
|
|
lblObj = objxm_comp_get_subobj(obj, AB_CFG_LABEL_OBJ);
|
|
lbl_widget = objxm_get_widget(lblObj);
|
|
|
|
if (lblObj != NULL && lbl_widget != NULL)
|
|
{
|
|
switch(obj_get_label_position(obj))
|
|
{
|
|
case AB_CP_WEST:
|
|
XtVaGetValues(lbl_widget, XmNwidth, &lbl_w, NULL);
|
|
XtVaGetValues(XtParent(lbl_widget), /* RowColumn */
|
|
XmNmarginWidth, &margin,
|
|
XmNspacing, &spacing,
|
|
NULL);
|
|
|
|
width = r_rect->width - lbl_w - (2*margin) - spacing;
|
|
r_rect->width = width;
|
|
break;
|
|
case AB_CP_NORTH:
|
|
XtVaGetValues(lbl_widget, XmNheight, &lbl_h, NULL);
|
|
XtVaGetValues(XtParent(lbl_widget), /* RowColumn */
|
|
XmNmarginHeight, &margin,
|
|
XmNspacing, &spacing,
|
|
NULL);
|
|
|
|
height = r_rect->height - lbl_h - (2*margin) - spacing;
|
|
r_rect->height = height;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
resize_in_pixels(
|
|
ABObj obj,
|
|
int width,
|
|
int height,
|
|
int border_w
|
|
)
|
|
{
|
|
BOOL w_resizable = abobj_width_resizable(obj);
|
|
BOOL h_resizable = abobj_height_resizable(obj);
|
|
|
|
if (w_resizable && h_resizable)
|
|
abobj_set_pixel_size(obj, width, height, border_w);
|
|
|
|
else if (w_resizable)
|
|
abobj_set_pixel_width(obj, width, border_w);
|
|
|
|
else if (h_resizable)
|
|
abobj_set_pixel_height(obj, height, border_w);
|
|
|
|
}
|
|
|
|
void
|
|
abobjP_track_external_resizes(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent *event,
|
|
Boolean cont_to_dispatch
|
|
)
|
|
{
|
|
ABObj obj = (ABObj)client_data;
|
|
Widget parent = XtParent(widget);
|
|
int new_value;
|
|
int new_h = -1;
|
|
int new_w = -1;
|
|
int old_w, old_h;
|
|
BOOL resized = False;
|
|
|
|
if (event->type == ConfigureNotify)
|
|
{
|
|
XConfigureEvent *cfg_event = (XConfigureEvent *)&event->xconfigure;
|
|
|
|
obj_get_size(obj, &old_w, &old_h);
|
|
|
|
if (old_w != -1)
|
|
new_w = (int)cfg_event->width + (2*cfg_event->border_width);
|
|
|
|
if (old_h != -1)
|
|
new_h = (int)cfg_event->height + (2*cfg_event->border_width);
|
|
|
|
if (new_w != old_w || new_h != old_h)
|
|
{
|
|
if (obj && obj_is_group(obj) &&
|
|
(obj_get_group_type(obj) != AB_GROUP_IGNORE))
|
|
{
|
|
return;
|
|
}
|
|
|
|
abobj_set_save_needed(obj_get_module(obj), TRUE);
|
|
obj_resize(obj, new_w, new_h);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* calculate resize rect based on resize-direction & obj dimensions
|
|
*/
|
|
static void
|
|
make_rect (
|
|
XRectangle *new_r,
|
|
XRectangle *r,
|
|
int x,
|
|
int y,
|
|
RESIZE_DIR dir
|
|
)
|
|
{
|
|
switch (dir)
|
|
{
|
|
case NORTH:
|
|
new_r->x = r->x;
|
|
new_r->y = min(y, rect_bottom(r));
|
|
new_r->width = r->width;
|
|
new_r->height = max(0, r->y + r->height - y);
|
|
break;
|
|
case SOUTH:
|
|
new_r->x = r->x;
|
|
new_r->y = r->y;
|
|
new_r->width = r->width;
|
|
new_r->height = max(0, y - r->y);
|
|
break;
|
|
case EAST:
|
|
new_r->x = r->x;
|
|
new_r->y = r->y;
|
|
new_r->width = max(0, x - r->x);
|
|
new_r->height = r->height;
|
|
break;
|
|
case WEST:
|
|
new_r->x = min(x, rect_right(r));
|
|
new_r->y = r->y;
|
|
new_r->width = max(0, r->x + r->width - x);
|
|
new_r->height = r->height;
|
|
break;
|
|
case NORTH_EAST:
|
|
new_r->x = r->x;
|
|
new_r->y = min(y, rect_bottom(r));
|
|
new_r->width = max(0, x - r->x);
|
|
new_r->height = max(0, r->y + r->height - y);
|
|
break;
|
|
case NORTH_WEST:
|
|
new_r->x = min(x, rect_right(r));
|
|
new_r->y = min(y, rect_bottom(r));
|
|
new_r->width = max(0, r->x + r->width - x);
|
|
new_r->height = max(0, r->y + r->height - y);
|
|
break;
|
|
case SOUTH_EAST:
|
|
new_r->x = r->x;
|
|
new_r->y = r->y;
|
|
new_r->width = max(0, x - r->x);
|
|
new_r->height = max(0, y - r->y);
|
|
break;
|
|
case SOUTH_WEST:
|
|
new_r->x = min(x, rect_right(r));
|
|
new_r->y = r->y;
|
|
new_r->width = max(0, r->x + r->width - x);
|
|
new_r->height = max(0, y - r->y);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* calculate resize rect based on resize-direction & obj dimensions & a
|
|
* boundary.
|
|
*/
|
|
static void
|
|
make_rect_in_rect(
|
|
XRectangle *pr,
|
|
XRectangle *new_r,
|
|
XRectangle *r,
|
|
int x,
|
|
int y,
|
|
RESIZE_DIR dir
|
|
)
|
|
{
|
|
int x_tmp, y_tmp;
|
|
int pr_right = rect_right(pr);
|
|
int pr_bottom = rect_bottom(pr);
|
|
|
|
if (x < pr->x) x_tmp = pr->x;
|
|
else if (x > pr_right) x_tmp = pr_right;
|
|
else x_tmp = x;
|
|
|
|
if (y < pr->y) y_tmp = pr->y;
|
|
else if (y > pr_bottom) y_tmp = pr_bottom;
|
|
else y_tmp = y;
|
|
|
|
make_rect(new_r, r, x_tmp, y_tmp, dir);
|
|
}
|
|
|
|
/*
|
|
* Function for undoing RESIZE
|
|
*/
|
|
static void
|
|
undo_resize(
|
|
ABUndoRec undo_rec
|
|
)
|
|
{
|
|
|
|
Position x,
|
|
y;
|
|
int width,
|
|
height,
|
|
i;
|
|
ABObj obj;
|
|
|
|
if (!undo_rec)
|
|
return;
|
|
|
|
/*
|
|
* Set undo to undo this resize (undo of undo)
|
|
*/
|
|
(void)abobj_set_undo(undo_rec->list, undo_rec->count,
|
|
undo_resize, AB_UNDO_RESIZE);
|
|
|
|
/*
|
|
* For each object that was resized
|
|
*/
|
|
for (i = 0; i < undo_rec->count; ++i)
|
|
{
|
|
BOOL w_resizable, h_resizable;
|
|
/*
|
|
* If undo record is not the right type, something is WRONG !!
|
|
*/
|
|
if (undo_rec->info_list[i].type != AB_UNDO_RESIZE)
|
|
continue;
|
|
|
|
obj = undo_rec->list[i];
|
|
w_resizable = abobj_width_resizable(obj);
|
|
h_resizable = abobj_height_resizable(obj);
|
|
|
|
/*
|
|
* Get current x,y position
|
|
*/
|
|
if (obj->ui_handle)
|
|
{
|
|
XtVaGetValues(objxm_get_widget(obj),
|
|
XmNx, &x,
|
|
XmNy, &y,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
x = (Position)obj_get_x(obj);
|
|
y = (Position)obj_get_y(obj);
|
|
}
|
|
|
|
/*
|
|
* Get previous width/height
|
|
*/
|
|
width = undo_rec->info_list[i].info.resize.width;
|
|
height = undo_rec->info_list[i].info.resize.height;
|
|
|
|
/*
|
|
* Resize the object !
|
|
*/
|
|
resize_in_pixels(obj, (int)width, (int)height, border_w);
|
|
abobj_set_xy(obj, (int)x, (int)y);
|
|
|
|
if (xy_obj->attachments)
|
|
abobj_calculate_new_layout(xy_obj, (int)x, (int)y,
|
|
width, height);
|
|
|
|
abobj_instantiate_changes(obj);
|
|
|
|
/* WORKAROUND for Motif XmForm bug (it ignores child resize request
|
|
* if x,y have not also changed). So, we have to force it.
|
|
*/
|
|
abobj_force_dang_form_resize(xy_obj);
|
|
|
|
if (util_get_verbosity() > 3)
|
|
objxm_dump_widget_geometry(xy_widget);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Can the object be resized using direct-manipulation?
|
|
*/
|
|
BOOL
|
|
abobj_is_directly_resizable(
|
|
ABObj obj
|
|
)
|
|
{
|
|
BOOL resizable = True;
|
|
|
|
switch(obj_get_type(obj))
|
|
{
|
|
case AB_TYPE_BUTTON:
|
|
case AB_TYPE_LABEL:
|
|
case AB_TYPE_COMBO_BOX:
|
|
case AB_TYPE_LIST:
|
|
if (obj_get_width(obj) == -1)
|
|
resizable = False;
|
|
break;
|
|
case AB_TYPE_CHOICE:
|
|
resizable = False;
|
|
break;
|
|
case AB_TYPE_CONTAINER:
|
|
{
|
|
AB_CONTAINER_TYPE cont_type;
|
|
cont_type = obj_get_container_type(obj);
|
|
if ((cont_type == AB_CONT_MENU_BAR ||
|
|
cont_type == AB_CONT_TOOL_BAR ||
|
|
cont_type == AB_CONT_FOOTER ||
|
|
cont_type == AB_CONT_BUTTON_PANEL ||
|
|
cont_type == AB_CONT_GROUP) ||
|
|
obj_get_width(obj) == -1)
|
|
resizable = False;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return resizable;
|
|
}
|
|
|
|
/*
|
|
* Can the object's height be changed (from Prop sheet)?
|
|
*/
|
|
BOOL
|
|
abobj_height_resizable(
|
|
ABObj obj
|
|
)
|
|
{
|
|
BOOL resizable = True;
|
|
|
|
switch(obj_get_type(obj))
|
|
{
|
|
case AB_TYPE_COMBO_BOX:
|
|
case AB_TYPE_TEXT_FIELD:
|
|
case AB_TYPE_SPIN_BOX:
|
|
case AB_TYPE_CHOICE:
|
|
resizable = False;
|
|
break;
|
|
case AB_TYPE_BUTTON:
|
|
case AB_TYPE_LABEL:
|
|
case AB_TYPE_BASE_WINDOW:
|
|
case AB_TYPE_DIALOG:
|
|
if (obj_get_height(obj) == -1)
|
|
resizable = False;
|
|
break;
|
|
case AB_TYPE_SCALE:
|
|
if (obj_get_orientation(obj) == AB_ORIENT_HORIZONTAL)
|
|
resizable = False;
|
|
break;
|
|
case AB_TYPE_CONTAINER:
|
|
{
|
|
AB_CONTAINER_TYPE cont_type;
|
|
cont_type = obj_get_container_type(obj);
|
|
if (cont_type == AB_CONT_MENU_BAR ||
|
|
(obj_is_control_panel(obj) && obj_get_height(obj) == -1))
|
|
resizable = False;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return resizable;
|
|
}
|
|
|
|
/*
|
|
* Can the object's width be changed (from Prop sheet)?
|
|
*/
|
|
BOOL
|
|
abobj_width_resizable(
|
|
ABObj obj
|
|
)
|
|
{
|
|
BOOL resizable = True;
|
|
|
|
switch(obj_get_type(obj))
|
|
{
|
|
case AB_TYPE_CHOICE:
|
|
resizable = False;
|
|
break;
|
|
case AB_TYPE_SPIN_BOX:
|
|
case AB_TYPE_COMBO_BOX:
|
|
case AB_TYPE_BUTTON:
|
|
case AB_TYPE_LABEL:
|
|
case AB_TYPE_LIST:
|
|
case AB_TYPE_BASE_WINDOW:
|
|
case AB_TYPE_DIALOG:
|
|
if (obj_get_width(obj) == -1)
|
|
resizable = False;
|
|
break;
|
|
case AB_TYPE_SCALE:
|
|
if (obj_get_orientation(obj) == AB_ORIENT_VERTICAL)
|
|
resizable = False;
|
|
break;
|
|
case AB_TYPE_CONTAINER:
|
|
{
|
|
AB_CONTAINER_TYPE cont_type;
|
|
cont_type = obj_get_container_type(obj);
|
|
if (cont_type == AB_CONT_MENU_BAR ||
|
|
cont_type == AB_CONT_TOOL_BAR ||
|
|
cont_type == AB_CONT_FOOTER ||
|
|
cont_type == AB_CONT_BUTTON_PANEL ||
|
|
cont_type == AB_CONT_GROUP ||
|
|
(obj_is_control_panel(obj) && obj_get_width(obj) == -1))
|
|
resizable = False;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return resizable;
|
|
}
|