/* Copyright (c) 1999 Alexander Yukhimets. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #define X(w) (((CoreWidget)(w))->core.x) #define Y(w) (((CoreWidget)(w))->core.y) #define WIDTH(w) (((CoreWidget)(w))->core.width) #define HEIGHT(w) (((CoreWidget)(w))->core.height) #define DEPTH(w) (((CoreWidget)(w))->core.depth) #define BORDER(w) (((CoreWidget)(w))->core.border_width) #define COLORMAP(w) (((CoreWidget)(w))->core.colormap) #define BACKGROUND(w) (((CoreWidget)(w))->core.background_pixel) #define NUM_CHILDREN(w) (((CompositeWidget)(w))->composite.num_children) #define CHILD(w,i) (((CompositeWidget)(w))->composite.children[(i)]) #define CONSTRAINTS(w) (((CoreWidget)(w))->core.constraints) #define HAS_FOCUS(w) (((XmManagerWidget)(w))->manager.has_focus) #define SHADOW_THICKNESS(w) (((XmManagerWidget)(w))->manager.shadow_thickness) #define STRING_DIR(w) (((XmManagerWidget)(w))->manager.string_direction) #define FOREGROUND(w) (((XmManagerWidget)(w))->manager.foreground) #define HIGHLIGHT_COLOR(w) (((XmManagerWidget)(w))->manager.highlight_color) #define HIGHLIGHT_PIXMAP(w) (((XmManagerWidget)(w))->manager.highlight_pixmap) #define HIGHLIGHT_GC(w) (((XmManagerWidget)(w))->manager.highlight_GC) #define BACKGROUND_GC(w) (((XmManagerWidget)(w))->manager.background_GC) #define TOP_SHADOW_GC(w) (((XmManagerWidget)(w))->manager.top_shadow_GC) #define BOTTOM_SHADOW_GC(w) (((XmManagerWidget)(w))->manager.bottom_shadow_GC) #define ARM_COLOR(w) (((XmAxyNotebookWidget)(w))->notebook.arm_color) #define FONT_LIST(w) (((XmAxyNotebookWidget)(w))->notebook.font_list) #define SHOW_TABS(w) (((XmAxyNotebookWidget)(w))->notebook.show_tabs) #define HIGHLIGHT_THICKNESS(w) \ (((XmAxyNotebookWidget)(w))->notebook.highlight_thickness) #define MARGIN_WIDTH(w) (((XmAxyNotebookWidget)(w))->notebook.margin_width) #define MARGIN_HEIGHT(w) (((XmAxyNotebookWidget)(w))->notebook.margin_height) #define INNER_MARGIN_WIDTH(w) \ (((XmAxyNotebookWidget)(w))->notebook.inner_margin_width) #define INNER_MARGIN_HEIGHT(w) \ (((XmAxyNotebookWidget)(w))->notebook.inner_margin_height) #define TAB_SPACING(w) (((XmAxyNotebookWidget)(w))->notebook.tab_spacing) #define TAB_RAISE(w) (((XmAxyNotebookWidget)(w))->notebook.tab_raise) #define TAB_MARGIN_WIDTH(w) \ (((XmAxyNotebookWidget)(w))->notebook.tab_margin_width) #define TAB_MARGIN_HEIGHT(w) \ (((XmAxyNotebookWidget)(w))->notebook.tab_margin_height) #define LABEL_MARGIN_WIDTH(w) \ (((XmAxyNotebookWidget)(w))->notebook.label_margin_width) #define LABEL_MARGIN_HEIGHT(w) \ (((XmAxyNotebookWidget)(w))->notebook.label_margin_height) #define PAGE_CHANGED_CB(w) \ (((XmAxyNotebookWidget)(w))->notebook.page_changed_callback) #define FONT_FID(w) (((XmAxyNotebookWidget)(w))->notebook.font_fid) #define FONT_WIDTH(w) (((XmAxyNotebookWidget)(w))->notebook.font_width) #define FONT_HEIGHT(w) (((XmAxyNotebookWidget)(w))->notebook.font_height) #define FONT_Y(w) (((XmAxyNotebookWidget)(w))->notebook.font_y) #define DRAWING_AREA(w) (((XmAxyNotebookWidget)(w))->notebook.drawing_area) #define HIGHLIGHTED_TAB(w) \ (((XmAxyNotebookWidget)(w))->notebook.highlighted_tab) #define HIGHLIGHT_DRAWN(w) \ (((XmAxyNotebookWidget)(w))->notebook.highlight_drawn) #define CURRENT_WIDGET(w) (((XmAxyNotebookWidget)(w))->notebook.current_widget) #define CURRENT_PAGE(w) (((XmAxyNotebookWidget)(w))->notebook.current_page) #define NUM_PAGES(w) (((XmAxyNotebookWidget)(w))->notebook.num_pages) #define TAB_HEIGHT(w) (((XmAxyNotebookWidget)(w))->notebook.tab_height) #define CHILD_X(w) (((XmAxyNotebookWidget)(w))->notebook.child_x) #define CHILD_Y(w) (((XmAxyNotebookWidget)(w))->notebook.child_y) #define CHILD_WIDTH(w) (((XmAxyNotebookWidget)(w))->notebook.child_width) #define CHILD_HEIGHT(w) (((XmAxyNotebookWidget)(w))->notebook.child_height) #define NORMAL_GC(w) (((XmAxyNotebookWidget)(w))->notebook.normal_gc) #define ARM_GC(w) (((XmAxyNotebookWidget)(w))->notebook.arm_gc) #define TAB_CHILD(w) (((XmAxyNotebookWidget)(w))->notebook.tab_child) #define CHILD_CONSTR(w,i) CONSTRAINTS(CHILD(w,i)) #define C_TAB_LABEL(r) (((XmAxyNotebookConstraintRec*)r)->notebook.tab_label) #define C_RESIZABLE(r) (((XmAxyNotebookConstraintRec*)r)->notebook.resizable) #define C_TAB_RECT(r) (((XmAxyNotebookConstraintRec*)r)->notebook.tab_rect) #define C_PAGE_NUM(r) (((XmAxyNotebookConstraintRec*)r)->notebook.page_number) #define C_IS_TAB(r) (((XmAxyNotebookConstraintRec*)r)->notebook.is_tab) #define C_TAB_CLIP(r) (((XmAxyNotebookConstraintRec*)r)->notebook.tab_clip) #define C_TAB_VISIBLE(r) \ (((XmAxyNotebookConstraintRec*)r)->notebook.tab_visible) #define TAB_LABEL_I(w,i) C_TAB_LABEL(CHILD_CONSTR(w,i)) #define RESIZABLE_I(w,i) C_RESIZABLE(CHILD_CONSTR(w,i)) #define TAB_RECT_I(w,i) C_TAB_RECT(CHILD_CONSTR(w,i)) #define PAGE_NUM_I(w,i) C_PAGE_NUM(CHILD_CONSTR(w,i)) #define IS_TAB_I(w,i) C_IS_TAB(CHILD_CONSTR(w,i)) #define TAB_CLIP_I(w,i) C_TAB_CLIP(CHILD_CONSTR(w,i)) #define TAB_VISIBLE_I(w,i) C_TAB_VISIBLE(CHILD_CONSTR(w,i)) #define TAB_LABEL(c) C_TAB_LABEL(CONSTRAINTS(c)) #define RESIZABLE(c) C_RESIZABLE(CONSTRAINTS(c)) #define TAB_RECT(c) C_TAB_RECT(CONSTRAINTS(c)) #define PAGE_NUM(c) C_PAGE_NUM(CONSTRAINTS(c)) #define IS_TAB(c) C_IS_TAB(CONSTRAINTS(c)) #define TAB_CLIP(c) C_TAB_CLIP(CONSTRAINTS(c)) #define TAB_VISIBLE(c) C_TAB_VISIBLE(CONSTRAINTS(c)) #define DEFAULT_FONT_LIST(w) _XmGetDefaultFontList((Widget)w, XmFONT_IS_FONT) #define EHT(w) \ ((HIGHLIGHT_THICKNESS(w)<=0)?(Dimension)0:(HIGHLIGHT_THICKNESS(w)+1)) /* class methods */ static void Initialize(Widget,Widget,ArgList,Cardinal*); static void Destroy(Widget); static void Resize(Widget); static void Redisplay(Widget, XEvent*, Region); static Boolean SetValues(Widget,Widget, Widget,ArgList,Cardinal*); static XtGeometryResult QueryGeometry(Widget,XtWidgetGeometry*, XtWidgetGeometry*); static void ChangeManaged(Widget); static XtGeometryResult GeometryManager(Widget,XtWidgetGeometry*, XtWidgetGeometry*); static void ConstraintInitialize(Widget,Widget,ArgList,Cardinal*); static void ConstraintDestroy(Widget); static Boolean ConstraintSetValues(Widget,Widget, Widget,ArgList,Cardinal*); /* action routines */ static void DAFocusIn(Widget,XEvent*,String*,Cardinal*); static void DAFocusOut(Widget,XEvent*,String*,Cardinal*); static void DAMouseDown(Widget,XEvent*,String*,Cardinal*); static void DAMoveLeft(Widget,XEvent*,String*,Cardinal*); static void DAMoveRight(Widget,XEvent*,String*,Cardinal*); static void DASelect(Widget,XEvent*,String*,Cardinal*); /* local functions */ static void install_font(Widget); static void create_gc(Widget); static void calc_preferred_size(Widget,Dimension*,Dimension*,Widget); static void do_layout(Widget,Widget); static void compute_tab_rects(Widget); static void configure_children(Widget,Widget); static void draw_shadows(Widget,Region); static void draw_da_tabs(Widget,Window,XEvent*); static void draw_da_highlight(Widget); static Widget search_da_tab(Widget, XEvent*); static void expose_da_cb(Widget,XtPointer,XtPointer); static void change_tab(Widget, Widget); static XtActionsRec actions[] = { {"XmAxyNotebookDAMouseDown",DAMouseDown}, {"XmAxyNotebookDAFocusIn",DAFocusIn}, {"XmAxyNotebookDAFocusOut",DAFocusOut}, {"XmAxyNotebookDAMoveRight",DAMoveRight}, {"XmAxyNotebookDAMoveLeft",DAMoveLeft}, {"XmAxyNotebookDASelect",DASelect}, }; static char drawingAreaTranslations[]="\ : XmAxyNotebookDAFocusIn()\n\ : XmAxyNotebookDAFocusOut()\n\ : XmAxyNotebookDAMouseDown()\n\ (2+): XmAxyNotebookDAMouseDown()\n\ :osfRight: XmAxyNotebookDAMoveRight()\n\ :osfLeft: XmAxyNotebookDAMoveLeft()\n\ :osfDown: XmAxyNotebookDAMoveRight()\n\ :osfUp: XmAxyNotebookDAMoveLeft()\n\ Return: XmAxyNotebookDASelect()\n\ space: XmAxyNotebookDASelect()\n\ "; #define Offset(field) XtOffsetOf(XmAxyNotebookRec, notebook.field) #define offset(field) XtOffsetOf(XmAxyNotebookRec, field) static XtResource resources[]={ {XmNselectColor,XmCSelectColor, XmRPixel,sizeof(Pixel), Offset(arm_color),XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXEL}, {XmNfontList,XmCFontList, XmRFontList,sizeof(XmFontList), Offset(font_list),XmRImmediate, (XtPointer)NULL}, {XmNshowTabs,XmCShowTabs, XmRBoolean,sizeof(Boolean), Offset(show_tabs),XmRImmediate, (XtPointer)TRUE}, {XmNhighlightThickness,XmCHighlightThickness, XmRHorizontalDimension,sizeof(Dimension), Offset(highlight_thickness),XmRImmediate, (XtPointer)1}, {XmNinnerMarginHeight,XmCInnerMarginHeight, XmRVerticalDimension,sizeof(Dimension), Offset(inner_margin_height),XmRImmediate, (XtPointer)4}, {XmNinnerMarginWidth,XmCInnerMarginWidth, XmRHorizontalDimension,sizeof(Dimension), Offset(inner_margin_width),XmRImmediate, (XtPointer)4}, {XmNmarginHeight,XmCMarginHeight, XmRVerticalDimension,sizeof(Dimension), Offset(margin_height),XmRImmediate, (XtPointer)6}, {XmNmarginWidth,XmCMarginWidth, XmRHorizontalDimension,sizeof(Dimension), Offset(margin_width),XmRImmediate, (XtPointer)6}, {XmNpageChangedCallback,XmCPageChangedCallback, XtRCallback,sizeof(XtPointer), Offset(page_changed_callback), XtRImmediate, (XtPointer)NULL}, {XmNtabRaise,XmCTabRaise, XmRVerticalDimension,sizeof(Dimension), Offset(tab_raise), XtRImmediate, (XtPointer)2}, {XmNtabSpacing,XmCTabSpacing, XmRHorizontalDimension,sizeof(Dimension), Offset(tab_spacing),XmRImmediate, (XtPointer)0}, {XmNtabMarginWidth,XmCTabMarginWidth, XmRHorizontalDimension,sizeof(Dimension), Offset(tab_margin_width),XmRImmediate, (XtPointer)2}, {XmNtabMarginHeight,XmCTabMarginHeight, XmRVerticalDimension,sizeof(Dimension), Offset(tab_margin_height),XmRImmediate, (XtPointer)2}, {XmNlabelMarginWidth,XmCLabelMarginWidth, XmRHorizontalDimension,sizeof(Dimension), Offset(label_margin_width),XmRImmediate, (XtPointer)2}, {XmNlabelMarginHeight,XmCLabelMarginHeight, XmRVerticalDimension,sizeof(Dimension), Offset(label_margin_height),XmRImmediate, (XtPointer)2}, {XmNshadowThickness,XmCShadowThickness, XmRHorizontalDimension,sizeof(Dimension), offset(manager.shadow_thickness),XmRImmediate, (XtPointer)2}, }; static XmSyntheticResource syn_resources[] = { {XmNhighlightThickness, sizeof(Dimension), Offset(highlight_thickness), _XmFromHorizontalPixels, _XmToHorizontalPixels}, {XmNinnerMarginWidth, sizeof(Dimension), Offset(inner_margin_width), _XmFromHorizontalPixels, _XmToHorizontalPixels}, {XmNinnerMarginHeight, sizeof(Dimension), Offset(inner_margin_height), _XmFromVerticalPixels, _XmToVerticalPixels}, {XmNmarginWidth, sizeof(Dimension), Offset(margin_width), _XmFromHorizontalPixels, _XmToHorizontalPixels}, {XmNmarginHeight, sizeof(Dimension), Offset(margin_height), _XmFromVerticalPixels, _XmToVerticalPixels}, {XmNtabRaise, sizeof(Dimension), Offset(tab_raise), _XmFromVerticalPixels, _XmToVerticalPixels}, {XmNtabMarginWidth, sizeof(Dimension), Offset(tab_margin_width), _XmFromHorizontalPixels, _XmToHorizontalPixels}, {XmNtabMarginHeight, sizeof(Dimension), Offset(tab_margin_height), _XmFromVerticalPixels, _XmToVerticalPixels}, {XmNlabelMarginWidth, sizeof(Dimension), Offset(label_margin_width), _XmFromHorizontalPixels, _XmToHorizontalPixels}, {XmNlabelMarginHeight, sizeof(Dimension), Offset(label_margin_height), _XmFromVerticalPixels, _XmToVerticalPixels}, }; #undef offset #undef Offset static XtResource constraints[]={ {XmNtabLabel,XmCTabLabel, XmRXmString,sizeof(XmString), XtOffsetOf(XmAxyNotebookConstraintRec, notebook.tab_label), XmRImmediate,(XtPointer)NULL}, {XmNresizable,XmCResizable, XmRBoolean,sizeof(Boolean), XtOffsetOf(XmAxyNotebookConstraintRec, notebook.resizable), XmRImmediate,(XtPointer)TRUE} }; externaldef (xmaxynotebookclassrec) XmAxyNotebookClassRec xmAxyNotebookClassRec={ /* Core class part */ { /* superclass */ (WidgetClass)&xmManagerClassRec, /* class_name */ "XmAxyNotebook", /* widget_size */ sizeof(XmAxyNotebookRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ XtExposeCompressMaximal, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ QueryGeometry, /* display_accelerator */ NULL, /* extension */ NULL, }, /* Composite Class part */ { /* geometry_manager */ GeometryManager, /* change_managed */ ChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL, }, /* Constraint Class part */ { /* resources */ constraints, /* num_resources */ XtNumber(constraints), /* constraint_size */ sizeof(XmAxyNotebookConstraintRec), /* initialize */ ConstraintInitialize, /* destroy */ ConstraintDestroy, /* set_values */ ConstraintSetValues, /* extension */ NULL, }, /* Manager Class part */ { /* translations */ XtInheritTranslations, /* syn_resources */ syn_resources, /* num_syn_resources */ XtNumber(syn_resources), /* syn_constraint_resources */ NULL, /* num_syn_constraint_resources */0, /* parent_process */ XmInheritParentProcess, /* extension */ NULL, }, /* Notebook Class part */ { /* extension */ NULL, } }; externaldef (xmaxynotebookwidgetclass) WidgetClass xmAxyNotebookWidgetClass=(WidgetClass) &xmAxyNotebookClassRec; /* Core class methods */ static void Initialize(Widget wreq,Widget wnew,ArgList args,Cardinal *nargs){ Arg arg[10]; Cardinal n; if(ARM_COLOR(wnew)==XmUNSPECIFIED_PIXEL){ Pixel fg,ts,bs; XmGetColors(XtScreen(wnew),COLORMAP(wnew),BACKGROUND(wnew), &fg,&ts,&bs,&ARM_COLOR(wnew)); } if(FONT_LIST(wnew)==NULL){ FONT_LIST(wnew)=XmFontListCopy( _XmGetDefaultFontList(wnew,XmLABEL_FONTLIST)); } else { FONT_LIST(wnew)=XmFontListCopy(FONT_LIST(wnew)); } install_font(wnew); CURRENT_WIDGET(wnew)=NULL; CURRENT_PAGE(wnew)=0; NUM_PAGES(wnew)=0; TAB_HEIGHT(wnew)=0; CHILD_WIDTH(wnew)=0; CHILD_HEIGHT(wnew)=0; HIGHLIGHTED_TAB(wnew)=0; HIGHLIGHT_DRAWN(wnew)=FALSE; create_gc(wnew); TAB_CHILD(wnew)=TRUE; n=0; XtSetArg(arg[n],XmNbackground,BACKGROUND(wnew));n++; DRAWING_AREA(wnew)=XtCreateWidget("Tabs",xmDrawingAreaWidgetClass, wnew,arg,n); XtOverrideTranslations(DRAWING_AREA(wnew), XtParseTranslationTable(drawingAreaTranslations)); if(SHOW_TABS(wnew))XtManageChild(DRAWING_AREA(wnew)); XtAddCallback(DRAWING_AREA(wnew),XmNexposeCallback, expose_da_cb,(XtPointer)wnew); XtAddCallback(DRAWING_AREA(wnew),XmNresizeCallback, expose_da_cb,(XtPointer)wnew); XtVaSetValues(wnew,XmNinitialFocus,DRAWING_AREA(wnew),NULL); } static void Destroy(Widget w){ XmFontListFree(FONT_LIST(w)); XtReleaseGC(w,NORMAL_GC(w)); XtReleaseGC(w,ARM_GC(w)); } static void Resize(Widget w){ do_layout(w,NULL); draw_shadows(w,NULL); } static void Redisplay(Widget w, XEvent *event, Region region){ draw_shadows(w,region); _XmRedisplayGadgets(w,event,region); } #define NE(field) \ (((XmAxyNotebookWidget)wcur)->field != ((XmAxyNotebookWidget)wnew)->field) #define NB(field) \ ((((XmAxyNotebookWidget)wcur)->field && !((XmAxyNotebookWidget)wnew)->field) ||\ (!((XmAxyNotebookWidget)wcur)->field && ((XmAxyNotebookWidget)wnew)->field)) static Boolean SetValues(Widget wcur,Widget wreq, Widget wnew, ArgList args,Cardinal *nargs){ Boolean redraw=FALSE; Boolean layout=FALSE; if(NE(notebook.arm_color) || NE(manager.foreground) || NE(core.background_pixel)){ XtReleaseGC(wnew,NORMAL_GC(wnew)); XtReleaseGC(wnew,ARM_GC(wnew)); create_gc(wnew); XtVaSetValues(DRAWING_AREA(wnew),XmNbackground,BACKGROUND(wnew),NULL); redraw=TRUE; } if(NE(notebook.font_list)){ XmFontListFree(FONT_LIST(wcur)); install_font(wnew); layout=TRUE; redraw=TRUE; } if(NE(notebook.tab_raise)){ layout=TRUE; redraw=TRUE; } if(NB(notebook.show_tabs)){ layout=TRUE; redraw=TRUE; if(!SHOW_TABS(wnew))XtUnmanageChild(DRAWING_AREA(wnew)); else XtManageChild(DRAWING_AREA(wnew)); } if(NE(notebook.highlight_thickness) || NE(notebook.margin_width) || NE(notebook.margin_height) || NE(notebook.inner_margin_height) || NE(notebook.inner_margin_width) || NE(notebook.tab_spacing) || NE(manager.shadow_thickness) || NE(manager.string_direction)){ layout=TRUE; redraw=TRUE; } if(layout) { if(HEIGHT(wcur)==HEIGHT(wnew) || WIDTH(wcur)==WIDTH(wnew)){ Dimension width,height; calc_preferred_size(wnew,&width,&height,NULL); if(HEIGHT(wcur)==HEIGHT(wnew)) HEIGHT(wnew)=height; if(WIDTH(wcur)==WIDTH(wnew)) WIDTH(wnew)=width; } if(HEIGHT(wcur)==HEIGHT(wnew) && WIDTH(wcur)==WIDTH(wnew)){ do_layout(wnew,NULL); redraw=TRUE; } } return redraw; } #undef NE #undef NB static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *proposed,XtWidgetGeometry *answer){ Dimension width,height; calc_preferred_size(w,&width,&height,NULL); if(!XtIsRealized(w)){ if(WIDTH(w)!=0) width=WIDTH(w); if(HEIGHT(w)!=0) height=HEIGHT(w); } if(answer!=NULL){ answer->request_mode=(CWWidth | CWHeight); answer->width=width; answer->height=height; } if(((proposed->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight)) && proposed->width==width && proposed->height==height) return XtGeometryYes; else if(width == WIDTH(w) && height == HEIGHT(w)) return XtGeometryNo; else return XtGeometryAlmost; } /* Composite methods */ static XtGeometryResult GeometryManager(Widget child, XtWidgetGeometry *request,XtWidgetGeometry *reply){ Widget w=XtParent(child); Dimension width,height,saved_width,saved_height; XtWidgetGeometry parent; XtGeometryResult result; if(!RESIZABLE(child)) return XtGeometryNo; if((request->request_mode & CWX) || (request->request_mode & CWY)) return XtGeometryNo; saved_width=WIDTH(child); saved_height=HEIGHT(child); WIDTH(child)=request->width; HEIGHT(child)=request->height; calc_preferred_size(w,&width,&height,child); WIDTH(child)=saved_width; HEIGHT(child)=saved_height; if(width==WIDTH(w) && height==HEIGHT(w)) return XtGeometryYes; parent.request_mode=(CWWidth|CWHeight); parent.width=width; parent.height=height; if(request->request_mode & XtCWQueryOnly){ parent.request_mode |= XtCWQueryOnly; } result=XtMakeGeometryRequest(XtParent(w),&parent,NULL); if(result==XtGeometryAlmost) result=XtGeometryNo; if(result==XtGeometryYes && !(request->request_mode & XtCWQueryOnly)){ WIDTH(child)=request->width; HEIGHT(child)=request->height; do_layout(w,child); } else { do_layout(w,child); } return result; } static void ChangeManaged(Widget w){ Dimension width,height; int i,page=0; for(i=0;i0 && CURRENT_PAGE(w)==page) CURRENT_WIDGET(w)=CHILD(w,i); } } if(CURRENT_WIDGET(w)==NULL || PAGE_NUM(CURRENT_WIDGET(w))!=CURRENT_PAGE(w)){ for(i=0;imax_logical_extent.width; FONT_HEIGHT(w) = extents->max_logical_extent.height; FONT_Y(w) = extents->max_logical_extent.y; XFontsOfFontSet((XFontSet)font, &fonts, &font_names); FONT_FID(w) = fonts[0]->fid; } else { FONT_WIDTH(w) = (font->max_bounds.width + font->min_bounds.width) /2; FONT_HEIGHT(w) = (font->max_bounds.descent + font->max_bounds.ascent); FONT_Y(w) = font->max_bounds.ascent; FONT_FID(w) = font->fid; } XmFontListFreeFontContext(context); } static void create_gc(Widget w){ XGCValues values; values.foreground = FOREGROUND(w); values.background = BACKGROUND(w); values.font=FONT_FID(w); NORMAL_GC(w) = XtAllocateGC(w,DEPTH(w), GCForeground|GCBackground|GCFont,&values, GCClipXOrigin|GCClipYOrigin|GCPlaneMask|GCForeground|GCBackground|GCFont, GCLineWidth|GCLineStyle|GCCapStyle|GCJoinStyle|GCGraphicsExposures| GCDashOffset|GCArcMode); values.foreground=ARM_COLOR(w); ARM_GC(w) = XtAllocateGC(w,DEPTH(w), GCForeground|GCBackground,&values, GCForeground|GCBackground|GCClipXOrigin|GCClipYOrigin|GCPlaneMask, GCLineWidth|GCLineStyle|GCCapStyle|GCJoinStyle|GCGraphicsExposures| GCDashOffset|GCArcMode); } static void calc_preferred_size(Widget w,Dimension *width,Dimension *height, Widget in){ Dimension tab_height=0,tab_width=0,page_height=0,page_width=0; Dimension str_width,str_height; int i; Widget child; XtWidgetGeometry request,reply; for(i=0;itab_height) tab_height=str_height; } if(child==in){ if(WIDTH(child)>page_width) page_width=WIDTH(child); if(HEIGHT(child)>page_height) page_height=HEIGHT(child); } else { request.request_mode=(CWWidth | CWHeight); request.width=0; request.height=0; XtQueryGeometry(child,NULL,&reply); if(!(reply.request_mode & CWWidth)) reply.width=WIDTH(child); if(!(reply.request_mode & CWHeight)) reply.height=HEIGHT(child); if(reply.width>page_width) page_width=reply.width; if(reply.height>page_height) page_height=reply.height; } } if(SHOW_TABS(w)){ tab_height+=(Dimension)(SHADOW_THICKNESS(w)+TAB_MARGIN_HEIGHT(w)*2+ EHT(w)*2+LABEL_MARGIN_HEIGHT(w)*2+TAB_RAISE(w)); tab_width-=(Dimension)(TAB_SPACING(w)); } tab_width=Max(tab_width,page_width+INNER_MARGIN_WIDTH(w)*2+ SHADOW_THICKNESS(w)*2); *width=(Dimension)(tab_width+MARGIN_WIDTH(w)*2); *height=(Dimension)(page_height+SHADOW_THICKNESS(w)*2+tab_height+ INNER_MARGIN_HEIGHT(w)*2+MARGIN_HEIGHT(w)*2); } static void do_layout(Widget w,Widget instigator){ compute_tab_rects(w); configure_children(w,instigator); } static void compute_tab_rects(Widget w){ Position left_x; Dimension greater_height,str_width,str_height; Widget child=0,prev=0; int i; Dimension width, height; left_x=0; greater_height = 0; if(SHOW_TABS(w)){ TAB_RECT(DRAWING_AREA(w)).x=MARGIN_WIDTH(w); TAB_RECT(DRAWING_AREA(w)).y=MARGIN_HEIGHT(w); TAB_RECT(DRAWING_AREA(w)).width=i=WIDTH(w)-MARGIN_WIDTH(w)*2; if(i<=0) TAB_RECT(DRAWING_AREA(w)).width=1; for(i=0;igreater_height)greater_height = height; TAB_RECT(child).x=left_x; TAB_RECT(child).y=0; TAB_RECT(child).width = width; if(!prev || TAB_RECT(prev).x+TAB_RECT(prev).width<=TAB_RECT(child).x){ TAB_CLIP(child).x=TAB_RECT(child).x; TAB_CLIP(child).y=TAB_RECT(child).y; TAB_CLIP(child).width=TAB_RECT(child).width; } else { TAB_CLIP(child).x=TAB_RECT(prev).x+TAB_RECT(prev).width; TAB_CLIP(child).y=TAB_RECT(child).y; TAB_CLIP(child).width= TAB_RECT(child).x+TAB_RECT(child).width-TAB_CLIP(child).x; } if(TAB_RECT(child).x+TAB_RECT(child).width > TAB_RECT(DRAWING_AREA(w)).width){ TAB_VISIBLE(child)=FALSE; } else { TAB_VISIBLE(child)=TRUE; } left_x+=(Dimension)(width+TAB_SPACING(w)-SHADOW_THICKNESS(w)); prev=child; } for(i=0;ix; Y(child)=rect->y; WIDTH(child)=rect->width; HEIGHT(child)=rect->height; BORDER(child)=0; } else { _XmConfigureObject(child,rect->x,rect->y,rect->width,rect->height,0); } } else { if(child==CURRENT_WIDGET(w)){ if(child==instigator){ X(child)=CHILD_X(w); Y(child)=CHILD_Y(w); WIDTH(child)=CHILD_WIDTH(w); HEIGHT(child)=CHILD_HEIGHT(w); BORDER(child)=0; } else { _XmConfigureObject(child,CHILD_X(w),CHILD_Y(w), CHILD_WIDTH(w),CHILD_HEIGHT(w),0); } } else { if(child==instigator){ X(child)=X(w)-CHILD_WIDTH(w); Y(child)=Y(w)-CHILD_HEIGHT(w); WIDTH(child)=CHILD_WIDTH(w); HEIGHT(child)=CHILD_HEIGHT(w); BORDER(child)=0; } else { _XmConfigureObject(child,X(w)-CHILD_WIDTH(w),Y(w)-CHILD_HEIGHT(w), CHILD_WIDTH(w),CHILD_HEIGHT(w),0); } } } } } static void draw_shadows(Widget w,Region region){ XRectangle *rect; XRectangle cr; #define OPTIMIZE_SHADOW_DRAWING 0 #if OPTIMIZE_SHADOW_DRAWING Boolean shadow_intersect; XRectangle r[4]; #endif if(!XtIsRealized(w)) return; if(region) XClipBox(region,&cr); else { cr.x=0;cr.y=0;cr.width=WIDTH(w);cr.height=HEIGHT(w);} XClearArea(XtDisplay(w),XtWindow(w),cr.x,cr.y,cr.width,cr.height,FALSE); #if OPTIMIZE_SHADOW_DRAWING /* left */ r[0].x=MARGIN_WIDTH(w); r[0].y=MARGIN_HEIGHT(w)+TAB_HEIGHT(w); r[0].width=SHADOW_THICKNESS(w); r[0].height=HEIGHT(w)-MARGIN_HEIGHT(w)*2-TAB_HEIGHT(w); /* bottom */ r[1].x=r[0].x; r[1].y=r[0].y+r[0].height-r[0].width; r[1].width=WIDTH(w)-MARGIN_WIDTH(w)*2; r[1].height=r[0].width; /* top */ r[2].x=r[1].x; r[2].y=r[0].y; r[2].width=r[1].width; r[2].height=r[1].height; /* right */ r[3].x=r[0].x+r[1].width-r[0].width; r[3].y=r[0].y; r[3].width=r[0].width; r[3].height=r[0].height; shadow_intersect=axyRectanglesIntersect(&r[0],&cr) | axyRectanglesIntersect(&r[1],&cr) | axyRectanglesIntersect(&r[2],&cr) | axyRectanglesIntersect(&r[3],&cr); if(shadow_intersect) { #endif XSetClipRectangles(XtDisplay(w),TOP_SHADOW_GC(w),0,0,&cr,1,Unsorted); XSetClipRectangles(XtDisplay(w),BOTTOM_SHADOW_GC(w),0,0,&cr,1,Unsorted); _XmDrawShadows(XtDisplay(w),XtWindow(w), TOP_SHADOW_GC(w),BOTTOM_SHADOW_GC(w), MARGIN_WIDTH(w),MARGIN_HEIGHT(w)+TAB_HEIGHT(w), WIDTH(w)-MARGIN_WIDTH(w)*2,HEIGHT(w)-MARGIN_HEIGHT(w)*2-TAB_HEIGHT(w), SHADOW_THICKNESS(w),XmSHADOW_OUT); XSetClipMask(XtDisplay(w),TOP_SHADOW_GC(w),None); XSetClipMask(XtDisplay(w),BOTTOM_SHADOW_GC(w),None); #if OPTIMIZE_SHADOW_DRAWING } #endif rect=&TAB_RECT(CURRENT_WIDGET(w)); if(SHOW_TABS(w) && (int)rect->x+(int)rect->width<=(int)WIDTH(w)-(int)MARGIN_WIDTH(w)*2){ #if OPTIMIZE_SHADOW_DRAWING if(shadow_intersect) { #endif XClearArea(XtDisplay(w),XtWindow(w), rect->x+SHADOW_THICKNESS(w)+MARGIN_WIDTH(w), MARGIN_HEIGHT(w)+TAB_HEIGHT(w), rect->width-SHADOW_THICKNESS(w)*2,SHADOW_THICKNESS(w),FALSE); #if OPTIMIZE_SHADOW_DRAWING } #endif } } static void draw_da_tabs(Widget da,Window window,XEvent *event){ Widget w=XtParent(da); XExposeEvent *e=(XExposeEvent*)event; int i,tmp; XRectangle *tab_rect,*tab_clip,tab_clip_modified; XRectangle cr,clip; if(window==0) return; if(e==NULL){ cr.x=0;cr.y=0;cr.width=WIDTH(da);cr.height=HEIGHT(da); } else { cr.x=e->x;cr.y=e->y;cr.width=e->width;cr.height=e->height; } XClearArea(XtDisplay((Widget)w),window, cr.x,cr.y,cr.width,cr.height,FALSE); if(SHOW_TABS(w)){ for(i=NUM_CHILDREN(w)-1;i>=0;i--){ if(CHILD(w,i)==da || !XtIsManaged(CHILD(w,i))) continue; if(CURRENT_WIDGET(w)==CHILD(w,i)) continue; if(!TAB_VISIBLE_I(w,i)) { continue; } tab_rect=&TAB_RECT_I(w,i); tab_clip=&TAB_CLIP_I(w,i); if(TAB_VISIBLE(CURRENT_WIDGET(w)) && PAGE_NUM(CURRENT_WIDGET(w))==PAGE_NUM_I(w,i)+1){ tab_clip_modified.x=tab_clip->x; tab_clip_modified.y=tab_clip->y; tab_clip_modified.width=tmp= (int)TAB_RECT(CURRENT_WIDGET(w)).x-(int)tab_clip->x; if(tmp<0) tab_clip_modified.width=0; tab_clip_modified.height=tab_clip->height; } else { tab_clip_modified.x=tab_clip->x; tab_clip_modified.y=tab_clip->y; tab_clip_modified.width=tab_clip->width; tab_clip_modified.height=tab_clip->height; } axyRectanglesIntersection(&cr,&tab_clip_modified,&clip); if(axyRectangleIsEmpty(&clip)) { continue; } XSetClipRectangles(XtDisplay((Widget)w),ARM_GC(w),0,0,&clip,1,Unsorted); XFillRectangle(XtDisplay((Widget)w),window,ARM_GC(w), tab_rect->x+SHADOW_THICKNESS(w), tab_rect->y+TAB_RAISE(w)+SHADOW_THICKNESS(w), tab_rect->width-SHADOW_THICKNESS(w)*2, tab_rect->height-TAB_RAISE(w)-SHADOW_THICKNESS(w)); XSetClipMask(XtDisplay((Widget)w),ARM_GC(w),None); XSetClipRectangles(XtDisplay(w),NORMAL_GC(w),0,0,&clip,1,Unsorted); XmStringDraw(XtDisplay(w),window,FONT_LIST(w), TAB_LABEL_I(w,i),NORMAL_GC(w), tab_rect->x+SHADOW_THICKNESS(w)+TAB_MARGIN_WIDTH(w)+ EHT(w)+LABEL_MARGIN_WIDTH(w), tab_rect->y+SHADOW_THICKNESS(w)+TAB_MARGIN_HEIGHT(w)+ EHT(w)+LABEL_MARGIN_HEIGHT(w)+(Dimension)TAB_RAISE(w), tab_rect->width-SHADOW_THICKNESS(w)*2-TAB_MARGIN_WIDTH(w)*2- EHT(w)*2-LABEL_MARGIN_WIDTH(w)*2, XmALIGNMENT_CENTER,STRING_DIR(w),&clip); XSetClipMask(XtDisplay(w),NORMAL_GC(w),None); XSetClipRectangles(XtDisplay(w),TOP_SHADOW_GC(w),0,0,&clip,1,Unsorted); XSetClipRectangles(XtDisplay(w),BOTTOM_SHADOW_GC(w),0,0,&clip,1,Unsorted); _XmDrawShadows(XtDisplay(w),window, TOP_SHADOW_GC(w),BOTTOM_SHADOW_GC(w), tab_rect->x,tab_rect->y+(Dimension)TAB_RAISE(w), tab_rect->width,tab_rect->height+SHADOW_THICKNESS(w)- (Dimension)TAB_RAISE(w), SHADOW_THICKNESS(w),XmSHADOW_OUT); XSetClipMask(XtDisplay(w),TOP_SHADOW_GC(w),None); XSetClipMask(XtDisplay(w),BOTTOM_SHADOW_GC(w),None); } tab_rect=&TAB_RECT(CURRENT_WIDGET(w)); axyRectanglesIntersection(&cr,tab_rect,&clip); if(TAB_VISIBLE(CURRENT_WIDGET(w)) && !axyRectangleIsEmpty(&clip)){ XClearArea(XtDisplay(w),window,clip.x,clip.y, clip.width,clip.height,FALSE); XSetClipRectangles(XtDisplay(w),NORMAL_GC(w),0,0,&clip,1,Unsorted); XmStringDraw(XtDisplay(w),window,FONT_LIST(w), TAB_LABEL(CURRENT_WIDGET(w)),NORMAL_GC(w), tab_rect->x+SHADOW_THICKNESS(w)+TAB_MARGIN_WIDTH(w)+ EHT(w)+LABEL_MARGIN_WIDTH(w), tab_rect->y+SHADOW_THICKNESS(w)+TAB_MARGIN_HEIGHT(w)+ EHT(w)+LABEL_MARGIN_HEIGHT(w)+ (Dimension)(TAB_RAISE(w)/2), tab_rect->width-SHADOW_THICKNESS(w)*2-TAB_MARGIN_WIDTH(w)*2- EHT(w)*2-LABEL_MARGIN_WIDTH(w)*2, XmALIGNMENT_CENTER,STRING_DIR(w),&clip); XSetClipMask(XtDisplay(w),NORMAL_GC(w),None); XSetClipRectangles(XtDisplay(w),TOP_SHADOW_GC(w),0,0,&clip,1,Unsorted); XSetClipRectangles(XtDisplay(w),BOTTOM_SHADOW_GC(w),0,0,&clip,1,Unsorted); _XmDrawShadows(XtDisplay(w),window, TOP_SHADOW_GC(w),BOTTOM_SHADOW_GC(w), tab_rect->x, tab_rect->y, tab_rect->width,tab_rect->height+SHADOW_THICKNESS(w), SHADOW_THICKNESS(w),XmSHADOW_OUT); XSetClipMask(XtDisplay(w),TOP_SHADOW_GC(w),None); XSetClipMask(XtDisplay(w),BOTTOM_SHADOW_GC(w),None); } if(HIGHLIGHT_DRAWN(w)) draw_da_highlight(da); } } static void draw_da_highlight(Widget da){ Widget w=XtParent(da); XRectangle *rect,*clip,clip_modified; GC gc=HIGHLIGHT_DRAWN(w)?HIGHLIGHT_GC(w): (HIGHLIGHTED_TAB(w)==CURRENT_WIDGET(w)?BACKGROUND_GC(w):ARM_GC(w)); int tmp; if(HIGHLIGHT_THICKNESS(w)==0) return; if(!XtIsRealized(da) || !HIGHLIGHTED_TAB(w) || !TAB_VISIBLE(HIGHLIGHTED_TAB(w))) return; rect=&TAB_RECT(HIGHLIGHTED_TAB(w)); clip=&TAB_CLIP(HIGHLIGHTED_TAB(w)); if(HIGHLIGHTED_TAB(w)!=CURRENT_WIDGET(w)){ if(TAB_VISIBLE(CURRENT_WIDGET(w)) && PAGE_NUM(CURRENT_WIDGET(w))==PAGE_NUM(HIGHLIGHTED_TAB(w))+1){ clip_modified.x=clip->x; clip_modified.y=clip->y; clip_modified.width=tmp= (int)TAB_RECT(CURRENT_WIDGET(w)).x-(int)clip->x; if(tmp<0) clip_modified.width=0; clip_modified.height=clip->height; } else { clip_modified.x=clip->x; clip_modified.y=clip->y; clip_modified.width=clip->width; clip_modified.height=clip->height; } XSetClipRectangles(XtDisplay(w),gc,0,0,&clip_modified,1,Unsorted); } _XmDrawSimpleHighlight(XtDisplay(da),XtWindow(da),gc, rect->x+SHADOW_THICKNESS(w)+TAB_MARGIN_WIDTH(w), rect->y+SHADOW_THICKNESS(w)+TAB_MARGIN_HEIGHT(w)+ (HIGHLIGHTED_TAB(w)==CURRENT_WIDGET(w)? (Dimension)(TAB_RAISE(w)/2):(Dimension)TAB_RAISE(w)), rect->width-SHADOW_THICKNESS(w)*2-TAB_MARGIN_WIDTH(w)*2, rect->height-SHADOW_THICKNESS(w)-TAB_MARGIN_HEIGHT(w)*2-TAB_RAISE(w), HIGHLIGHT_THICKNESS(w)); XSetClipMask(XtDisplay(w),gc,None); } static Widget search_da_tab(Widget da, XEvent *event){ Widget w=XtParent(da); int i; XRectangle *rect; Widget child; Position mx,my; if(!SHOW_TABS(w)) return 0; mx=event->xbutton.x; my=event->xbutton.y; for(i=NUM_CHILDREN(w)-1;i>=0;i--){ child=CHILD(w,i); if(child==da) continue; if(!XtIsManaged(child)) continue; if(!TAB_VISIBLE(child)) continue; if(child==CURRENT_WIDGET(w)) { rect=&TAB_RECT(child); if(mx>=rect->x && mxx+rect->width) return child; } else { rect=&TAB_CLIP(child); if(mx>=rect->x && mxx+rect->width){ if(my<=TAB_RAISE(w)) return 0; else return child; } } } return 0; } static void expose_da_cb(Widget da,XtPointer w,XtPointer call){ XmDrawingAreaCallbackStruct *cbs=(XmDrawingAreaCallbackStruct*)call; if(cbs->window==0) return; draw_da_tabs(da,cbs->window,cbs->event); } static void change_tab(Widget w,Widget child){ _XmConfigureObject(CURRENT_WIDGET(w),X(w)-CHILD_WIDTH(w),Y(w)-CHILD_HEIGHT(w), CHILD_WIDTH(w),CHILD_HEIGHT(w),0); if(HIGHLIGHTED_TAB(w) && HIGHLIGHT_DRAWN(w)){ HIGHLIGHT_DRAWN(w)=FALSE; draw_da_highlight(DRAWING_AREA(w)); HIGHLIGHT_DRAWN(w)=TRUE; } CURRENT_PAGE(w)=PAGE_NUM(child); CURRENT_WIDGET(w)=child; _XmConfigureObject(CURRENT_WIDGET(w),CHILD_X(w),CHILD_Y(w), CHILD_WIDTH(w),CHILD_HEIGHT(w),0); HIGHLIGHTED_TAB(w)=child; HIGHLIGHT_DRAWN(w)=TRUE; draw_shadows(w,NULL); draw_da_tabs(DRAWING_AREA(w),XtWindow(DRAWING_AREA(w)),NULL); }