/* * align.c * * The alignment dialogue box * * © 1994-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Glass. * * Glass is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Glass is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Glass. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*----- Header files ------------------------------------------------------*/ /* * ANSI standard headers */ #include #include /* * Steel headers */ #define _STDAPP #include "steel/Steel.h" /* * Glass headers */ #include "gIcons.h" #include "glass.h" #include "window.h" #include "align.h" #include "tfile.h" /*----- Type definitions --------------------------------------------------*/ typedef struct { wimp_box box; int i; } align__iconstr; typedef enum { align__MIN, align__CENTRE, align__MAX } align__order; /*----- Static global variables -------------------------------------------*/ static dbox align__dbox; static align__order align__sortOrder; /*----- Support routines --------------------------------------------------*/ /* * int align__horizCompare(const void *a,const void *b) * * Use * Compares two icons for horizontal alignment. Used as a compare for * qsort. */ static int align__horizCompare(const void *a,const void *b) { const align__iconstr *x=a; const align__iconstr *y=b; int result=0; switch (align__sortOrder) { case align__MIN: result=x->box.x0-y->box.x0; break; case align__MAX: result=x->box.x1-y->box.x1; break; case align__CENTRE: result=x->box.x1+x->box.x0-y->box.x0-y->box.x1; break; default: werr(TRUE,msgs_lookup("alBATH")); break; } return (result); } /* * int align__vertCompare(const void *a,const void *b) * * Use * Compares two icons for vertical alignment. Used as a compare for * qsort. */ static int align__vertCompare(const void *a,const void *b) { const align__iconstr *x=a; const align__iconstr *y=b; int result=0; switch (align__sortOrder) { case align__MIN: result=x->box.y0-y->box.y0; break; case align__MAX: result=x->box.y1-y->box.y1; break; case align__CENTRE: result=x->box.y1+x->box.y0-y->box.y0-y->box.y1; break; default: werr(TRUE,msgs_lookup("alBATV")); break; } return (result); } /* * void align__doAlign(void) * * Use * Does an align on the currently selected icons, wherever they may be. * The settings are read from the dialogue box, and processed. */ static void align__doAlign(void) { align__iconstr *a; /* Array of icons to align */ glass_windPointer *w=window_selectionOwner(); /* Window containing icons */ wimp_box bound; /* Bounding box of the selection */ int width=0; /* Total width of all the icons */ int height=0; /* Total height of all the icons */ int xcont=-1; /* Index/icon of horizontal container */ int ycont=-1; /* Index/icon of vertical container */ int num; /* Number of selected icons */ /* --- Loop variables --- */ int i; int j; /* --- Ensure that we have something to do --- */ if (!w) return; if (!w->selno) return; num=w->selno; /* --- Put the icons into an array for sorting etc. --- * * * We also keep track of the bounding box of the selected icons, their * total width and their total height, and which, if any, are containers. */ { BOOL started=FALSE; /* --- Allocate memory for the array --- */ if (a=mem_alloc(num*sizeof(align__iconstr)),!a) { werr(FALSE,msgs_lookup("alNEM")); return; } j=0; for (i=0;idef->desc.w.nicons;i++) { if (w->def->i[i].selected) { a[j].i=i; window_boundingBox(w,i,&a[j].box); width+=a[j].box.x1-a[j].box.x0; height+=a[j].box.y1-a[j].box.y0; if (!started) { bound=a[j].box; started=TRUE; xcont=ycont=j; } else { if (bound.x0>a[j].box.x0) { bound.x0=a[j].box.x0; if (bound.x1a[j].box.y0) { bound.y0=a[j].box.y0; if (bound.y1def->desc.w.scx+ (w->def->desc.w.box.x1-w->def->desc.w.box.x0)/2; } for (i=0;iselno,sizeof(align__iconstr),align__horizCompare); if (dbox_selecticon(align__dbox,glass_AHLEFT,dbox_READSTATE)) { int space=a[num-1].box.x0-a[0].box.x0; int anchor=a[0].box.x0; int thisBit; for (i=0;idef->desc.w.box.x1-w->def->desc.w.box.x0-width; int icwidth; int thisBit; int anchor=w->def->desc.w.scx; /* This anchor also moves */ for (i=0;idef->desc.w.scy- (w->def->desc.w.box.y1-w->def->desc.w.box.y0)/2; } for (i=0;iselno,sizeof(align__iconstr),align__vertCompare); if (dbox_selecticon(align__dbox,glass_AVBOTTOM,dbox_READSTATE)) { int space=a[num-1].box.y0-a[0].box.y0; int anchor=a[0].box.y0; int thisBit; for (i=0;idef->desc.w.box.y1-w->def->desc.w.box.y0; int icheight; int thisBit; int anchor=w->def->desc.w.scy-space; /* This anchor also moves */ space-=height; for (i=0;it); for (i=0;iselno;i++) window_setBox(w,a[i].i,&a[i].box); mem_free(a); } /*----- Event handlers ----------------------------------------------------*/ /* * void align__dboxHandler(dbox d,dbox_field f,void *handle) * * Use * Handles events for the Alignment dialogue box. * * Parameters * dbox d == the dbox handle (align__dbox) * dbox_field f == what happened (usually a mouse click) * void *handle == a pointer (ignored) */ static void align__dboxHandler(dbox d,dbox_field f,void *handle) { BOOL shadeBox; unused(handle); switch (f) { case dbox_CLOSE: dbox_delete(d); align__dbox=0; break; case glass_AOK: dbox_clickicon(d,f); align__doAlign(); if (!dbox_wasAdjustClick()) dbox_hide(d); dbox_unclick(); if (!dbox_wasAdjustClick()) { dbox_delete(d); align__dbox=0; } break; case glass_ACANCEL: dbox_clickicon(d,f); dbox_hide(d); dbox_unclick(); dbox_delete(d); align__dbox=0; break; case glass_AHNONE: dbox_clickicon(d,f); dbox_shadeicon(d,glass_AHLEFT,TRUE); dbox_shadeicon(d,glass_AHRIGHT,TRUE); dbox_shadeicon(d,glass_AHCENTRE,TRUE); dbox_shadeicon(d,glass_AHWIDTH,TRUE); dbox_shadeicon(d,glass_AHBOUND,TRUE); dbox_shadeicon(d,glass_AHVISAREA,TRUE); dbox_shadeicon(d,glass_AHCONTAIN,TRUE); dbox_unclick(); break; case glass_AHALIGN: dbox_clickicon(d,f); dbox_shadeicon(d,glass_AHLEFT,FALSE); dbox_shadeicon(d,glass_AHRIGHT,FALSE); dbox_shadeicon(d,glass_AHCENTRE,FALSE); dbox_shadeicon(d,glass_AHWIDTH,TRUE); if (dbox_selecticon(d,glass_AHWIDTH,dbox_READSTATE)) { dbox_selecticon(d,glass_AHWIDTH,FALSE); dbox_selecticon(d,glass_AHCENTRE,TRUE); } shadeBox=!dbox_selecticon(d,glass_AHCENTRE,dbox_READSTATE); dbox_shadeicon(d,glass_AHBOUND,shadeBox); dbox_shadeicon(d,glass_AHVISAREA,shadeBox); dbox_shadeicon(d,glass_AHCONTAIN,TRUE); if (dbox_selecticon(d,glass_AHCONTAIN,dbox_READSTATE)) { dbox_selecticon(d,glass_AHCONTAIN,FALSE); dbox_selecticon(d,glass_AHBOUND,TRUE); } dbox_unclick(); break; case glass_AHDISTRIB: dbox_clickicon(d,f); dbox_shadeicon(d,glass_AHLEFT,FALSE); dbox_shadeicon(d,glass_AHRIGHT,FALSE); dbox_shadeicon(d,glass_AHCENTRE,FALSE); dbox_shadeicon(d,glass_AHWIDTH,FALSE); shadeBox=!dbox_selecticon(d,glass_AHWIDTH,dbox_READSTATE); dbox_shadeicon(d,glass_AHBOUND,shadeBox); dbox_shadeicon(d,glass_AHVISAREA,shadeBox); dbox_shadeicon(d,glass_AHCONTAIN,shadeBox); dbox_unclick(); break; case glass_AVNONE: dbox_clickicon(d,f); dbox_shadeicon(d,glass_AVTOP,TRUE); dbox_shadeicon(d,glass_AVBOTTOM,TRUE); dbox_shadeicon(d,glass_AVCENTRE,TRUE); dbox_shadeicon(d,glass_AVHEIGHT,TRUE); dbox_shadeicon(d,glass_AVBOUND,TRUE); dbox_shadeicon(d,glass_AVVISAREA,TRUE); dbox_shadeicon(d,glass_AVCONTAIN,TRUE); dbox_unclick(); break; case glass_AVALIGN: dbox_clickicon(d,f); dbox_shadeicon(d,glass_AVTOP,FALSE); dbox_shadeicon(d,glass_AVBOTTOM,FALSE); dbox_shadeicon(d,glass_AVCENTRE,FALSE); dbox_shadeicon(d,glass_AVHEIGHT,TRUE); if (dbox_selecticon(d,glass_AVHEIGHT,dbox_READSTATE)) { dbox_selecticon(d,glass_AVHEIGHT,FALSE); dbox_selecticon(d,glass_AVCENTRE,TRUE); } shadeBox=!dbox_selecticon(d,glass_AVCENTRE,dbox_READSTATE); dbox_shadeicon(d,glass_AVBOUND,shadeBox); dbox_shadeicon(d,glass_AVVISAREA,shadeBox); dbox_shadeicon(d,glass_AVCONTAIN,TRUE); if (dbox_selecticon(d,glass_AVCONTAIN,dbox_READSTATE)) { dbox_selecticon(d,glass_AVCONTAIN,FALSE); dbox_selecticon(d,glass_AVBOUND,TRUE); } dbox_unclick(); break; case glass_AVDISTRIB: dbox_clickicon(d,f); dbox_shadeicon(d,glass_AVTOP,FALSE); dbox_shadeicon(d,glass_AVBOTTOM,FALSE); dbox_shadeicon(d,glass_AVCENTRE,FALSE); dbox_shadeicon(d,glass_AVHEIGHT,FALSE); shadeBox=!dbox_selecticon(d,glass_AVHEIGHT,dbox_READSTATE); dbox_shadeicon(d,glass_AVBOUND,shadeBox); dbox_shadeicon(d,glass_AVVISAREA,shadeBox); dbox_shadeicon(d,glass_AVCONTAIN,shadeBox); dbox_unclick(); break; case glass_AHLEFT: case glass_AHRIGHT: case glass_AHCENTRE: case glass_AHWIDTH: case glass_AHBOUND: case glass_AHVISAREA: case glass_AHCONTAIN: dbox_clickicon(d,f); if (dbox_selecticon(d,glass_AHALIGN,dbox_READSTATE)) shadeBox=!dbox_selecticon(d,glass_AHCENTRE,dbox_READSTATE); else shadeBox=!dbox_selecticon(d,glass_AHWIDTH,dbox_READSTATE); dbox_shadeicon(d,glass_AHBOUND,shadeBox); dbox_shadeicon(d,glass_AHVISAREA,shadeBox); dbox_shadeicon(d, glass_AHCONTAIN, !dbox_selecticon(d,glass_AHWIDTH,dbox_READSTATE)); dbox_unclick(); break; case glass_AVTOP: case glass_AVBOTTOM: case glass_AVCENTRE: case glass_AVHEIGHT: case glass_AVBOUND: case glass_AVVISAREA: case glass_AVCONTAIN: dbox_clickicon(d,f); if (dbox_selecticon(d,glass_AVALIGN,dbox_READSTATE)) shadeBox=!dbox_selecticon(d,glass_AVCENTRE,dbox_READSTATE); else shadeBox=!dbox_selecticon(d,glass_AVHEIGHT,dbox_READSTATE); dbox_shadeicon(d,glass_AVBOUND,shadeBox); dbox_shadeicon(d,glass_AVVISAREA,shadeBox); dbox_shadeicon(d, glass_AVCONTAIN, !dbox_selecticon(d,glass_AVHEIGHT,dbox_READSTATE)); dbox_unclick(); break; } } /*----- External routines -------------------------------------------------*/ /* * void align(void) * * Use * Opens the align dialogue box. There can only be one selection, ergo * there can only be one align box. */ void align(void) { if (!align__dbox) { align__dbox=dbox_create("align"); if (!align__dbox) return; dbox_shadeicon(align__dbox,glass_AHLEFT,TRUE); dbox_shadeicon(align__dbox,glass_AHRIGHT,TRUE); dbox_shadeicon(align__dbox,glass_AHCENTRE,TRUE); dbox_shadeicon(align__dbox,glass_AHWIDTH,TRUE); dbox_shadeicon(align__dbox,glass_AHBOUND,TRUE); dbox_shadeicon(align__dbox,glass_AHVISAREA,TRUE); dbox_shadeicon(align__dbox,glass_AHCONTAIN,TRUE); dbox_shadeicon(align__dbox,glass_AVTOP,TRUE); dbox_shadeicon(align__dbox,glass_AVBOTTOM,TRUE); dbox_shadeicon(align__dbox,glass_AVCENTRE,TRUE); dbox_shadeicon(align__dbox,glass_AVHEIGHT,TRUE); dbox_shadeicon(align__dbox,glass_AVBOUND,TRUE); dbox_shadeicon(align__dbox,glass_AVVISAREA,TRUE); dbox_shadeicon(align__dbox,glass_AVCONTAIN,TRUE); dbox_eventHandler(align__dbox,align__dboxHandler,0); } dbox_display(align__dbox,dbox_STATIC_LASTPOS); }