123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850 |
- /* GCSx
- ** FRAME.CPP
- **
- ** Frame windows
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program 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 of the License, or
- ** (at your option) any later version.
- **
- ** This program 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 this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- // @TODO: several [pos] loops that refer to clientArea could be iterator-based now
- #include "all.h"
- #define DEBUG_INFO_CLIENTS \
- debugWrite("Clients %s: (0-%d)", debugDump(), clientArea.size() - 1); \
- for (int debug_pos = 0; debug_pos < (int)clientArea.size(); ++debug_pos) { \
- if (clientArea[debug_pos].window) { \
- debugWrite(" %d: %d,%d (%d x %d, show %d x %d) %s", debug_pos, \
- clientArea[debug_pos].x, clientArea[debug_pos].y, \
- clientArea[debug_pos].width, clientArea[debug_pos].height, \
- clientArea[debug_pos].widthShown, clientArea[debug_pos].heightShown, \
- clientArea[debug_pos].window->debugDump()); \
- } \
- }
- int FrameWindow::cascadeStep = -1;
- int FrameWindow::minimumPanelSize = 0;
- const char* FrameWindow::wtButtonAll = "hgf";
- const char* FrameWindow::wtButtonNoResize = "hf";
- const string FrameWindow::wtButtonClose("f");
- const string FrameWindow::wtButtonUp("m");
- const string FrameWindow::wtButtonDown("n");
- const string FrameWindow::wtButtonLeft("l");
- const string FrameWindow::wtButtonRight("k");
- FrameWindow::FrameWindow(const string& title, ResizableType isResizable, FrameType type, Window* client, TitlebarType hasTitlebarType, int hasOuterBorder, FrameWindow* isFramePanel) : Window(), titlebar(title), clientArea() { start_func
- assert(type != FRAMETYPE_NOCHANGE);
- assert(hasTitlebarType != TITLEBAR_NOCHANGE);
- assert(isResizable != RESIZING_NOCHANGE);
- assert(hasOuterBorder != -1);
- minimumPanelSize = fontHeight(FONT_TOOLTITLEBAR) + FRAME_TOOLTITLETOPPAD + FRAME_TOOLTITLEBOTTOMPAD;
-
- // This is the first place we might error- so far, nothing needs undoing until client is pushed
- ClientArea ca = { client, -1, -1, -1, -1, -1, -1, CLIENT_PRIMARY };
- clientArea.push_back(ca);
-
- state = FRAME_STATE_NORMAL;
- dragMode = FRAME_DRAG_NONE;
- deleteMe = 1;
- haveFocus = subFocus = 0;
- scrollX = scrollY = 0;
- scrollRepeatTicks = scrollRepeatDelay = 0;
- hScrollLine = vScrollLine = fontHeight();
- whyDirty = FRAME_DIRTY_ALL;
- floatTarget = 0;
- autoCenterScroll = 0;
- reserve[0] = reserve[1] = reserve[2] = reserve[3] = 0;
-
- // (we set outerBorder only because setFeatures looks at it)
- outerBorder = 0;
- framePanel = NULL;
-
- setFeatures(isResizable, type, hasTitlebarType, hasOuterBorder, isFramePanel, 1);
-
- // Initial size
- if (client) {
- client->setParent(this);
- width = client->getWidth();
- if (width < titlebarButtonTotalWidth) width = titlebarButtonTotalWidth;
- height = client->getHeight();
- if (height < 0) height = 0;
- width += outerBorder * 2 + FRAME_INNERBORDER * 2;
- height += outerBorder * 2 + FRAME_INNERBORDER * 2 + titlebarHeight;
- }
- else {
- width = outerBorder * 2 + 2 + titlebarButtonTotalWidth;
- height = titlebarHeight + 2 * outerBorder;
- }
- }
- void FrameWindow::setFeatures(ResizableType isResizable, FrameType type, TitlebarType hasTitlebarType, int hasOuterBorder, FrameWindow* isFramePanel, int skipResizing) { start_func
- int oldOuterBorder = outerBorder;
- if (hasTitlebarType != TITLEBAR_NOCHANGE) titlebarType = hasTitlebarType;
- if (isFramePanel != NULL) framePanel = isFramePanel;
- if (hasOuterBorder != -1) outerBorder = hasOuterBorder ? FRAME_OUTERBORDER : 0;
- if (isResizable != RESIZING_NOCHANGE) resizable = isResizable;
- if (type != FRAMETYPE_NOCHANGE) frameType = type;
- // Recalculate our constants- small chance of VideoException in this section
- titlebarX = outerBorder + FRAME_INNERBORDER - FRAME_BEVELTHICKNESS;
- titlebarY = outerBorder;
- titlebarHeight = (titlebarType == TITLEBAR_TOOL ? FRAME_TOOLTITLETOPPAD + FRAME_TOOLTITLEBOTTOMPAD : FRAME_TITLETOPPAD + FRAME_TITLEBOTTOMPAD) + fontHeight(titlebarType == TITLEBAR_TOOL ? FONT_TOOLTITLEBAR : FONT_TITLEBAR);
- titlebarButtonY = titlebarY + 1;
- titlebarButtonSize = titlebarHeight - 2;
- titlebarButtonXPad = (titlebarButtonSize - fontWidth(wtButtonClose, titlebarType == TITLEBAR_TOOL ? FONT_TOOLTITLEBARWIDGET : FONT_TITLEBARWIDGET)) / 2;
- scrollbarButtonSize = fontHeight(FONT_WIDGET) + 2;
- scrollbarButtonXPad = (scrollbarButtonSize - fontWidth(wtButtonClose, FONT_WIDGET)) / 2;
- if (titlebarType == TITLEBAR_OFF) {
- titlebarHeight = 0;
- titlebarButtons[0] = 0;
- }
- else if ((resizable) && (!framePanel)) {
- strcpy(titlebarButtons, wtButtonAll);
- }
- else {
- strcpy(titlebarButtons, wtButtonNoResize);
- }
- if (state == FRAME_STATE_MINIMIZED) {
- char* button = strchr(titlebarButtons, 'h');
- if (button) *button = 'j';
- }
- if (state == FRAME_STATE_MAXIMIZED) {
- char* button = strchr(titlebarButtons, 'g');
- if (button) *button = 'j';
- }
- titlebarButtonTotalWidth = titlebarButtonSize * strlen(titlebarButtons);
- // Resize to fit new outer border and minimum titlebar width
- if (!skipResizing) {
- int newWidth = width + outerBorder * 2 - oldOuterBorder * 2;
- int newHeight = height + outerBorder * 2 - oldOuterBorder * 2;
- if (newWidth < outerBorder * 2 + 2 + titlebarButtonTotalWidth) newWidth = outerBorder * 2 + 2 + titlebarButtonTotalWidth;
- int newX = x;
- int newY = y;
- confineSize(newX, newY, newWidth, newHeight);
- move(newX, newY);
- resize(newWidth, newHeight);
- }
- }
- FrameWindow* FrameWindow::getFramePanel() { start_func
- return framePanel;
- }
-
- void FrameWindow::requestViewSize(int requestWidth, int requestHeight) { start_func
- if (state != FRAME_STATE_MAXIMIZED) {
- requestWidth += width - clientArea[0].width;
- requestHeight += height - clientArea[0].height;
-
- if (width > requestWidth) requestWidth = width;
- if (height > requestHeight) requestHeight = height;
-
- int newX = x;
- int newY = y;
- confineSize(newX, newY, requestWidth, requestHeight);
- move(newX, newY);
- resize(requestWidth, requestHeight);
- }
- }
- void FrameWindow::dropClients() { start_func
- vector<ClientArea>::iterator end = clientArea.end();
- for (vector<ClientArea>::iterator pos = clientArea.begin(); pos != end; ++pos) {
- if ((*pos).window) {
- (*pos).window->setParent(NULL);
- (*pos).window = NULL;
- }
- }
- }
- // Determines size of reserves based on existing window size, then relocates
- // all tool windows and central client window
- void FrameWindow::reorganizeReserves() { start_func
- int max = clientArea.size();
- int countPanel[4];
-
- // Determine max sizes of all items
- for (int spot = CLIENT_RIGHT; spot <= CLIENT_BOTTOM; ++spot) {
- reserve[spot] = 0;
- countPanel[spot] = 0;
- for (int pos = 1; pos < max; ++pos) {
- if (clientArea[pos].window) {
- // Pull size from window itself?
- if (clientArea[pos].width < 0) clientArea[pos].width = clientArea[pos].window->getWidth();
- if (clientArea[pos].height < 0) clientArea[pos].height = clientArea[pos].window->getHeight();
- // (while we're here, unhide everything for now)
- clientArea[pos].position = clientArea[pos].position & ~CLIENT_HIDDEN;
- if (clientArea[pos].position == spot) {
- ++countPanel[spot];
- if (spot & CLIENT_TOPBOTTOM) {
- if (clientArea[pos].height > reserve[spot]) {
- reserve[spot] = clientArea[pos].height;
- }
- }
- else {
- if (clientArea[pos].width > reserve[spot]) {
- reserve[spot] = clientArea[pos].width;
- }
- }
- }
- }
- }
-
- // Add in gutter if needed
- if (reserve[spot]) {
- reserve[spot] += FRAME_CLIENTPAD;
- }
- }
-
- // Start with entire area dedicated to client area INCLUDING inner border
- int mainWidth = width - (outerBorder * 2);
- int mainHeight = height - (outerBorder * 2 + titlebarHeight);
- int mainX = outerBorder;
- int mainY = titlebarY + titlebarHeight;
-
- // Add in each area that exists, as long as client area has space to "give"
- // If not, "hide" area
- // Add in top?
- if ((reserve[CLIENT_TOP]) && (mainWidth > 0) && (mainHeight > 0)) {
- if (mainHeight < reserve[CLIENT_TOP]) {
- reserve[CLIENT_TOP] = mainHeight;
- }
- mainY += reserve[CLIENT_TOP];
- mainHeight -= reserve[CLIENT_TOP];
- reserve[CLIENT_TOP] -= FRAME_CLIENTPAD;
- }
- else {
- reserve[CLIENT_TOP] = 0;
- }
-
- // Bottom?
- if ((reserve[CLIENT_BOTTOM]) && (mainWidth > 0) && (mainHeight > 0)) {
- if (mainHeight < reserve[CLIENT_BOTTOM]) {
- reserve[CLIENT_BOTTOM] = mainHeight;
- }
- mainHeight -= reserve[CLIENT_BOTTOM];
- reserve[CLIENT_BOTTOM] -= FRAME_CLIENTPAD;
- }
- else {
- reserve[CLIENT_BOTTOM] = 0;
- }
- // Left?
- if ((reserve[CLIENT_LEFT]) && (mainWidth > 0) && (mainHeight > 0)) {
- if (mainWidth < reserve[CLIENT_LEFT]) {
- reserve[CLIENT_LEFT] = mainWidth;
- }
- mainX += reserve[CLIENT_LEFT];
- mainWidth -= reserve[CLIENT_LEFT];
- reserve[CLIENT_LEFT] -= FRAME_CLIENTPAD;
- }
- else {
- reserve[CLIENT_LEFT] = 0;
- }
- // Right?
- if ((reserve[CLIENT_RIGHT]) && (mainWidth > 0) && (mainHeight > 0)) {
- if (mainWidth < reserve[CLIENT_RIGHT]) {
- reserve[CLIENT_RIGHT] = mainWidth;
- }
- mainWidth -= reserve[CLIENT_RIGHT];
- reserve[CLIENT_RIGHT] -= FRAME_CLIENTPAD;
- }
- else {
- reserve[CLIENT_RIGHT] = 0;
- }
-
- // Loop through all areas again, placing in proper positions or hiding as needed
- for (int spot = CLIENT_RIGHT; spot <= CLIENT_BOTTOM; ++spot) {
- int nextCoord = 0;
- int lastDid = 0;
- // Minimum size for all panels combined (reduces as we proceed)
- int minSizeForAll = (minimumPanelSize + FRAME_CLIENTPAD) * countPanel[spot];
- for (int pos = 1; pos < max; ++pos) {
- if ((clientArea[pos].position == spot) && (clientArea[pos].window)) {
- // Hiding entire side?
- if (reserve[spot] <= 0) {
- clientArea[pos].position |= CLIENT_HIDDEN;
- }
- else {
- // Account for our share of the minimum size
- minSizeForAll -= minimumPanelSize + FRAME_CLIENTPAD;
-
- // Assume we get entire desired area for now
- clientArea[pos].widthShown = clientArea[pos].width;
- clientArea[pos].heightShown = clientArea[pos].height;
-
- // Place in next position
- if (spot & CLIENT_TOPBOTTOM) {
- // Horizontal position
- clientArea[pos].x = nextCoord + outerBorder;
- // Clip width? (accounting for min size of future panels)
- if (clientArea[pos].x + clientArea[pos].widthShown > width - outerBorder - minSizeForAll) {
- clientArea[pos].widthShown = width - outerBorder - clientArea[pos].x - minSizeForAll;
- }
- // Minimum size
- if (clientArea[pos].widthShown < minimumPanelSize) {
- clientArea[pos].widthShown = minimumPanelSize;
- }
- // Clip width? (if minimum size is too much, not accounting for future panels)
- if (clientArea[pos].x + clientArea[pos].widthShown > width - outerBorder) {
- clientArea[pos].widthShown = width - outerBorder - clientArea[pos].x;
- }
- // Hidden?
- if (clientArea[pos].widthShown <= 0) {
- clientArea[pos].position |= CLIENT_HIDDEN;
- }
- // Next position
- nextCoord += clientArea[pos].widthShown + FRAME_CLIENTPAD;
- // Height is elementary
- clientArea[pos].heightShown = reserve[spot];
- // Vertical position is elementary
- if (spot == CLIENT_TOP) {
- clientArea[pos].y = titlebarY + titlebarHeight;
- }
- else {
- clientArea[pos].y = mainY + mainHeight + FRAME_CLIENTPAD;
- }
- }
- else {
- // Vertical position
- clientArea[pos].y = nextCoord + titlebarY + titlebarHeight + reserve[CLIENT_TOP];
- // Clip height? (accounting for min size of future panels)
- if (clientArea[pos].y + clientArea[pos].heightShown > mainY + mainHeight - minSizeForAll) {
- clientArea[pos].heightShown = mainY + mainHeight - clientArea[pos].y - minSizeForAll;
- }
- // Minimum size
- if (clientArea[pos].heightShown < minimumPanelSize) {
- clientArea[pos].heightShown = minimumPanelSize;
- }
- // Clip height? (if minimum size is too much, not accounting for future panels)
- if (clientArea[pos].y + clientArea[pos].heightShown > mainY + mainHeight) {
- clientArea[pos].heightShown = mainY + mainHeight - clientArea[pos].y;
- }
- // Hidden?
- if (clientArea[pos].heightShown <= 0) {
- clientArea[pos].position |= CLIENT_HIDDEN;
- }
- // Next position
- nextCoord += clientArea[pos].heightShown + FRAME_CLIENTPAD;
- // Width is elementary
- clientArea[pos].widthShown = reserve[spot];
- // Horizontal position is elementary
- if (spot == CLIENT_LEFT) {
- clientArea[pos].x = outerBorder;
- }
- else {
- clientArea[pos].x = mainX + mainWidth + FRAME_CLIENTPAD;
- }
- }
-
- lastDid = pos;
- }
-
- if (clientArea[pos].position & CLIENT_HIDDEN) {
- clientArea[pos].widthShown = 0;
- clientArea[pos].heightShown = 0;
- }
- }
- }
-
- // We now resize the last one, if it wasn't hidden- if there's more space
- if ((lastDid) && (!(clientArea[lastDid].position & CLIENT_HIDDEN))) {
- if (spot & CLIENT_TOPBOTTOM) {
- // Extend width?
- if (clientArea[lastDid].x + clientArea[lastDid].widthShown < width - outerBorder) {
- clientArea[lastDid].widthShown = width - outerBorder - clientArea[lastDid].x;
- }
- }
- else {
- // Extend height?
- if (clientArea[lastDid].y + clientArea[lastDid].heightShown < mainY + mainHeight) {
- clientArea[lastDid].heightShown = mainY + mainHeight - clientArea[lastDid].y;
- }
- }
- }
- }
-
- // Client area now loses space for inner borders
- mainWidth -= FRAME_INNERBORDER * 2;
- mainHeight -= FRAME_INNERBORDER * 2;
-
- if (mainWidth < 0) mainWidth = 0;
- if (mainHeight < 0) mainHeight = 0;
- // Finally, we apply the calculations to the main client area
- clientArea[0].x = mainX + FRAME_INNERBORDER;
- clientArea[0].y = mainY + FRAME_INNERBORDER;
- clientArea[0].width = mainWidth;
- clientArea[0].height = mainHeight;
- clientArea[0].widthShown = mainWidth;
- clientArea[0].heightShown = mainHeight;
- }
- int FrameWindow::findToolPanel(Window* toolPanel) { start_func
- assert(toolPanel);
- for (int pos = 1; pos < (int)clientArea.size(); ++pos) {
- if (clientArea[pos].window == toolPanel) return pos;
- }
-
- return 0;
- }
- void FrameWindow::addToolPanel(FrameWindow* toolPanel, int position, vector<ClientArea>::iterator* insertBefore) { start_func
- assert(toolPanel);
- position &= ~CLIENT_HIDDEN;
-
- int newHeight = height;
- int newWidth = width;
- int newX = x;
- int newY = y;
- int desiredSize = -1;
- int wasMinimized = toolPanel->isMinimized();
- if (wasMinimized) toolPanel->restore();
- // Do this now so panel size is as it will be (border and all)
- // Add as managed (temporarily ensure not notifying anyone, to eliminate redundant notifications)
- toolPanel->setParentNotify(NULL);
- toolPanel->setParent(NULL);
- if (position == CLIENT_FLOAT) { // (but not closed)
- toolPanel->show(SHOW_CURRENT, SHOW_CURRENT, SHOW_CURRENT, SHOW_CURRENT);
- toolPanel->setFeatures(RESIZING_NOCHANGE, FRAMETYPE_NOCHANGE, TITLEBAR_NOCHANGE, 1, this);
- }
- else {
- toolPanel->hide();
- toolPanel->setFeatures(RESIZING_NOCHANGE, FRAMETYPE_NOCHANGE, TITLEBAR_NOCHANGE, 0, this);
- toolPanel->setParent(this);
- }
- toolPanel->setParentNotify(this);
-
- // Rearrange panels to make room?
- if (!(position & CLIENT_NOTMANAGED)) {
- // Count panels on this side and note the last one
- int count = 0;
- int last = 0;
- int pos;
- for (pos = 1; pos < (int)clientArea.size(); ++pos) {
- if ((clientArea[pos].window) && (!(clientArea[pos].position & CLIENT_NOTMANAGED)) && ((clientArea[pos].position & CLIENT_GETSIDE) == (position & CLIENT_GETSIDE))) {
- count++;
- last = pos;
- }
- }
- // Assuming we're not the only panel on this size, we need to manage the size
- // If we are, we'll just end up resizing at worst
- int totalSize;
- int prevSize = 0;
-
- // Desired size is the lesser of requested size or our fair share of the panel
- // Also calculate the total size of all previous items on this panel
- if (position & CLIENT_TOPBOTTOM) {
- desiredSize = toolPanel->getWidth();
- totalSize = width - (outerBorder * 2);
- if (count) {
- // Base off of requested size- not actual
- prevSize = clientArea[last].x - outerBorder + clientArea[last].width;
- }
- }
- else {
- desiredSize = toolPanel->getHeight();
- totalSize = height - titlebarY - outerBorder - titlebarHeight - reserve[CLIENT_TOP] - reserve[CLIENT_BOTTOM];
- if (count) {
- prevSize = clientArea[last].y - titlebarY - titlebarHeight - reserve[CLIENT_TOP] + clientArea[last].height;
- }
- }
- // Apply any empty space to our "requirement"
- desiredSize -= totalSize - prevSize;
- // If more room needed, we can try resizing
- if (desiredSize > 0) {
- if (position & CLIENT_TOPBOTTOM) {
- int oldSize = newWidth;
- newWidth += desiredSize;
- confineSize(newX, newY, newWidth, newHeight);
- desiredSize -= newWidth - oldSize;
- }
- else {
- int oldSize = newHeight;
- newHeight += desiredSize;
- confineSize(newX, newY, newWidth, newHeight);
- desiredSize -= newHeight - oldSize;
- }
- }
-
- // Limit any remaining desired size to our fair share of the previous space
- if (desiredSize > totalSize / (count + 1)) {
- desiredSize = totalSize / (count + 1);
- }
-
- // Is more room still needed?
- if ((desiredSize > 0) && (count)) {
- int totalDesiredSize = desiredSize;
- // Rearrange all other clients equally to make room
- for (pos = 1; pos < (int)clientArea.size(); ++pos) {
- if ((clientArea[pos].window) && (!(clientArea[pos].position & CLIENT_NOTMANAGED)) && ((clientArea[pos].position & CLIENT_GETSIDE) == (position & CLIENT_GETSIDE))) {
- if (position & CLIENT_TOPBOTTOM) {
- // Decrease size by an amount based on ratio of total size
- clientArea[pos].width -= totalDesiredSize * clientArea[pos].width / totalSize;
- desiredSize -= totalDesiredSize * clientArea[pos].width / totalSize;
- }
- else {
- // Decrease size by an amount based on ratio of total size
- clientArea[pos].height -= totalDesiredSize * clientArea[pos].height / totalSize;
- desiredSize -= totalDesiredSize * clientArea[pos].height / totalSize;
- }
- }
- }
- }
-
- // If any "desired size" left, deduct it from what's allowed
- if (position & CLIENT_TOPBOTTOM) {
- desiredSize = toolPanel->getWidth() - ((desiredSize > 0) ? desiredSize : 0);
- }
- else {
- desiredSize = toolPanel->getHeight() - ((desiredSize > 0) ? desiredSize : 0);
- }
- // Resize window if new panel is docked and larger than the reserve already there
- if (state != FRAME_STATE_MAXIMIZED) {
- if ((position & CLIENT_GETSIDE) == CLIENT_LEFT) {
- if (toolPanel->getWidth() > reserve[CLIENT_LEFT]) {
- newWidth += toolPanel->getWidth() - reserve[CLIENT_LEFT];
- if (reserve[CLIENT_LEFT] == 0) newWidth += FRAME_CLIENTPAD;
- }
- }
- if ((position & CLIENT_GETSIDE) == CLIENT_RIGHT) {
- if (toolPanel->getWidth() > reserve[CLIENT_RIGHT]) {
- newWidth += toolPanel->getWidth() - reserve[CLIENT_RIGHT];
- if (reserve[CLIENT_LEFT] == 0) newWidth += FRAME_CLIENTPAD;
- }
- }
- if ((position & CLIENT_GETSIDE) == CLIENT_TOP) {
- if (toolPanel->getHeight() > reserve[CLIENT_TOP]) {
- newHeight += toolPanel->getHeight() - reserve[CLIENT_TOP];
- if (reserve[CLIENT_LEFT] == 0) newWidth += FRAME_CLIENTPAD;
- }
- }
- if ((position & CLIENT_GETSIDE) == CLIENT_BOTTOM) {
- if (toolPanel->getHeight() > reserve[CLIENT_BOTTOM]) {
- newHeight += toolPanel->getHeight() - reserve[CLIENT_BOTTOM];
- if (reserve[CLIENT_LEFT] == 0) newWidth += FRAME_CLIENTPAD;
- }
- }
- confineSize(newX, newY, newWidth, newHeight);
- move(newX, newY);
- }
- }
- // Add to panels
- ClientArea ca = { toolPanel, -1, -1,
- (position & CLIENT_TOPBOTTOM) ? desiredSize : -1,
- (position & CLIENT_TOPBOTTOM) ? -1 : desiredSize,
- -1, -1, position };
-
- if ((insertBefore) && ((*insertBefore) != clientArea.end())) {
- clientArea.insert(*insertBefore, ca);
- }
- else {
- clientArea.push_back(ca);
- }
-
- // Handles resize and also rearranges client areas
- resize(newWidth, newHeight);
- if (wasMinimized) toolPanel->minimize();
- return;
- }
- void FrameWindow::removeToolPanel(Window* toolPanel) { start_func
- assert(toolPanel);
- assert(clientArea[0].window != toolPanel);
- vector<ClientArea>::iterator end = clientArea.end();
- for (vector<ClientArea>::iterator pos = clientArea.begin(); pos != end; ++pos) {
- if ((*pos).window == toolPanel) {
- (*pos).window->setParent(NULL);
- clientArea.erase(pos);
- break;
- }
- }
-
- // @TODO: Do we need to check if toolpanel is referenced in a drag setting, subfocus, etc?
-
- // Rearranges client areas as needed
- resize(width, height);
- }
- void FrameWindow::setTitle(const string& newTitle) { start_func
- // (this line could memfault)
- titlebar = newTitle;
- setDirty();
- whyDirty |= FRAME_DIRTY_TITLE;
- }
- Window::WindowType FrameWindow::windowType() const { start_func
- return WINDOW_FRAME;
- }
- #ifndef NDEBUG
- const char* FrameWindow::debugDump() const { start_func
- return titlebar.c_str();
- }
- #endif
- void FrameWindow::nextWindow() { start_func
- // Cancel if modal or not on desktop
- if ((windowSort() == WINDOWSORT_MODAL) || (parent != desktop)) return;
- desktop->bringToTop(desktop->findWindow(WINDOW_FRAME, 0));
- }
- void FrameWindow::prevWindow() { start_func
- // Cancel if modal or not on desktop
- if ((windowSort() == WINDOWSORT_MODAL) || (parent != desktop)) return;
- // Find us
- int pos = 0;
- while (desktop->findWindow(WINDOW_FRAME, pos) != this) {
- // (Shouldn't be NULL unless we aren't in collection!)
- assert(desktop->findWindow(WINDOW_FRAME, pos));
- ++pos;
- }
-
- if (--pos >= 0) {
- desktop->bringToTop(desktop->findWindow(WINDOW_FRAME, pos));
- desktop->sendToBottom(this);
- }
- }
- int FrameWindow::isMinimized() { start_func
- return (state == FRAME_STATE_MINIMIZED) ? 1 : 0;
- }
- void FrameWindow::minimize() { start_func
- if (state == FRAME_STATE_MINIMIZED) return;
- char* button = strchr(titlebarButtons, 'h');
- if (!button) return; // Can't minimize!
- if (state == FRAME_STATE_MAXIMIZED) restore();
- restoreX = x;
- restoreY = y;
- restoreWidth = width;
- restoreHeight = height;
- state = FRAME_STATE_MINIMIZED;
- resize(width, titlebarHeight + 2 * outerBorder);
- *button = 'j';
- }
- void FrameWindow::maximize() { start_func
- if ((state == FRAME_STATE_MAXIMIZED) || ((parent != desktop) && (parent != NULL))) return;
- char* button = strchr(titlebarButtons, 'g');
- if (!button) return; // Can't maximize!
- if (state == FRAME_STATE_MINIMIZED) {
- char* button2 = strchr(titlebarButtons, 'j');
- if (button2) *button2 = 'h';
- }
- restoreX = x;
- restoreY = y;
-
- if (state == FRAME_STATE_NORMAL) {
- restoreWidth = width;
- restoreHeight = height;
- }
- // (final -1/+1 is for the inner titlebar border)
- state = FRAME_STATE_MAXIMIZED;
- move(desktop->desktopX() - outerBorder, desktop->desktopY() - outerBorder - 1);
- resize(desktop->desktopWidth() + outerBorder * 2,
- desktop->desktopHeight() + outerBorder * 2 + 1);
- *button = 'j';
- }
- void FrameWindow::restore() { start_func
- if (state == FRAME_STATE_NORMAL) return;
-
- char* button = strchr(titlebarButtons, 'j');
- if (button) *button = state == FRAME_STATE_MAXIMIZED ? 'g' : 'h';
- if (state != FRAME_STATE_MAXIMIZED) {
- restoreX = x;
- restoreY = y;
- }
- state = FRAME_STATE_NORMAL;
- confineSize(restoreX, restoreY, restoreWidth, restoreHeight);
- move(restoreX, restoreY);
- resize(restoreWidth, restoreHeight);
- }
- void FrameWindow::toggleToolPanel(int index, int giveFocusIfOpen) { start_func
- if ((index < (int)clientArea.size()) && (index > 0) && (clientArea[index].window)) {
- int position = clientArea[index].position & ~CLIENT_HIDDEN;
-
- // Ignore floating/desktop (@TODO: fix later)
- if ((position & CLIENT_FLOAT) || (position & CLIENT_DOCKED)) {
- return;
- }
-
- // Toggle closed or not
- position ^= CLIENT_CLOSED;
-
- if ((!(position & CLIENT_CLOSED)) && (giveFocusIfOpen)) focusToolPanel(index);
- else if ((position & CLIENT_CLOSED) && (subFocus == index)) focusToolPanel(0);
-
- // Redraw
- resize(width, height);
- }
- }
- void FrameWindow::focusToolPanel(int index) { start_func
- // No focus if not visible or doesn't exist
- if (index >= (int)clientArea.size()) index = 0;
- if (index > 0) {
- if ((!clientArea[index].window) || (clientArea[index].position & CLIENT_NOTMANAGED)) {
- index = 0;
- }
- // Ignore floating/desktop (@TODO: fix later)
- if ((clientArea[index].position & CLIENT_FLOAT) || (clientArea[index].position & CLIENT_DOCKED)) {
- return;
- }
- }
- // Doesn't match current focus?
- if ((index != subFocus) && (haveFocus)) {
- // Lose
- SDL_Event customEvent;
- customEvent.type = SDL_INPUTFOCUS;
- customEvent.user.code = 2;
- customEvent.user.data1 = NULL;
- customEvent.user.data2 = NULL;
- if (clientArea[subFocus].window) clientArea[subFocus].window->event(0, &customEvent);
-
- // Gain
- subFocus = index;
- customEvent.user.code = 1;
- if (clientArea[subFocus].window) clientArea[subFocus].window->event(haveFocus, &customEvent);
- }
- // If we didn't have focus, we still need to set our personal focus
- // for when we regain focus later
- else {
- subFocus = index;
- }
- }
- void FrameWindow::redoSize() { start_func
- if (state == FRAME_STATE_MAXIMIZED) {
- restore();
- maximize();
- }
- else {
- int cX = x;
- int cY = y;
- int cW = width;
- int cH = height;
- confineSize(cX, cY, cW, cH);
- move(cX, cY);
- resize(cW, cH);
- }
- }
- void FrameWindow::updateClientSize() { start_func
- resize(width, height);
- }
- void FrameWindow::setAutoCenter(int newAutoCenter) { start_func
- autoCenterScroll = newAutoCenter;
- resize(width, height);
- }
- void FrameWindow::setScroll(int vLine, int hLine) { start_func
- assert(vLine > 0);
- assert(hLine > 0);
-
- vScrollLine = vLine;
- hScrollLine = hLine;
-
- // A page = full height/width, rounded down to a line multiple,
- // minus one line's worth
- vScrollPage = (clientHeightInner / vLine - 1) * vLine;
- if (vScrollPage < vLine) vScrollPage = vLine;
- hScrollPage = (clientWidthInner / hLine - 1) * hLine;
- if (hScrollPage < hLine) hScrollPage = hLine;
- }
- void FrameWindow::resize(int newWidth, int newHeight, int newViewWidth, int newViewHeight, int fromParent) { start_func
- // If a framepanel, resize to view if from parent (unless minimized)
- if (framePanel) {
- if ((state != FRAME_STATE_MINIMIZED) && (fromParent)) {
- if (newViewWidth == -1) newViewWidth = viewWidth;
- if (newViewWidth != -1) newWidth = newViewWidth;
- if (newViewHeight == -1) newViewHeight = viewHeight;
- if (newViewHeight != -1) newHeight = newViewHeight;
- }
- }
- else {
- // (enforce minimum width/height)
- if (newHeight < (titlebarHeight + 2 * outerBorder)) {
- newHeight = titlebarHeight + 2 * outerBorder;
- }
- if (newWidth < (outerBorder * 2 + 2 + titlebarButtonTotalWidth)) {
- newWidth = outerBorder * 2 + 2 + titlebarButtonTotalWidth;
- }
- }
- if (clientArea[0].window) {
- clientActualWidth = clientArea[0].window->getWidth();
- clientActualHeight = clientArea[0].window->getHeight();
- }
- else {
- clientActualWidth = clientActualHeight = 0;
- }
- // Our size (doesn't always set dirty, so we must)
- Window::resize(newWidth, newHeight, newViewWidth, newViewHeight, fromParent);
- setDirty();
- whyDirty = FRAME_DIRTY_ALL;
- // Tool panel and reserve sizes and client area size
- reorganizeReserves();
- // If resizing in SNAP mode-
- // Our actual size should fit exactly to hold clientarea 0, if possible- but
- // allow it to resize first (unless we're minimized)
- if ((resizable == RESIZING_SNAP) &&
- (clientArea[0].window) &&
- (clientActualWidth > 0) &&
- (clientActualHeight > 0) &&
- (state != FRAME_STATE_MINIMIZED)) {
- clientArea[0].window->resize(clientActualWidth, clientActualHeight, clientArea[0].width, clientArea[0].height, 1);
- clientActualWidth = clientArea[0].window->getWidth();
- clientActualHeight = clientArea[0].window->getHeight();
- if ((clientActualWidth != clientArea[0].width) || (clientActualHeight != clientArea[0].height)) {
- newWidth += clientActualWidth - clientArea[0].width;
- newHeight += clientActualHeight - clientArea[0].height;
- Window::resize(newWidth, newHeight, newViewWidth, newViewHeight, fromParent);
- reorganizeReserves();
- }
- }
- // Finish tool panels
- int max = clientArea.size();
- for (int pos = 1; pos < max; ++pos) {
- if (clientArea[pos].window) {
- if ((clientArea[pos].position & CLIENT_FLOAT) || (clientArea[pos].position & CLIENT_DOCKED)) {
- // Don't resize floating or desktop-docked panels
- }
- else if (clientArea[pos].position & CLIENT_NOTMANAGED) {
- clientArea[pos].window->resize(clientArea[pos].window->getWidth(), clientArea[pos].window->getHeight(), 0, 0, 1);
- }
- else {
- clientArea[pos].window->move(clientArea[pos].x, clientArea[pos].y);
- clientArea[pos].window->resize(clientArea[pos].window->getWidth(), clientArea[pos].window->getHeight(), clientArea[pos].widthShown, clientArea[pos].heightShown, 1);
- }
- }
- }
- // Scrollbars default to off
- vScrollbarX = vScrollbarY = vScrollbarWidth = vScrollbarHeight = vScrollbarTabSize = 0;
- hScrollbarX = hScrollbarY = hScrollbarWidth = hScrollbarHeight = hScrollbarTabSize = 0;
- // Must have room for at least 3 button sizes, or no scrollbars appear
- if ((clientArea[0].window) &&
- (clientArea[0].width >= scrollbarButtonSize * 3) &&
- (clientArea[0].height >= scrollbarButtonSize * 3)) {
- int needH = clientActualWidth > clientArea[0].width;
- int needV = clientActualHeight > clientArea[0].height;
- if (needV) needH = clientActualWidth > clientArea[0].width - scrollbarButtonSize;
- if (needH) needV = clientActualHeight > clientArea[0].height - scrollbarButtonSize;
-
- if (needV) {
- vScrollbarX = clientArea[0].x + clientArea[0].width - scrollbarButtonSize;
- vScrollbarY = clientArea[0].y;
- vScrollbarWidth = scrollbarButtonSize;
- vScrollbarHeight = clientArea[0].height;
- if (needH) vScrollbarHeight -= scrollbarButtonSize;
- }
-
- if (needH) {
- hScrollbarX = clientArea[0].x;
- hScrollbarY = clientArea[0].y + clientArea[0].height - scrollbarButtonSize;
- hScrollbarWidth = clientArea[0].width;
- hScrollbarHeight = scrollbarButtonSize;
- if (needV) hScrollbarWidth -= scrollbarButtonSize;
- }
- }
-
- // Assign inner size
- clientWidthInner = clientArea[0].width - vScrollbarWidth;
- clientHeightInner = clientArea[0].height - hScrollbarHeight;
-
- // Now we can determine scrollbar tab sizes
- // Determine tab size as the percent the current view is of the total view
- // Tab position determined by scrollTo call later
- if (vScrollbarX) {
- vScrollbarTabSize = clientHeightInner * (vScrollbarHeight - scrollbarButtonSize * 2) / clientActualHeight;
- if (vScrollbarTabSize < FRAME_SCROLLTABMIN) vScrollbarTabSize = FRAME_SCROLLTABMIN;
- if (vScrollbarTabSize > (vScrollbarHeight - scrollbarButtonSize * 2)) vScrollbarTabSize = 0;
- }
- if (hScrollbarY) {
- hScrollbarTabSize = clientWidthInner * (hScrollbarWidth - scrollbarButtonSize * 2) / clientActualWidth;
- if (hScrollbarTabSize < FRAME_SCROLLTABMIN) hScrollbarTabSize = FRAME_SCROLLTABMIN;
- if (hScrollbarTabSize > (hScrollbarWidth - scrollbarButtonSize * 2)) hScrollbarTabSize = 0;
- }
- // Calculate titlebar size
- titlebarWidth = newWidth - (outerBorder * 2);
- titlebarButtonX = titlebarX + titlebarWidth - 1 - titlebarButtonTotalWidth;
- // Ensure we're scrolled properly and sizing is set right
- if ((autoCenterScroll) && (clientActualWidth < clientWidthInner)) {
- scrollX = (clientWidthInner - clientActualWidth) / 2;
- }
- if ((autoCenterScroll) && (clientActualHeight < clientHeightInner)) {
- scrollY = (clientHeightInner - clientActualHeight) / 2;
- }
- scrollTo(scrollX, scrollY);
- setScroll(vScrollLine, hScrollLine);
- // Tell client of new view size?
- if (clientArea[0].window) {
- clientArea[0].window->resize(clientActualWidth, clientActualHeight, clientWidthInner, clientHeightInner, 1);
- clientArea[0].window->move(clientArea[0].x + scrollX, clientArea[0].y + scrollY);
- }
- }
- FrameWindow::~FrameWindow() { start_func
- if (parent == desktop) desktop->removeWindow(this);
-
- vector<ClientArea>::iterator end = clientArea.end();
- for (vector<ClientArea>::iterator pos = clientArea.begin(); pos != end; ++pos) {
- if ((*pos).window) {
- (*pos).window->setParent(NULL);
- (*pos).window->setParentNotify(NULL);
- if ((*pos).window->wantsToBeDeleted()) delete (*pos).window;
- }
- }
- }
- void FrameWindow::resolutionChange(int fromW, int fromH, int fromBpp, int toW, int toH, int toBpp) { start_func
- Window::resolutionChange(fromW, fromH, fromBpp, toW, toH, toBpp);
- vector<ClientArea>::iterator end = clientArea.end();
- for (vector<ClientArea>::iterator pos = clientArea.begin(); pos != end; ++pos) {
- if ((*pos).window) {
- (*pos).window->resolutionChange(fromW, fromH, fromBpp, toW, toH, toBpp);
- }
- }
- }
- void FrameWindow::dragFloatPanel(int index, int drop) { start_func
- assert(index > 0);
- assert(index < (int)clientArea.size());
-
- if ((clientArea[index].window) && (clientArea[index].position & CLIENT_FLOAT)) {
- // x/y position of floating panel, relative to our window
- int fx = clientArea[index].window->getX() - x;
- int fy = clientArea[index].window->getY() - y;
- // sensitivity based off size
- int sx = clientArea[index].window->getWidth() / 2;
- int sy = clientArea[index].window->getHeight() / 2;
-
- // work off of center
- fx += sx;
- fy += sy;
-
- // scan all panel positions
- int closestDist = 99999;
- int closestSide = -1;
- int closestAfter = -1;
- int dist;
- vector<ClientArea>::iterator source = clientArea.end();
- vector<ClientArea>::iterator closest = clientArea.end();
- vector<ClientArea>::iterator end = clientArea.end();
- vector<ClientArea>::iterator pos = clientArea.begin();
- for (++pos; pos != end; ++pos) {
- if ((*pos).window == clientArea[index].window) {
- source = pos;
- }
- else if (((*pos).window) && (!((*pos).position & CLIENT_NOTMANAGED))) {
- if ((*pos).position & CLIENT_TOPBOTTOM) {
- // Look at left and right centers
- if (abs(fy - ((*pos).y + (*pos).heightShown / 2)) < sy) {
- if (abs(fx - (*pos).x) < sx) {
- dist = abs(fx - (*pos).x) + abs(fy - ((*pos).y + (*pos).heightShown / 2));
- if (dist <= closestDist) {
- closestDist = dist;
- closest = pos;
- closestAfter = 0;
- floatTargetX = (*pos).x;
- }
- }
- if (abs(fx - ((*pos).x + (*pos).widthShown)) < sx) {
- dist = abs(fx - ((*pos).x + (*pos).widthShown)) + abs(fy - ((*pos).y + (*pos).heightShown / 2));
- if (dist <= closestDist) {
- closestDist = dist;
- closest = pos;
- closestAfter = 1;
- floatTargetX = (*pos).x + (*pos).widthShown;
- }
- }
- if (closest == pos) {
- closestSide = (*pos).position;
- floatTargetX -= sx;
- floatTargetWidth = sx * 2;
- floatTargetY = (*pos).y;
- floatTargetHeight = (*pos).heightShown;
- }
- }
- }
- else {
- // Look at top and bottom centers
- if (abs(fx - ((*pos).x + (*pos).widthShown / 2)) < sx) {
- if (abs(fy - (*pos).y) < sy) {
- dist = abs(fy - (*pos).y) + abs(fx - ((*pos).x + (*pos).widthShown / 2));
- if (dist <= closestDist) {
- closestDist = dist;
- closest = pos;
- closestAfter = 0;
- floatTargetY = (*pos).y;
- }
- }
- if (abs(fy - ((*pos).y + (*pos).heightShown)) < sy) {
- dist = abs(fy - ((*pos).y + (*pos).heightShown)) + abs(fx - ((*pos).x + (*pos).widthShown / 2));
- if (dist <= closestDist) {
- closestDist = dist;
- closest = pos;
- closestAfter = 1;
- floatTargetY = (*pos).y + (*pos).heightShown;
- }
- }
- if (closest == pos) {
- closestSide = (*pos).position;
- floatTargetY -= sy;
- floatTargetHeight = sy * 2;
- floatTargetX = (*pos).x;
- floatTargetWidth = (*pos).widthShown;
- }
- }
- }
- }
- }
-
- // Scan any empty reserves also
- if (reserve[CLIENT_LEFT] <= 0) {
- // Look at left center of client area
- if ((abs(fy - (clientArea[0].y + clientArea[0].height / 2)) < sy) && (abs(fx - clientArea[0].x) < sx)) {
- dist = abs(fy - (clientArea[0].y + clientArea[0].height / 2)) + abs(fx - clientArea[0].x);
- if (dist <= closestDist) {
- closestDist = dist;
- closestSide = CLIENT_LEFT;
- closest = clientArea.end();
- floatTargetX = clientArea[0].x - sx;
- floatTargetY = clientArea[0].y;
- floatTargetWidth = sx * 2;
- floatTargetHeight = clientArea[0].height;
- }
- }
- }
- if (reserve[CLIENT_RIGHT] <= 0) {
- // Look at right center of client area
- if ((abs(fy - (clientArea[0].y + clientArea[0].height / 2)) < sy) && (abs(fx - (clientArea[0].x + clientArea[0].width)) < sx)) {
- dist = abs(fy - (clientArea[0].y + clientArea[0].height / 2)) + abs(fx - (clientArea[0].x + clientArea[0].width));
- if (dist <= closestDist) {
- closestDist = dist;
- closestSide = CLIENT_RIGHT;
- closest = clientArea.end();
- floatTargetX = clientArea[0].x + clientArea[0].width - sx;
- floatTargetY = clientArea[0].y;
- floatTargetWidth = sx * 2;
- floatTargetHeight = clientArea[0].height;
- }
- }
- }
- if (reserve[CLIENT_TOP] <= 0) {
- // Look at top center of client area
- if ((abs(fx - (clientArea[0].x + clientArea[0].width / 2)) < sx) && (abs(fy - clientArea[0].y) < sy)) {
- dist = abs(fx - (clientArea[0].x + clientArea[0].width / 2)) + abs(fy - clientArea[0].y);
- if (dist <= closestDist) {
- closestDist = dist;
- closestSide = CLIENT_TOP;
- closest = clientArea.end();
- floatTargetX = clientArea[0].x;
- floatTargetY = clientArea[0].y - sy;
- floatTargetWidth = clientArea[0].width;
- floatTargetHeight = sy * 2;
- }
- }
- }
- if (reserve[CLIENT_BOTTOM] <= 0) {
- // Look at bottom center of client area
- if ((abs(fx - (clientArea[0].x + clientArea[0].width / 2)) < sx) && (abs(fy - (clientArea[0].y + clientArea[0].height)) < sy)) {
- dist = abs(fx - (clientArea[0].x + clientArea[0].width / 2)) + abs(fy - (clientArea[0].y + clientArea[0].height));
- if (dist <= closestDist) {
- closestDist = dist;
- closestSide = CLIENT_BOTTOM;
- closest = clientArea.end();
- floatTargetX = clientArea[0].x;
- floatTargetY = clientArea[0].y + clientArea[0].height - sy;
- floatTargetWidth = clientArea[0].width;
- floatTargetHeight = sy * 2;
- }
- }
- }
- if ((closestSide < 0) || (floatTargetWidth <= 0) || (floatTargetHeight <= 0)) {
- floatTarget = 0;
- }
- else {
- if (drop) {
- // Drop panel on this side
- FrameWindow* window = dynamic_cast<FrameWindow*>((*source).window);
- int position = (((*source).position & ~CLIENT_FLOAT) & ~CLIENT_GETSIDE) | closestSide;
-
- // If relative to an existing panel, sort into list in proper position
- if (closest != clientArea.end()) {
- // adjust element later in list first, to preserve iterators
- if (source > closest) {
- clientArea.erase(source);
- if (closestAfter) ++closest; // (source = closest now? still ok)
- addToolPanel(window, position, &closest);
- }
- else {
- (*source).window = NULL;
- if (closestAfter) ++closest;
- addToolPanel(window, position, &closest);
- clientArea.erase(source);
- }
-
- // Note that both iterators are likely invalid now
- }
- else {
- clientArea.erase(source);
- addToolPanel(window, position);
- }
- floatTarget = 0;
- resize(width, height, -1, -1);
- }
- else {
- floatTarget = 1;
- }
- }
-
- setDirty();
- whyDirty = FRAME_DIRTY_ALL;
- }
- }
- void FrameWindow::dragToolPanel(int index, int xMotion, int yMotion, int& dragItemOverflowX, int& dragItemOverflowY) { start_func
- assert(index > 0);
- assert(index < (int)clientArea.size());
- xMotion += dragItemOverflowX;
- dragItemOverflowX = 0;
- yMotion += dragItemOverflowY;
- dragItemOverflowY = 0;
-
- if ((clientArea[index].window) && (!(clientArea[index].position & CLIENT_NOTMANAGED))) {
- // Dragging off of toolbar? (drag 1/2 of distance perpendicular)
- int dragOff = 0;
- if (clientArea[index].position & CLIENT_TOPBOTTOM) {
- if (abs(yMotion) > clientArea[index].heightShown / 2) {
- dragOff = 1;
- }
- }
- else {
- if (abs(xMotion) > clientArea[index].widthShown / 2) {
- dragOff = 1;
- }
- }
-
- if (dragOff) {
- // Target desktop position
- int tx, ty;
- tx = x + clientArea[index].x + xMotion - FRAME_OUTERBORDER;
- ty = y + clientArea[index].y + yMotion - FRAME_OUTERBORDER;
-
- // Float it
- int newX = tx;
- int newY = ty;
- int newWidth = dynamic_cast<FrameWindow*>(clientArea[index].window)->getWidth() + FRAME_OUTERBORDER * 2;
- int newHeight = dynamic_cast<FrameWindow*>(clientArea[index].window)->getHeight() + FRAME_OUTERBORDER * 2;
- dynamic_cast<FrameWindow*>(clientArea[index].window)->setFeatures(RESIZING_NOCHANGE, FRAMETYPE_NOCHANGE, TITLEBAR_NOCHANGE, 1, this);
- dynamic_cast<FrameWindow*>(clientArea[index].window)->setParent(NULL);
- dynamic_cast<FrameWindow*>(clientArea[index].window)->confineSize(newX, newY, newWidth, newHeight);
- clientArea[index].position |= CLIENT_FLOAT;
- dynamic_cast<FrameWindow*>(clientArea[index].window)->show(newX, newY, newWidth, newHeight);
- resize(width, height, -1, -1);
-
- // Initiate a fake click to continue drag- click must be on exact
- // same relative location within window so determine how far off that is
- tx = dynamic_cast<FrameWindow*>(clientArea[index].window)->getX() - tx;
- ty = dynamic_cast<FrameWindow*>(clientArea[index].window)->getY() - ty;
-
- // Generate fake event
- SDL_Event customEvent;
- int mx, my;
- SDL_GetMouseState(&mx, &my);
- customEvent.button.x = mx + tx;
- customEvent.button.y = my + ty;
- customEvent.type = SDL_MOUSEBUTTONDOWN;
- customEvent.button.button = SDL_BUTTON_LEFT;
- desktop->preventDoubleClick();
- insertEvent(&customEvent);
-
- return;
- }
-
- // Find panel right before us
- // Set sizes of panels before us "in stone" (once we start dragging,
- // the user has locked in the previous sizes as a starting point)
- int previous = 0;
- for (int pos = 1; pos < index; ++pos) {
- if (clientArea[pos].window) {
- if (clientArea[pos].position == clientArea[index].position) {
- if (clientArea[pos].position& CLIENT_TOPBOTTOM) {
- clientArea[pos].width = clientArea[pos].widthShown;
- }
- else {
- clientArea[pos].height = clientArea[pos].heightShown;
- }
- previous = pos;
- }
- }
- }
- // If found, resize it appropriately
- if (previous) {
- int oldSize;
-
- if (clientArea[index].position & CLIENT_TOPBOTTOM) {
- clientArea[previous].width += xMotion;
- oldSize = clientArea[previous].widthShown + xMotion;
- xMotion = 0;
- }
- else {
- clientArea[previous].height += yMotion;
- oldSize = clientArea[previous].heightShown + yMotion;
- yMotion = 0;
- }
- resize(width, height, -1, -1);
- if (clientArea[index].position & CLIENT_TOPBOTTOM) {
- if (oldSize != clientArea[previous].widthShown) {
- dragItemOverflowX = oldSize - clientArea[previous].widthShown;
- }
- }
- else {
- if (oldSize != clientArea[previous].heightShown) {
- dragItemOverflowY = oldSize - clientArea[previous].heightShown;
- }
- }
- }
- }
-
- dragItemOverflowX = xMotion;
- dragItemOverflowY = yMotion;
- }
- void FrameWindow::childMoved(int fromX, int fromY, int toX, int toY, Window* child) { start_func
- assert(child);
-
- setChildDirty();
- }
- void FrameWindow::childResized(int fromW, int fromH, int toW, int toH, Window* child) { start_func
- assert(child);
- // Reaccount for child's new window size as requested
- for (unsigned int pos = 1; pos < clientArea.size(); ++pos) {
- if ((clientArea[pos].window == child) && (!(clientArea[pos].position & CLIENT_NOTMANAGED))) {
- clientArea[pos].width = -1;
- clientArea[pos].height = -1;
- resize(width, height, -1, -1);
- break;
- }
- }
-
- setChildDirty();
- }
- void FrameWindow::childDeleted(Window* child) { start_func
- assert(child);
-
- vector<ClientArea>::iterator end = clientArea.end();
- for (vector<ClientArea>::iterator pos = clientArea.begin(); pos != end; ++pos) {
- if ((*pos).window == child) {
- (*pos).window= NULL;
- break;
- }
- }
- }
- void FrameWindow::childModified(Window* child) { start_func
- assert(child);
- vector<ClientArea>::iterator end = clientArea.end();
- for (vector<ClientArea>::iterator pos = clientArea.begin(); pos != end; ++pos) {
- if (((*pos).window) && ((*pos).window != child)) {
- (*pos).window->siblingModified(child);
- }
- }
-
- Window::childModified(child);
- }
- void FrameWindow::siblingModified(Window* sibling) { start_func
- assert(sibling);
- vector<ClientArea>::iterator end = clientArea.end();
- for (vector<ClientArea>::iterator pos = clientArea.begin(); pos != end; ++pos) {
- if (((*pos).window) && ((*pos).window != sibling)) {
- (*pos).window->siblingModified(sibling);
- }
- }
- }
- void FrameWindow::display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset) { start_func
- assert(destSurface);
- if (visible) {
- // This breaks redraw down into titlebar, scrollbars, edge, client areas
- // Redraw all?
- if (whyDirty == FRAME_DIRTY_ALL) {
- getRect(toDisplay);
- toDisplay.x += xOffset;
- toDisplay.y += yOffset;
- dirty = 0;
- intersectRects(toDisplay, clipArea);
- }
-
- xOffset += x;
- yOffset += y;
-
- // Anything to draw so far?
- if (toDisplay.w) {
- SDL_SetClipRect(destSurface, &toDisplay);
-
- // Draw fill and border
- if (outerBorder) {
- drawGuiBox(xOffset, yOffset, width, height, FRAME_BEVELTHICKNESS, destSurface);
- }
- else {
- drawRect(xOffset, yOffset, width, height, guiPacked[COLOR_FILL], destSurface);
- }
- if (((frameType == FRAMETYPE_BEVEL_BK) || (frameType == FRAMETYPE_BEVEL_TEXT)) &&
- (clientArea[0].width > 0) && (clientArea[0].height > 0)) {
- drawGuiBoxInvert(xOffset + clientArea[0].x - FRAME_BEVELTHICKNESS, yOffset + clientArea[0].y - FRAME_BEVELTHICKNESS,
- clientArea[0].width + FRAME_BEVELTHICKNESS * 2, clientArea[0].height + FRAME_BEVELTHICKNESS * 2,
- FRAME_BEVELTHICKNESS, destSurface);
- }
- }
-
- // This will be the final displayed amount, we update it as we go but still work
- // off of the original dirtied area for efficiency
- Rect updatedArea = toDisplay;
-
- // Titlebar
- if (titlebarType != TITLEBAR_OFF) {
- // Determine clip area for titlebar
- Rect titleClip = { titlebarX + xOffset, titlebarY + yOffset, titlebarWidth, titlebarHeight };
- intersectRects(titleClip, clipArea);
-
- // If we need to update title, OR it intersects with the dirty area,
- // redraw it; note that if the second conditional is tested, vertClip will be reduced
- // to whatever portion intersects with the dirty area, which is what we want
- if ((whyDirty & FRAME_DIRTY_TITLE) || (intersectRects(titleClip, toDisplay))) {
- // Add titlebar rect into updated area
- boundRects(updatedArea, titleClip);
-
- SDL_SetClipRect(destSurface, &titleClip);
- drawGradient(titlebarX + xOffset, titlebarY + yOffset, titlebarWidth - titlebarButtonTotalWidth, titlebarHeight, guiRGB[haveFocus ? COLOR_TITLEACTIVE1 : COLOR_TITLEINACTIVE1], guiRGB[haveFocus ? COLOR_TITLEACTIVE2 : COLOR_TITLEINACTIVE2], destSurface);
- // (fill corners of inverted titlebar box first)
- drawPixel(titlebarX + xOffset + titlebarWidth - 1, titlebarY + yOffset, guiPacked[COLOR_FILL], destSurface);
- drawPixel(titlebarX + xOffset, titlebarY + yOffset + titlebarHeight - 1, guiPacked[COLOR_FILL], destSurface);
- drawGuiBoxInvert(titlebarX + xOffset, titlebarY + yOffset, titlebarWidth, titlebarHeight, 1, destSurface);
-
- // Buttons
- for (int pos = strlen(titlebarButtons) - 1; pos >= 0; --pos) {
- string text(1, titlebarButtons[pos]);
- if ((dragMode == FRAME_DRAG_BUTTONS) && (dragItem == (DragSubType)(pos + 1))) {
- // Non-gradient: drawRect(xOffset + titlebarButtonX + pos * titlebarButtonSize, yOffset + titlebarButtonY, titlebarButtonSize, titlebarButtonSize, guiPacked[COLOR_FILL], destSurface);
- drawGradient(xOffset + titlebarButtonX + pos * titlebarButtonSize, yOffset + titlebarButtonY, titlebarButtonSize, titlebarButtonSize, guiRGB[COLOR_BUTTONDOWN1], guiRGB[COLOR_BUTTONDOWN2], destSurface);
- drawGuiBoxInvert(xOffset + titlebarButtonX + pos * titlebarButtonSize, yOffset + titlebarButtonY, titlebarButtonSize, titlebarButtonSize, 2, destSurface);
- drawText(text, guiRGB[COLOR_TEXT], xOffset + titlebarButtonX + pos * titlebarButtonSize + titlebarButtonXPad + 1, yOffset + titlebarButtonY + titlebarButtonXPad + 1, destSurface, titlebarType == TITLEBAR_TOOL ? FONT_TOOLTITLEBARWIDGET : FONT_TITLEBARWIDGET);
- }
- else {
- drawGuiBox(xOffset + titlebarButtonX + pos * titlebarButtonSize, yOffset + titlebarButtonY, titlebarButtonSize, titlebarButtonSize, 2, destSurface);
- // Non-gradient: nothing
- drawGradient(xOffset + titlebarButtonX + pos * titlebarButtonSize + 2, yOffset + titlebarButtonY + 2, titlebarButtonSize - 4, titlebarButtonSize - 4, guiRGB[COLOR_BUTTONFILL1], guiRGB[COLOR_BUTTONFILL2], destSurface);
- drawText(text, guiRGB[COLOR_TEXT], xOffset + titlebarButtonX + pos * titlebarButtonSize + titlebarButtonXPad, yOffset + titlebarButtonY + titlebarButtonXPad, destSurface, titlebarType == TITLEBAR_TOOL ? FONT_TOOLTITLEBARWIDGET : FONT_TITLEBARWIDGET);
- }
- }
-
- // (clip text further- done last due to new clip rectangle)
- Rect titleTextClip = { xOffset + titlebarX + 1, yOffset + titlebarY + 1, titlebarWidth - 2 - titlebarButtonTotalWidth, titlebarHeight - 2 };
- intersectRects(titleTextClip, titleClip);
- SDL_SetClipRect(destSurface, &titleTextClip);
- drawText(titlebar, guiRGB[COLOR_TEXT], xOffset + titlebarX + (titlebarType == TITLEBAR_TOOL ? FRAME_TOOLTITLELEFTPAD : FRAME_TITLELEFTPAD), yOffset + titlebarY + (titlebarType == TITLEBAR_TOOL ? FRAME_TOOLTITLETOPPAD : FRAME_TITLETOPPAD), destSurface, titlebarType == TITLEBAR_TOOL ? FONT_TOOLTITLEBAR : FONT_TITLEBAR);
- }
- }
-
- // (make sure vertical exists before doing more work)
- if (vScrollbarX) {
- // Determine clip area for vertical scrollbar
- Rect vertClip = { vScrollbarX + xOffset, vScrollbarY + yOffset, vScrollbarWidth, vScrollbarHeight };
- intersectRects(vertClip, clipArea);
-
- // If we need to update vertical scroll, OR it intersects with the dirty area,
- // redraw it; note that if the second conditional is tested, vertClip will be reduced
- // to whatever portion intersects with the dirty area, which is what we want
- if ((whyDirty & FRAME_DIRTY_SCROLLVERT) || (intersectRects(vertClip, toDisplay))) {
- // Add vertical rect into updated area
- boundRects(updatedArea, vertClip);
-
- // Draw vertical scrollbar
- SDL_SetClipRect(destSurface, &vertClip);
- SDL_FillRect(destSurface, &vertClip, guiPacked[COLOR_SCROLLTRACK]);
- if (vScrollbarTabSize) {
- // Invert if pressed
- if ((dragMode == FRAME_DRAG_SCROLLBAR_VERT) && (dragItem == FRAME_SCROLL_TAB)) {
- drawRect(xOffset + vScrollbarX, yOffset + vScrollbarY + scrollbarButtonSize + vScrollbarTab, scrollbarButtonSize, vScrollbarTabSize, guiPacked[COLOR_FILL], destSurface);
- drawGuiBoxInvert(xOffset + vScrollbarX, yOffset + vScrollbarY + scrollbarButtonSize + vScrollbarTab, scrollbarButtonSize, vScrollbarTabSize, 2, destSurface);
- }
- else {
- drawGuiBox(xOffset + vScrollbarX, yOffset + vScrollbarY + scrollbarButtonSize + vScrollbarTab, scrollbarButtonSize, vScrollbarTabSize, 2, destSurface);
- }
- }
- // if pressed
- if ((dragMode == FRAME_DRAG_SCROLLBAR_VERT) && (dragItem == FRAME_SCROLL_LESS)) {
- // Non-gradient: drawRect(xOffset + vScrollbarX, yOffset + vScrollbarY, scrollbarButtonSize, scrollbarButtonSize, guiPacked[COLOR_FILL], destSurface);
- drawGradient(xOffset + vScrollbarX, yOffset + vScrollbarY, scrollbarButtonSize, scrollbarButtonSize, guiRGB[COLOR_BUTTONDOWN1], guiRGB[COLOR_BUTTONDOWN2], destSurface);
- drawGuiBoxInvert(xOffset + vScrollbarX, yOffset + vScrollbarY, scrollbarButtonSize, scrollbarButtonSize, 2, destSurface);
- drawText(wtButtonUp, guiRGB[COLOR_TEXT], xOffset + vScrollbarX + scrollbarButtonXPad + 1, yOffset + vScrollbarY + scrollbarButtonXPad + 1, destSurface, FONT_WIDGET);
- }
- else {
- drawGuiBox(xOffset + vScrollbarX, yOffset + vScrollbarY, scrollbarButtonSize, scrollbarButtonSize, 2, destSurface);
- // Non-gradient: nothing
- drawGradient(xOffset + vScrollbarX + 2, yOffset + vScrollbarY + 2, scrollbarButtonSize - 4, scrollbarButtonSize - 4, guiRGB[COLOR_BUTTONFILL1], guiRGB[COLOR_BUTTONFILL2], destSurface);
- drawText(wtButtonUp, guiRGB[COLOR_TEXT], xOffset + vScrollbarX + scrollbarButtonXPad, yOffset + vScrollbarY + scrollbarButtonXPad, destSurface, FONT_WIDGET);
- }
- // if pressed
- if ((dragMode == FRAME_DRAG_SCROLLBAR_VERT) && (dragItem == FRAME_SCROLL_MORE)) {
- // Non-gradient: drawRect(xOffset + vScrollbarX, yOffset + vScrollbarY + vScrollbarHeight - scrollbarButtonSize, scrollbarButtonSize, scrollbarButtonSize, guiPacked[COLOR_FILL], destSurface);
- drawGradient(xOffset + vScrollbarX, yOffset + vScrollbarY + vScrollbarHeight - scrollbarButtonSize, scrollbarButtonSize, scrollbarButtonSize, guiRGB[COLOR_BUTTONDOWN1], guiRGB[COLOR_BUTTONDOWN2], destSurface);
- drawGuiBoxInvert(xOffset + vScrollbarX, yOffset + vScrollbarY + vScrollbarHeight - scrollbarButtonSize, scrollbarButtonSize, scrollbarButtonSize, 2, destSurface);
- drawText(wtButtonDown, guiRGB[COLOR_TEXT], xOffset + vScrollbarX + scrollbarButtonXPad + 1, yOffset + vScrollbarY + vScrollbarHeight - scrollbarButtonSize + scrollbarButtonXPad + 1, destSurface, FONT_WIDGET);
- }
- else {
- drawGuiBox(xOffset + vScrollbarX, yOffset + vScrollbarY + vScrollbarHeight - scrollbarButtonSize, scrollbarButtonSize, scrollbarButtonSize, 2, destSurface);
- // Non-gradient: nothing
- drawGradient(xOffset + vScrollbarX + 2, yOffset + vScrollbarY + vScrollbarHeight - scrollbarButtonSize + 2, scrollbarButtonSize - 4, scrollbarButtonSize - 4, guiRGB[COLOR_BUTTONFILL1], guiRGB[COLOR_BUTTONFILL2], destSurface);
- drawText(wtButtonDown, guiRGB[COLOR_TEXT], xOffset + vScrollbarX + scrollbarButtonXPad, yOffset + vScrollbarY + vScrollbarHeight - scrollbarButtonSize + scrollbarButtonXPad, destSurface, FONT_WIDGET);
- }
- }
- }
- // (make sure horizontal exists before doing more work)
- if (hScrollbarY) {
- // Determine clip area for horizontal scrollbar
- Rect horizClip = { hScrollbarX + xOffset, hScrollbarY + yOffset, hScrollbarWidth, hScrollbarHeight };
- intersectRects(horizClip, clipArea);
-
- // If we need to update horizontal scroll, OR it intersects with the dirty area,
- // redraw it; note that if the second conditional is tested, vertClip will be reduced
- // to whatever portion intersects with the dirty area, which is what we want
- if ((whyDirty & FRAME_DIRTY_SCROLLHORIZ) || (intersectRects(horizClip, toDisplay))) {
- // Add horizontal rect into updated area
- boundRects(updatedArea, horizClip);
-
- // Draw horizontal scrollbar
- SDL_SetClipRect(destSurface, &horizClip);
- SDL_FillRect(destSurface, &horizClip, guiPacked[COLOR_SCROLLTRACK]);
- if (hScrollbarTabSize) {
- // Invert if pressed
- if ((dragMode == FRAME_DRAG_SCROLLBAR_VERT) && (dragItem == FRAME_SCROLL_TAB)) {
- drawRect(xOffset + hScrollbarX + scrollbarButtonSize + hScrollbarTab, yOffset + hScrollbarY, hScrollbarTabSize, scrollbarButtonSize, guiPacked[COLOR_FILL], destSurface);
- drawGuiBoxInvert(xOffset + hScrollbarX + scrollbarButtonSize + hScrollbarTab, yOffset + hScrollbarY, hScrollbarTabSize, scrollbarButtonSize, 2, destSurface);
- }
- else {
- drawGuiBox(xOffset + hScrollbarX + scrollbarButtonSize + hScrollbarTab, yOffset + hScrollbarY, hScrollbarTabSize, scrollbarButtonSize, 2, destSurface);
- }
- }
- // if pressed
- if ((dragMode == FRAME_DRAG_SCROLLBAR_HORIZ) && (dragItem == FRAME_SCROLL_LESS)) {
- // Non-gradient: drawRect(xOffset + hScrollbarX, yOffset + hScrollbarY, scrollbarButtonSize, scrollbarButtonSize, guiPacked[COLOR_FILL], destSurface);
- drawGradient(xOffset + hScrollbarX, yOffset + hScrollbarY, scrollbarButtonSize, scrollbarButtonSize, guiRGB[COLOR_BUTTONDOWN1], guiRGB[COLOR_BUTTONDOWN2], destSurface);
- drawGuiBoxInvert(xOffset + hScrollbarX, yOffset + hScrollbarY, scrollbarButtonSize, scrollbarButtonSize, 2, destSurface);
- drawText(wtButtonLeft, guiRGB[COLOR_TEXT], xOffset + hScrollbarX + scrollbarButtonXPad + 1, yOffset + hScrollbarY + scrollbarButtonXPad + 1, destSurface, FONT_WIDGET);
- }
- else {
- drawGuiBox(xOffset + hScrollbarX, yOffset + hScrollbarY, scrollbarButtonSize, scrollbarButtonSize, 2, destSurface);
- // Non-gradient: nothing
- drawGradient(xOffset + hScrollbarX + 2, yOffset + hScrollbarY + 2, scrollbarButtonSize - 4, scrollbarButtonSize - 4, guiRGB[COLOR_BUTTONFILL1], guiRGB[COLOR_BUTTONFILL2], destSurface);
- drawText(wtButtonLeft, guiRGB[COLOR_TEXT], xOffset + hScrollbarX + scrollbarButtonXPad, yOffset + hScrollbarY + scrollbarButtonXPad, destSurface, FONT_WIDGET);
- }
- // if pressed
- if ((dragMode == FRAME_DRAG_SCROLLBAR_HORIZ) && (dragItem == FRAME_SCROLL_MORE)) {
- // Non-gradient: drawRect(xOffset + hScrollbarX + hScrollbarWidth - scrollbarButtonSize, yOffset + hScrollbarY, scrollbarButtonSize, scrollbarButtonSize, guiPacked[COLOR_FILL], destSurface);
- drawGradient(xOffset + hScrollbarX + hScrollbarWidth - scrollbarButtonSize, yOffset + hScrollbarY, scrollbarButtonSize, scrollbarButtonSize, guiRGB[COLOR_BUTTONDOWN1], guiRGB[COLOR_BUTTONDOWN2], destSurface);
- drawGuiBoxInvert(xOffset + hScrollbarX + hScrollbarWidth - scrollbarButtonSize, yOffset + hScrollbarY, scrollbarButtonSize, scrollbarButtonSize, 2, destSurface);
- drawText(wtButtonRight, guiRGB[COLOR_TEXT], xOffset + hScrollbarX + hScrollbarWidth - scrollbarButtonSize + scrollbarButtonXPad + 1, yOffset + hScrollbarY + scrollbarButtonXPad + 1, destSurface, FONT_WIDGET);
- }
- else {
- drawGuiBox(xOffset + hScrollbarX + hScrollbarWidth - scrollbarButtonSize, yOffset + hScrollbarY, scrollbarButtonSize, scrollbarButtonSize, 2, destSurface);
- // Non-gradient: nothing
- drawGradient(xOffset + hScrollbarX + hScrollbarWidth - scrollbarButtonSize + 2, yOffset + hScrollbarY + 2, scrollbarButtonSize - 4, scrollbarButtonSize - 4, guiRGB[COLOR_BUTTONFILL1], guiRGB[COLOR_BUTTONFILL2], destSurface);
- drawText(wtButtonRight, guiRGB[COLOR_TEXT], xOffset + hScrollbarX + hScrollbarWidth - scrollbarButtonSize + scrollbarButtonXPad, yOffset + hScrollbarY + scrollbarButtonXPad, destSurface, FONT_WIDGET);
- }
- }
- }
- // Fill in corner?
- if ((vScrollbarX) && (hScrollbarY)) {
- Rect cornerClip = { vScrollbarX + xOffset, hScrollbarY + yOffset, vScrollbarWidth, hScrollbarHeight };
- intersectRects(cornerClip, clipArea);
- // Only needed if area is dirty
- if (intersectRects(cornerClip, toDisplay)) {
- // We set clip because it may have been reset earlier
- SDL_SetClipRect(destSurface, &cornerClip);
- SDL_FillRect(destSurface, &cornerClip, guiPacked[COLOR_FILL]);
- }
- }
- // Panel areas?
- int max = clientArea.size();
- for (int pos = 1; pos < max; ++pos) {
- if ((!(clientArea[pos].position & CLIENT_NOTMANAGED)) && (clientArea[pos].window)) {
- // Panel area that CAN be drawn
- Rect panelClip = { clientArea[pos].x + xOffset, clientArea[pos].y + yOffset, clientArea[pos].widthShown, clientArea[pos].heightShown };
- intersectRects(panelClip, clipArea);
- // Panel area that MUST be drawn
- Rect panelDirty = panelClip;
- // If we need to update panel, OR it intersects with the dirty area, redraw it
- // We test dirty first, because we always want the dirty area to be what
- // the panel HAS to update, even if they're dirty...
- if ((intersectRects(panelDirty, toDisplay)) || (clientArea[pos].window->isDirty())) {
- // ... but we clip to a wider area- the area the panel CAN update
- SDL_SetClipRect(destSurface, &panelClip);
- // Background fill on dirty area
- SDL_FillRect(destSurface, &panelDirty, guiPacked[COLOR_FILL]);
- // Paint panel area
- clientArea[pos].window->display(destSurface, panelDirty, panelClip, xOffset, yOffset);
- // Add panel rect into updated area
- boundRects(updatedArea, panelDirty);
- }
- }
- }
- // Client area exists? (done separate due to 'inner' setting)
- if ((clientWidthInner > 0) && (clientHeightInner > 0)) {
- // Client area that CAN be drawn
- Rect clientClip = { clientArea[0].x + xOffset, clientArea[0].y + yOffset, clientWidthInner, clientHeightInner };
- intersectRects(clientClip, clipArea);
-
- // Client area that MUST be drawn
- Rect clientDirty = clientClip;
-
- // If we need to update client, OR it intersects with the dirty area, redraw it
- int clientIsDirty = 0;
- if ((clientArea[0].window) && (clientArea[0].window->isDirty())) clientIsDirty = 1;
- // We test dirty first, because we always want the dirty area to be what
- // the client HAS to update, even if they're dirty...
- if ((intersectRects(clientDirty, toDisplay)) || (clientIsDirty)) {
- // ... but we clip to a wider area- the area the client CAN update
- SDL_SetClipRect(destSurface, &clientClip);
-
- // Background fill on dirty area
- SDL_FillRect(destSurface, &clientDirty, guiPacked[frameType == FRAMETYPE_BEVEL_BK ? COLOR_BKFILL : frameType == FRAMETYPE_BEVEL_TEXT ? COLOR_TEXTBOX : COLOR_FILL]);
- // Paint client area
- if (clientArea[0].window) {
- clientArea[0].window->display(destSurface, clientDirty, clientClip, xOffset, yOffset);
- // Add client rect into updated area
- boundRects(updatedArea, clientDirty);
- }
- }
- }
-
- // Float target?
- if (floatTarget) {
- SDL_SetClipRect(destSurface, &toDisplay);
- drawSelectRect(xOffset + floatTargetX, yOffset + floatTargetY, floatTargetWidth, floatTargetHeight, guiPacked[COLOR_SELECTION1], destSurface);
- }
-
- toDisplay = updatedArea;
- }
- dirty = 0;
- childDirty = 0;
- whyDirty = FRAME_DIRTY_NONE;
- }
- /* Not currently used or supported
- int FrameWindow::usesAlpha() { start_func
- int uses = 0;
- for (int cl = 0; cl <= 2; ++cl) {
- if (clientArea[cl].window) uses = uses || clientArea[cl].window->usesAlpha();
- }
- return uses;
- }
- */
- Window::WindowSort FrameWindow::windowSort() const { start_func
- if (clientArea[0].window != NULL) return clientArea[0].window->windowSort();
- return WINDOWSORT_NORMAL;
- }
- Window::CommandSupport FrameWindow::supportsCommand(int code) const { start_func
- // Frame window commands
- if (code == WINDOW_MIN) return ((state == FRAME_STATE_MINIMIZED) || strchr(titlebarButtons, 'h')) ? Window::COMMAND_ENABLE : Window::COMMAND_DISABLE;
- if (code == WINDOW_MAX) return ((state == FRAME_STATE_MAXIMIZED) || strchr(titlebarButtons, 'g')) ? Window::COMMAND_ENABLE : Window::COMMAND_DISABLE;
- if (code == WINDOW_SWITCHPANEL) {
- int max = clientArea.size();
- for (int pos = 1; pos < max; ++pos) {
- if (clientArea[pos].window) {
- // @TODO: should this also work on floating/desktop panels?
- if (!(clientArea[pos].position & CLIENT_NOTMANAGED)) return Window::COMMAND_ENABLE;
- }
- }
- return Window::COMMAND_HIDE;
- }
- // @TODO: VIEW_TOOLPANEL/VIEW_* to toggle panel visibility
- if ((code == WINDOW_CLOSE) || (code == WINDOW_NEXT) || (code == WINDOW_PREV) ||
- (code == WINDOW_CLOSEALL) || (code == WINDOW_CLOSEALLBUT) || (code == WINDOW_TILEHORIZ) ||
- (code == WINDOW_TILEVERT) || (code == WINDOW_CASCADE)) return Window::COMMAND_ENABLE;
- CommandSupport uses = Window::COMMAND_HIDE;
- vector<ClientArea>::const_iterator end = clientArea.end();
- for (vector<ClientArea>::const_iterator pos = clientArea.begin(); pos != clientArea.end(); ++pos) {
- if ((*pos).window) {
- if (uses == Window::COMMAND_HIDE) uses = (*pos).window->supportsCommand(code);
- else {
- CommandSupport sc = (*pos).window->supportsCommand(code);
- if (sc & Window::COMMAND_ENABLE) return sc;
- }
- }
- }
- return uses;
- }
- int FrameWindow::wantsToBeDeleted() const { start_func
- return deleteMe;
- }
- void FrameWindow::setWantsToBeDeleted(int fDeleteMe) { start_func
- deleteMe = fDeleteMe;
- }
- int FrameWindow::attemptClose() { start_func
- if (clientArea[0].window != NULL) {
- return clientArea[0].window->attemptClose();
- }
- return 1;
- }
- void FrameWindow::scrollToView(int sX, int sY, int sWidth, int sHeight) { start_func
- int cX = -scrollX;
- int cY = -scrollY;
- // Don't adjust left-right if target encompasses entire view
- if ((sX > cX) || (sX + sWidth < cX + clientWidthInner)) {
- // If right-most edge of target is to the right of us, scroll to see it
- if (sX + sWidth > cX + clientWidthInner) cX = sX + sWidth - clientWidthInner;
-
- // Same for left
- if (sX < cX) cX = sX;
- }
- // Don't adjust up-down if target encompasses entire view
- if ((sY > cY) || (sY + sHeight < cY + clientHeightInner)) {
- // Same for bottom, top
- if (sY + sHeight > cY + clientHeightInner) cY = sY + sHeight - clientHeightInner;
- if (sY < cY) cY = sY;
- }
-
- // Complete scroll
- scrollTo(-cX, -cY);
- }
- void FrameWindow::scrollBy(int sX, int sY) { start_func
- scrollTo(scrollX + sX, scrollY + sY);
- }
- void FrameWindow::scrollTo(int sX, int sY, int tabX, int tabY) { start_func
- if (clientArea[0].window) {
- // Not too far in either direction
- if (sX < min(0, clientWidthInner - clientActualWidth)) sX = min(0, clientWidthInner - clientActualWidth);
- if (sY < min(0, clientHeightInner - clientActualHeight)) sY = min(0, clientHeightInner - clientActualHeight);
- // Check this direction last in case window is too large overall
- // Only allow scrolling "positive" if autocenter enabled
- if (autoCenterScroll) {
- if (sX > max(0, clientWidthInner - clientActualWidth)) sX = max(0, clientWidthInner - clientActualWidth);
- if (sY > max(0, clientHeightInner - clientActualHeight)) sY = max(0, clientHeightInner - clientActualHeight);
- }
- else {
- if (sX > 0) sX = 0;
- if (sY > 0) sY = 0;
- }
-
- // Tab positions
- if ((vScrollbarTabSize) && (clientHeightInner < clientActualHeight)) {
- int newTab;
- if (tabY >= 0) newTab = tabY;
- else newTab = (vScrollbarHeight - (scrollbarButtonSize * 2) - vScrollbarTabSize) * sY / (clientHeightInner - clientActualHeight);
- if (newTab != vScrollbarTab) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLVERT;
- }
- vScrollbarTab = newTab;
- }
- else {
- if (vScrollbarTab != 0) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLVERT;
- }
- vScrollbarTab = 0;
- }
- if ((hScrollbarTabSize) && (clientWidthInner < clientActualWidth)) {
- int newTab;
- if (tabX >= 0) newTab = tabX;
- else newTab = (hScrollbarWidth - (scrollbarButtonSize * 2) - hScrollbarTabSize) * sX / (clientWidthInner - clientActualWidth);
- if (newTab != hScrollbarTab) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLHORIZ;
- }
- hScrollbarTab = newTab;
- }
- else {
- if (hScrollbarTab != 0) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLHORIZ;
- }
- hScrollbarTab = 0;
- }
-
- if ((scrollX != sX) || (scrollY != sY)) {
- scrollX = sX;
- scrollY = sY;
- clientArea[0].window->move(clientArea[0].x + scrollX, clientArea[0].y + scrollY);
- }
- }
- else {
- // No client, no scrollbars- reset to zero- dirty if wasn't already at zero
- if ((scrollX) || (scrollY)) {
- setDirty();
- whyDirty = FRAME_DIRTY_ALL;
- }
- scrollX = scrollY = 0;
- }
- }
- void FrameWindow::confineSize(int& sX, int& sY, int& sWidth, int& sHeight) const { start_func
- int clipX, clipY, clipW, clipH;
-
- // Size is not confined by us if we aren't on desktop
- if ((parent != desktop) && (parent != NULL)) return;
- if (windowSort() >= WINDOWSORT_MODAL) {
- clipX = 0;
- clipY = 0;
- clipW = screenWidth;
- clipH = screenHeight;
- }
- else {
- clipX = desktop->desktopX();
- clipY = desktop->desktopY();
- clipW = desktop->desktopWidth();
- clipH = desktop->desktopHeight();
- }
- // Ensure fits on-screen
- if (sX + sWidth > clipX + clipW) {
- sX = clipX + clipW - sWidth;
- }
- if (sX < clipX) {
- sX = clipX;
- if (sWidth > clipW) sWidth = clipW;
- }
- if (sY + sHeight > clipY + clipH) {
- sY = clipY + clipH - sHeight;
- }
- if (sY < clipY) {
- sY = clipY;
- if (sHeight > clipH) sHeight = clipH;
- }
-
- // Ensure at least minimum size
- if (sHeight < (titlebarHeight + 2 * outerBorder)) {
- sHeight = (titlebarHeight + 2 * outerBorder);
- }
- if (sWidth < (outerBorder * 2 + 2 + titlebarButtonTotalWidth)) {
- sWidth = (outerBorder * 2 + 2 + titlebarButtonTotalWidth);
- }
- }
- void FrameWindow::show(int xPos, int yPos, int fWidth, int fHeight) { start_func
- assert(xPos >= SHOW_CURRMIN);
- assert(yPos >= SHOW_CURRMIN);
- assert(fWidth >= SHOW_CURRMIN);
- assert(fHeight >= SHOW_CURRMIN);
- int cascadeOffset = outerBorder + titlebarHeight;
- if (fWidth == SHOW_CASCADE) fWidth = desktop->desktopWidth() - cascadeOffset * 3;
- if (fHeight == SHOW_CASCADE) fHeight = desktop->desktopHeight() - cascadeOffset * 3;
- if (fWidth == SHOW_CURRENT) fWidth = width;
- if (fHeight == SHOW_CURRENT) fHeight = height;
- if (fWidth == SHOW_CURRMIN) {
- fWidth = width;
- if (fWidth < DEFAULT_MIN_WIDTH) fWidth = DEFAULT_MIN_WIDTH;
- }
- if (fHeight == SHOW_CURRMIN) {
- fHeight = height;
- if (fHeight < DEFAULT_MIN_HEIGHT) fHeight = DEFAULT_MIN_HEIGHT;
- }
- if ((xPos == SHOW_CASCADE) || (yPos == SHOW_CASCADE)) {
- if (++cascadeStep > 3) cascadeStep = 0;
- }
- if (xPos == SHOW_CASCADE) {
- xPos = desktop->desktopX() + cascadeStep * cascadeOffset;
- }
- if (yPos == SHOW_CASCADE) {
- yPos = desktop->desktopY() + cascadeStep * cascadeOffset;
- }
- if ((xPos == SHOW_CURRENT) || (xPos == SHOW_CURRMIN)) xPos = x;
- if ((yPos == SHOW_CURRENT) || (yPos == SHOW_CURRMIN)) yPos = y;
- confineSize(xPos, yPos, fWidth, fHeight);
- // Move
- resize(fWidth, fHeight);
- move(xPos, yPos);
- desktop->addWindow(this, 1);
- }
- void FrameWindow::hide() { start_func
- // If we aren't part of desktop, this is harmless
- desktop->removeWindow(this);
- }
- void FrameWindow::undoNotify(int undoType, int undoItemId, int undoItemSubId, int uX, int uY, int uW, int uH) { start_func
- if (clientArea[0].window) clientArea[0].window->undoNotify(undoType, undoItemId, undoItemSubId, uX, uY, uW, uH);
- }
- const char* FrameWindow::tooltip(int xPos, int yPos) const { start_func
- DragType toolType;
- DragSubType toolItem;
- whereCoords(xPos, yPos, &toolType, &toolItem);
-
- if (toolType == FRAME_DRAG_CLIENT) {
- xPos -= clientArea[toolItem].x;
- yPos -= clientArea[toolItem].y;
- if (toolItem == 0) {
- xPos += scrollX;
- yPos += scrollY;
- }
- return clientArea[toolItem].window->tooltip(xPos, yPos);
- }
-
- if (toolType == FRAME_DRAG_BUTTONS) {
- switch (titlebarButtons[toolItem - 1]) {
- case 'h':
- return "Roll-up window (minimize)";
-
- case 'g':
- return "Maximize window";
-
- case 'f':
- return "Close window";
-
- case 'j':
- return "Restore window";
- }
- }
- return NULL;
- }
- void FrameWindow::whereCoords(int x, int y, DragType* dragType, DragSubType* dragItem) const { start_func
- assert(dragType);
- assert(dragItem);
- *dragType = FRAME_DRAG_NONE;
- *dragItem = FRAME_RESIZE_NONE;
- // Main client area? Client *can* receive clicks outside it's actual area
- if ((clientArea[0].window) &&
- (x >= clientArea[0].x) &&
- (y >= clientArea[0].y) &&
- (x < clientArea[0].x + clientWidthInner) &&
- (y < clientArea[0].y + clientHeightInner)) {
- *dragType = FRAME_DRAG_CLIENT;
- *dragItem = (DragSubType)0;
- }
- // Buttons?
- // (check before titlebar as space is shared)
- else if ((titlebarType != TITLEBAR_OFF) &&
- (x >= titlebarButtonX) &&
- (y >= titlebarButtonY) &&
- (x < titlebarButtonX + titlebarButtonTotalWidth) &&
- (y < titlebarButtonY + titlebarButtonSize)) {
- *dragType = FRAME_DRAG_BUTTONS;
- // (add 1 because 0 is a 'none' value)
- *dragItem = (DragSubType)((x - titlebarButtonX) / titlebarButtonSize + 1);
- }
- // Titlebar?
- else if ((titlebarType != TITLEBAR_OFF) &&
- (x >= titlebarX) &&
- (y >= titlebarY) &&
- (x < titlebarX + titlebarWidth) &&
- (y < titlebarY + titlebarHeight)) {
- *dragType = FRAME_DRAG_TITLE;
- }
- // Vertical scrollbar?
- else if ((x >= vScrollbarX) &&
- (x < vScrollbarX + vScrollbarWidth) &&
- (y >= vScrollbarY) &&
- (y < vScrollbarY + vScrollbarHeight)) {
- *dragType = FRAME_DRAG_SCROLLBAR_VERT;
-
- if (y < vScrollbarY + scrollbarButtonSize) *dragItem = FRAME_SCROLL_LESS;
- else if (y >= vScrollbarY + vScrollbarHeight - scrollbarButtonSize) *dragItem = FRAME_SCROLL_MORE;
- else if (y < vScrollbarY + scrollbarButtonSize + vScrollbarTab) *dragItem = FRAME_SCROLL_PAGELESS;
- else if (y >= vScrollbarY + scrollbarButtonSize + vScrollbarTab + vScrollbarTabSize) *dragItem = FRAME_SCROLL_PAGEMORE;
- else *dragItem = FRAME_SCROLL_TAB;
- }
- // Horizontal scrollbar?
- else if ((x >= hScrollbarX) &&
- (x < hScrollbarX + hScrollbarWidth) &&
- (y >= hScrollbarY) &&
- (y < hScrollbarY + hScrollbarHeight)) {
- *dragType = FRAME_DRAG_SCROLLBAR_HORIZ;
- if (x < hScrollbarX + scrollbarButtonSize) *dragItem = FRAME_SCROLL_LESS;
- else if (x >= hScrollbarX + hScrollbarWidth - scrollbarButtonSize) *dragItem = FRAME_SCROLL_MORE;
- else if (x < hScrollbarX + scrollbarButtonSize + hScrollbarTab) *dragItem = FRAME_SCROLL_PAGELESS;
- else if (x >= hScrollbarX + scrollbarButtonSize + hScrollbarTab + hScrollbarTabSize) *dragItem = FRAME_SCROLL_PAGEMORE;
- else *dragItem = FRAME_SCROLL_TAB;
- }
- else {
- // Tool panels?
- int max = clientArea.size();
- for (int pos = 1; pos < max; ++pos) {
- if (clientArea[pos].window) {
- if (!(clientArea[pos].position & CLIENT_NOTMANAGED)) {
- if ((x >= clientArea[pos].x) &&
- (y >= clientArea[pos].y) &&
- (x < clientArea[pos].x + clientArea[pos].widthShown) &&
- (y < clientArea[pos].y + clientArea[pos].heightShown) &&
- (x < clientArea[pos].x + clientArea[pos].window->getWidth()) &&
- (y < clientArea[pos].y + clientArea[pos].window->getHeight())) {
- *dragType = FRAME_DRAG_CLIENT;
- *dragItem = (DragSubType)pos;
- return;
- }
- }
- }
- }
-
- // Resize?
- // (no resizing when maximized, minimized, no border, or prevented)
- if (state != FRAME_STATE_NORMAL) return;
- if ((!resizable) || (!outerBorder)) return;
- DragSubType resizing = FRAME_RESIZE_NONE;
- int sensitive = outerBorder + FRAME_INNERBORDER;
- if ((y >= 0) && (y < sensitive)) {
- resizing = (DragSubType)(resizing | FRAME_RESIZE_TOP);
- sensitive = RESIZE_CORNER_SENSITIVITY;
- }
- if ((y >= height - sensitive) && (y < height)) {
- resizing = (DragSubType)(resizing | FRAME_RESIZE_BOTTOM);
- sensitive = RESIZE_CORNER_SENSITIVITY;
- }
- if ((x >= 0) && (x < sensitive)) {
- resizing = (DragSubType)(resizing | FRAME_RESIZE_LEFT);
- sensitive = RESIZE_CORNER_SENSITIVITY;
- }
- if ((x >= width - sensitive) && (x < width)) {
- resizing = (DragSubType)(resizing | FRAME_RESIZE_RIGHT);
- sensitive = RESIZE_CORNER_SENSITIVITY;
- }
- // Redo the Ys due to possibile sensitivity change from finding an X match
- if ((y >= 0) && (y < sensitive))
- resizing = (DragSubType)(resizing | FRAME_RESIZE_TOP);
- if ((y >= height - sensitive) && (y < height))
- resizing = (DragSubType)(resizing | FRAME_RESIZE_BOTTOM);
- if (resizing) {
- *dragType = FRAME_DRAG_BORDER;
- *dragItem = resizing;
- }
- }
- }
- int FrameWindow::event(int hasFocus, const SDL_Event* event) { start_func
- assert(event);
- DragType newDragMode;
- DragSubType newDragItem;
- int pos;
- int used = 0;
- Uint32 ticks;
- int mX, mY;
- int done = 0;
- Window* exempt = NULL;
-
- // We need to copy the event if we expect to change it to send a copy to client
- SDL_Event clientEvent = *event;
- switch (event->type) {
- case SDL_CLOSE:
- // Close client(s), then us
- for (pos = 0; pos < (int)clientArea.size(); ++pos) {
- if (clientArea[pos].window) {
- // Shouldn't delete itself here
- clientArea[pos].window->event(hasFocus && (subFocus == pos), &clientEvent);
- // Prevent it from notifying us when it DOES delete itself ("we know")
- clientArea[pos].window->setParent(NULL);
- clientArea[pos].window->setParentNotify(NULL);
- if (clientArea[pos].window->wantsToBeDeleted()) delete clientArea[pos].window;
- clientArea[pos].window = NULL;
- }
- }
-
- if (parent == desktop) {
- desktop->removeWindow(this);
- // Make sure next frame window is selected
- pos = 0;
- while (desktop->findWindow(WINDOW_FRAME, pos) != NULL) {
- ++pos;
- }
- if (--pos >= 0) {
- desktop->bringToTop(desktop->findWindow(WINDOW_FRAME, pos));
- }
- }
- return 1;
-
- case SDL_MOUSEBUTTONUP:
- if (dragMode == FRAME_DRAG_CLIENT) {
- // Adjust coordinates to 0-based for client
- if (clientArea[dragItem].window) {
- clientEvent.button.x -= clientArea[dragItem].x + (dragItem == 0 ? scrollX : 0);
- clientEvent.button.y -= clientArea[dragItem].y + (dragItem == 0 ? scrollY : 0);
- // Propogate to client
- clientArea[dragItem].window->event(hasFocus && (subFocus == dragItem), &clientEvent);
- }
-
- if ((SDL_GetMouseState(NULL, NULL) & (SDL_BUTTON_LMASK | SDL_BUTTON_RMASK)) == 0) done = 1;
- }
- else if (event->button.button == SDL_BUTTON_LEFT) {
- // Button pressed?
- if ((dragMode == FRAME_DRAG_BUTTONS) && (dragItem)) {
- switch (titlebarButtons[(int)(dragItem - 1)]) {
- case 'h':
- minimize();
- break;
-
- case 'g':
- maximize();
- break;
-
- case 'f':
- closeWindow(); // Calls attemptClose
- break;
-
- case 'j':
- restore();
- break;
- }
- setDirty();
- whyDirty |= FRAME_DIRTY_TITLE;
- }
- else if (dragMode == FRAME_DRAG_SCROLLBAR_HORIZ) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLHORIZ;
- }
- else if (dragMode == FRAME_DRAG_SCROLLBAR_VERT) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLVERT;
- }
- else if (dragMode == FRAME_DRAG_TITLE) {
- if ((framePanel) && (parent == desktop)) {
- int index = framePanel->findToolPanel(this);
- if (index) framePanel->dragFloatPanel(index, 1);
- }
- }
-
- done = 1;
- }
-
- if (done) {
- scrollRepeatTicks = scrollRepeatDelay = 0;
- dragMode = FRAME_DRAG_NONE;
- doMouseHover(event->motion.x, event->motion.y, hasFocus, clientEvent);
- }
- break;
-
- case SDL_MOUSEBUTTONDBL:
- case SDL_MOUSEBUTTONDOWN:
- // Dragging/clicking what?
- whereCoords(event->button.x, event->button.y, &newDragMode, &newDragItem);
-
- if (newDragMode == FRAME_DRAG_CLIENT) {
- // No focus or drag on wheels
- if ((event->button.button != SDL_BUTTON_WHEELUP) &&
- (event->button.button != SDL_BUTTON_WHEELDOWN)) {
- dragMode = newDragMode;
- dragItem = newDragItem;
- focusToolPanel(dragItem);
- }
- // Adjust coordinates to 0-based for client
- if (clientArea[newDragItem].window) {
- clientEvent.button.x -= clientArea[newDragItem].x + (newDragItem == 0 ? scrollX : 0);
- clientEvent.button.y -= clientArea[newDragItem].y + (newDragItem == 0 ? scrollY : 0);
- // Propogate to client
- if (!clientArea[newDragItem].window->event(hasFocus && (subFocus == newDragItem), &clientEvent)) {
- // If not used, handle mouse wheel ourselves
- if ((newDragItem == 0) && (clientActualHeight > clientHeightInner)) {
- if (event->button.button == SDL_BUTTON_WHEELUP) {
- scrollTo(scrollX, scrollY + vScrollPage);
- }
- else if (event->button.button == SDL_BUTTON_WHEELDOWN) {
- scrollTo(scrollX, scrollY - vScrollPage);
- }
- }
- }
- }
- }
- else if ((event->type == SDL_MOUSEBUTTONDBL) && (newDragMode == FRAME_DRAG_TITLE)) {
- if ((state == FRAME_STATE_MINIMIZED) || (state == FRAME_STATE_MAXIMIZED)) restore();
- else minimize();
- }
- else if (((event->button.button == SDL_BUTTON_WHEELUP) || (event->button.button == SDL_BUTTON_WHEELDOWN)) &&
- ((newDragMode == FRAME_DRAG_SCROLLBAR_VERT) || (newDragMode == FRAME_DRAG_SCROLLBAR_HORIZ))) {
- if (newDragMode == FRAME_DRAG_SCROLLBAR_VERT) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLVERT;
- if (event->button.button == SDL_BUTTON_WHEELUP) scrollTo(scrollX, scrollY + vScrollPage);
- else if (event->button.button == SDL_BUTTON_WHEELDOWN) scrollTo(scrollX, scrollY - vScrollPage);
- }
- if (newDragMode == FRAME_DRAG_SCROLLBAR_HORIZ) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLHORIZ;
- if (event->button.button == SDL_BUTTON_WHEELUP) scrollTo(scrollX + hScrollPage, scrollY);
- else if (event->button.button == SDL_BUTTON_WHEELDOWN) scrollTo(scrollX - hScrollPage, scrollY);
- }
- }
- else if (event->button.button == SDL_BUTTON_LEFT) {
- if (newDragMode == FRAME_DRAG_SCROLLBAR_VERT) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLVERT;
- scrollRepeatTicks = SDL_GetTicks();
- scrollRepeatDelay = DELAY_SCROLLBAR_REPEATSTART;
- if (newDragItem == FRAME_SCROLL_LESS) scrollTo(scrollX, scrollY + vScrollLine);
- else if (newDragItem == FRAME_SCROLL_MORE) scrollTo(scrollX, scrollY - vScrollLine);
- else if (newDragItem == FRAME_SCROLL_PAGELESS) scrollTo(scrollX, scrollY + vScrollPage);
- else if (newDragItem == FRAME_SCROLL_PAGEMORE) scrollTo(scrollX, scrollY - vScrollPage);
- // Force mouse motion to determine new drag mode
- SDL_GetMouseState(&mX, &mY);
- SDL_WarpMouse(mX, mY);
- }
- if (newDragMode == FRAME_DRAG_SCROLLBAR_HORIZ) {
- setDirty();
- whyDirty |= FRAME_DIRTY_SCROLLHORIZ;
- scrollRepeatTicks = SDL_GetTicks();
- scrollRepeatDelay = DELAY_SCROLLBAR_REPEATSTART;
- if (newDragItem == FRAME_SCROLL_LESS) scrollTo(scrollX + hScrollLine, scrollY);
- else if (newDragItem == FRAME_SCROLL_MORE) scrollTo(scrollX - hScrollLine, scrollY);
- else if (newDragItem == FRAME_SCROLL_PAGELESS) scrollTo(scrollX + hScrollPage, scrollY);
- else if (newDragItem == FRAME_SCROLL_PAGEMORE) scrollTo(scrollX - hScrollPage, scrollY);
- // Force mouse motion to determine new drag mode
- SDL_GetMouseState(&mX, &mY);
- SDL_WarpMouse(mX, mY);
- }
- if (newDragMode == FRAME_DRAG_BUTTONS) {
- setDirty();
- whyDirty |= FRAME_DIRTY_TITLE;
- }
- dragMode = newDragMode;
- dragItem = newDragItem;
- dragX = event->button.x;
- dragY = event->button.y;
- dragItemOverflowX = 0;
- dragItemOverflowY = 0;
- }
- break;
-
- case SDL_MOUSEFOCUS:
- // We pay attention to MOUSEMOTION; we don't propogate MOUSEFOCUS
- // gain but we must alert client to loss
- if ((hoverMode == FRAME_DRAG_CLIENT) && (clientArea[hoverItem].window)) {
- // Lose focus
- SDL_Event customEvent;
- customEvent.type = SDL_MOUSEFOCUS;
- customEvent.user.code = 0;
- customEvent.user.data1 = NULL;
- customEvent.user.data2 = NULL;
- clientArea[hoverItem].window->event(hasFocus && (subFocus == hoverItem), &customEvent);
- }
- hoverMode = FRAME_DRAG_NONE;
- break;
- case SDL_MOUSEMOTION:
- if (dragMode == FRAME_DRAG_CLIENT) {
- // Adjust coordinates to 0-based for client
- if (clientArea[dragItem].window) {
- clientEvent.motion.x -= clientArea[dragItem].x + (dragItem == 0 ? scrollX : 0);
- clientEvent.motion.y -= clientArea[dragItem].y + (dragItem == 0 ? scrollY : 0);
- // Propogate to client
- clientArea[dragItem].window->event(hasFocus && (subFocus == dragItem), &clientEvent);
- }
- }
- else if (event->motion.state & SDL_BUTTON_LMASK) {
- // These are only used if dragging within desktop
- int clipX, clipY, clipW, clipH;
-
- if (windowSort() >= WINDOWSORT_MODAL) {
- clipX = 0;
- clipY = 0;
- clipW = screenWidth;
- clipH = screenHeight;
- }
- else {
- clipX = desktop->desktopX();
- clipY = desktop->desktopY();
- clipW = desktop->desktopX() + desktop->desktopWidth();
- clipH = desktop->desktopY() + desktop->desktopHeight();
- }
- // Drag title?
- // (no moving when maximized)
- if ((dragMode == FRAME_DRAG_TITLE) && (state != FRAME_STATE_MAXIMIZED)) {
- if (parent == desktop) {
- int newX = x + event->motion.xrel;
- int newY = y + event->motion.yrel;
- // Overflow
- if (dragItemOverflowY) {
- newY += dragItemOverflowY;
- dragItemOverflowY = 0;
- }
- if (dragItemOverflowX) {
- newX += dragItemOverflowX;
- dragItemOverflowX = 0;
- }
- if (newY + height > clipH) {
- dragItemOverflowY = newY + height - clipH;
- newY -= dragItemOverflowY;
- }
- if (newY < clipY) {
- dragItemOverflowY = newY - clipY;
- newY = clipY;
- }
- if (newX + width > clipW) {
- dragItemOverflowX = newX + width - clipW;
- newX -= dragItemOverflowX;
- }
- if (newX < clipX) {
- dragItemOverflowX = newX - clipX;
- newX = clipX;
- }
- move(newX, newY);
-
- if (framePanel) {
- int index = framePanel->findToolPanel(this);
- if (index) framePanel->dragFloatPanel(index, 0);
- }
- }
- else if (framePanel) {
- int index = framePanel->findToolPanel(this);
- if (index) framePanel->dragToolPanel(index, event->motion.xrel, event->motion.yrel, dragItemOverflowX, dragItemOverflowY);
- }
- }
- // Tab?
- else if ((dragMode == FRAME_DRAG_SCROLLBAR_HORIZ) &&
- (dragItem == FRAME_SCROLL_TAB)) {
- int newX = hScrollbarTab + event->motion.xrel;
- // Overflow
- if (dragItemOverflowX) {
- newX += dragItemOverflowX;
- dragItemOverflowX = 0;
- }
- if (newX + hScrollbarTabSize > (hScrollbarWidth - scrollbarButtonSize * 2)) {
- dragItemOverflowX = newX + hScrollbarTabSize - (hScrollbarWidth - scrollbarButtonSize * 2);
- newX -= dragItemOverflowX;
- }
- if (newX < 0) {
- dragItemOverflowX = newX;
- newX = 0;
- }
-
- // Scroll to right spot
- scrollTo(newX * (clientWidthInner - clientActualWidth) / (hScrollbarWidth - (scrollbarButtonSize * 2) - hScrollbarTabSize), scrollY, newX, -1);
- }
- else if ((dragMode == FRAME_DRAG_SCROLLBAR_VERT) &&
- (dragItem == FRAME_SCROLL_TAB)) {
- int newY = vScrollbarTab + event->motion.yrel;
- // Overflow
- if (dragItemOverflowY) {
- newY += dragItemOverflowY;
- dragItemOverflowY = 0;
- }
- if (newY + vScrollbarTabSize > (vScrollbarHeight - scrollbarButtonSize * 2)) {
- dragItemOverflowY = newY + vScrollbarTabSize - (vScrollbarHeight - scrollbarButtonSize * 2);
- newY -= dragItemOverflowY;
- }
- if (newY < 0) {
- dragItemOverflowY = newY;
- newY = 0;
- }
-
- // Scroll to right spot
- scrollTo(scrollX, newY * (clientHeightInner - clientActualHeight) / (vScrollbarHeight - (scrollbarButtonSize * 2) - vScrollbarTabSize), -1, newY);
- }
- // Buttons or scrollbar?
- else if ((dragMode == FRAME_DRAG_BUTTONS) ||
- (dragMode == FRAME_DRAG_SCROLLBAR_HORIZ) ||
- (dragMode == FRAME_DRAG_SCROLLBAR_VERT)) {
- whereCoords(event->motion.x, event->motion.y, &newDragMode, &newDragItem);
- if (dragMode == newDragMode) {
- if (dragItem != newDragItem) {
- dragItem = newDragItem;
- setDirty();
- if (dragMode == FRAME_DRAG_BUTTONS) whyDirty |= FRAME_DIRTY_TITLE;
- else if (dragMode == FRAME_DRAG_SCROLLBAR_HORIZ) whyDirty |= FRAME_DIRTY_SCROLLHORIZ;
- else whyDirty |= FRAME_DIRTY_SCROLLVERT;
- }
- }
- else {
- if (dragItem != FRAME_RESIZE_NONE) {
- dragItem = FRAME_RESIZE_NONE;
- setDirty();
- if (dragMode == FRAME_DRAG_BUTTONS) whyDirty |= FRAME_DIRTY_TITLE;
- else if (dragMode == FRAME_DRAG_SCROLLBAR_HORIZ) whyDirty |= FRAME_DIRTY_SCROLLHORIZ;
- else whyDirty |= FRAME_DIRTY_SCROLLVERT;
- }
- }
- }
- // Resize?
- else if (dragMode == FRAME_DRAG_BORDER) {
- if (parent == desktop) {
- int newHeight = height;
- int newWidth = width;
- int newX = x;
- int newY = y;
- // 2 = titlebar inner border (1) times two
- int minWidth = outerBorder * 2 + 2 + titlebarButtonTotalWidth;
- int minHeight = outerBorder * 2 + FRAME_INNERBORDER * 2 + titlebarHeight;
- // Only apply changes as appropriate
- // Bottom
- if (dragItem & FRAME_RESIZE_BOTTOM) {
- newHeight += event->motion.yrel;
- }
- // Top
- if (dragItem & FRAME_RESIZE_TOP) {
- newY = y + event->motion.yrel;
- newHeight -= event->motion.yrel;
- }
- // Overflow
- if (dragItemOverflowY) {
- newHeight += dragItemOverflowY;
- if (dragItem & FRAME_RESIZE_TOP) newY -= dragItemOverflowY;
- dragItemOverflowY = 0;
- }
- if (newHeight < minHeight) {
- dragItemOverflowY = newHeight - minHeight;
- if (dragItem & FRAME_RESIZE_TOP) newY += dragItemOverflowY;
- newHeight = minHeight;
- }
- if (newY + newHeight > clipH) {
- dragItemOverflowY = newY + newHeight - clipH;
- newHeight -= dragItemOverflowY;
- }
- if (newY < clipY) {
- dragItemOverflowY = clipY - newY;
- newHeight -= dragItemOverflowY;
- newY = clipY;
- }
- // Right
- if (dragItem & FRAME_RESIZE_RIGHT) {
- newWidth += event->motion.xrel;
- }
- // Left
- if (dragItem & FRAME_RESIZE_LEFT) {
- newX = x + event->motion.xrel;
- newWidth -= event->motion.xrel;
- }
- // Overflow
- if (dragItemOverflowX) {
- newWidth += dragItemOverflowX;
- if (dragItem & FRAME_RESIZE_LEFT) newX -= dragItemOverflowX;
- dragItemOverflowX = 0;
- }
- if (newWidth < minWidth) {
- dragItemOverflowX = newWidth - minWidth;
- if (dragItem & FRAME_RESIZE_LEFT) newX += dragItemOverflowX;
- newWidth = minWidth;
- }
- if (newX + newWidth > clipW) {
- dragItemOverflowX = newX + newWidth - clipW;
- newWidth -= dragItemOverflowX;
- }
- if (newX < clipX) {
- dragItemOverflowX = clipX - newX;
- newWidth -= dragItemOverflowX;
- newX = clipX;
- }
- move(newX, newY);
- resize(newWidth, newHeight);
-
- // If we didn't reach target size, "undo" some
- if ((width != newWidth) || (height != newHeight)) {
- if (width != newWidth) {
- int offBy = newWidth - width;
- if (dragItem & FRAME_RESIZE_LEFT) newX += offBy;
- newWidth -= offBy;
- dragItemOverflowX += offBy;
- }
- if (height != newHeight) {
- int offBy = newHeight - height;
- if (dragItem & FRAME_RESIZE_TOP) newY += offBy;
- newHeight -= offBy;
- dragItemOverflowY += offBy;
- }
- move(newX, newY);
- resize(newWidth, newHeight);
- }
-
- setDirty();
- whyDirty = FRAME_DIRTY_ALL;
- }
- else {
- // @TODO: resize within other window
- }
- }
- }
- // Just hover?
- else {
- doMouseHover(event->motion.x, event->motion.y, hasFocus, clientEvent);
- }
- break;
-
- case SDL_INPUTFOCUS:
- if ((event->user.code & 1) && (!haveFocus)) {
- haveFocus = 1;
- setDirty();
- whyDirty |= FRAME_DIRTY_TITLE;
-
- // Propogate to client
- for (pos = 0; pos < (int)clientArea.size(); ++pos) {
- if (clientArea[pos].window) {
- clientEvent.user.code = pos == subFocus ? 1 : 2;
- clientArea[pos].window->event(hasFocus, &clientEvent);
- }
- }
- }
- else if (!(event->user.code & 1) && (haveFocus)) {
- haveFocus = 0;
- dragMode = FRAME_DRAG_NONE;
- setDirty();
- whyDirty |= FRAME_DIRTY_TITLE;
- // Propogate to client
- for (pos = 0; pos < (int)clientArea.size(); ++pos) {
- if (clientArea[pos].window) {
- clientArea[pos].window->event(hasFocus, &clientEvent);
- }
- }
- }
- break;
-
- case SDL_KEYDOWN:
- case SDL_KEYUP:
- // Propogate to client- current focus area only
- if (clientArea[subFocus].window) {
- if (clientArea[subFocus].window->event(hasFocus, &clientEvent)) {
- return 1;
- }
- }
- // If current focus is tool panel or bar, give main area a shot at it
- if ((subFocus != 0) && (clientArea[0].window)) {
- // Don't do this for modifier keys
- if ((clientEvent.key.keysym.sym != SDLK_LSHIFT) &&
- (clientEvent.key.keysym.sym != SDLK_RSHIFT) &&
- (clientEvent.key.keysym.sym != SDLK_LALT) &&
- (clientEvent.key.keysym.sym != SDLK_RALT) &&
- (clientEvent.key.keysym.sym != SDLK_LCTRL) &&
- (clientEvent.key.keysym.sym != SDLK_RCTRL)) {
- if (clientArea[0].window->event(hasFocus, &clientEvent)) {
- // Switch focus to it
- focusToolPanel(0);
- return 1;
- }
- }
- }
- return 0;
-
- case SDL_COMMAND:
- // Catch certain commands
- switch (event->user.code) {
- case WINDOW_NEXT:
- nextWindow();
- return 1;
-
- case WINDOW_PREV:
- prevWindow();
- return 1;
-
- case WINDOW_CLOSE:
- closeWindow(); // Calls attemptClose
- return 1;
-
- case WINDOW_MIN:
- if (state == FRAME_STATE_MINIMIZED) restore();
- else minimize();
- return 1;
- case WINDOW_MAX:
- if (state == FRAME_STATE_MAXIMIZED) restore();
- else maximize();
- return 1;
- case WINDOW_CASCADE:
- // (Reset cascade position)
- cascadeStep = -1;
- case WINDOW_CLOSEALL:
- case WINDOW_CLOSEALLBUT:
- case WINDOW_TILEHORIZ:
- case WINDOW_TILEVERT: {
- Window* nextWin = NULL;
- int count = 0;
- int cascadeOffset = outerBorder + titlebarHeight;
- int cascadeWidth = desktop->desktopWidth() - cascadeOffset * 3;
- int cascadeHeight = desktop->desktopHeight() - cascadeOffset * 3;
- // First pass- does closes/cascades
- // (assignment intentional)
- while ( (nextWin = desktop->findWindow(WINDOW_FRAME, count)) ) {
- ++count;
- FrameWindow* fwin = dynamic_cast<FrameWindow*>(nextWin);
- if (fwin) {
- if ((event->user.code == WINDOW_CLOSEALL) ||
- ((event->user.code == WINDOW_CLOSEALLBUT) && (fwin != this))) {
- fwin->closeWindow();
- }
- else if (event->user.code == WINDOW_CASCADE) {
- fwin->restore();
- if (++cascadeStep > 3) cascadeStep = 0;
- fwin->move(desktop->desktopX() + cascadeStep * cascadeOffset,
- desktop->desktopY() + cascadeStep * cascadeOffset);
- fwin->resize(cascadeWidth, cascadeHeight);
- }
- }
- }
-
- // Do another pass for tiling
- if ((event->user.code == WINDOW_TILEHORIZ) || (event->user.code == WINDOW_TILEVERT)) {
- // Calculate minimum rows/columns to hold 'count' windows
- // Special exception- 3 or less
- int rows = 1, cols = 1;
- if (count <= 3) rows = count;
- else {
- while (rows * cols < count) {
- if (rows == cols) ++rows;
- else ++cols;
- }
- }
-
- // Number of entries in each row (horiz) or col (vert)
- int* entries = new int[rows];
- memset(entries, 0, sizeof(int[rows]));
-
- // Fill up the rows, from right-to-left (bottom-to-top)
- int row = rows;
- for (int pos = 0; pos < count; ++pos) {
- ++entries[--row];
- if (row == 0) row = rows;
- }
-
- // Now we move windows, fill last spot first
- int currRow = rows - 1;
- int currCol = entries[currRow] - 1;
-
- int pos = 0;
- // (assignment intentional)
- while ( (nextWin = desktop->findWindow(WINDOW_FRAME, pos++)) ) {
- FrameWindow* fwin = dynamic_cast<FrameWindow*>(nextWin);
- if (fwin) {
- fwin->restore();
- int width, height;
- if (event->user.code == WINDOW_TILEVERT) {
- // row/width are swapped
- width = desktop->desktopWidth() / rows;
- height = desktop->desktopHeight() / entries[currRow];
- fwin->move(desktop->desktopX() + width * currRow,
- desktop->desktopY() + height * currCol);
- }
- else {
- width = desktop->desktopWidth() / entries[currRow];
- height = desktop->desktopHeight() / rows;
- fwin->move(desktop->desktopX() + width * currCol,
- desktop->desktopY() + height * currRow);
- }
- fwin->resize(width, height);
- }
- // Next spot
- if (--currCol < 0) {
- --currRow;
- currCol = entries[currRow] - 1;
- }
- }
-
- delete[] entries;
- }
- return 1;
- }
-
- case WINDOW_SWITCHPANEL:
- // @TODO:
- /*
- if ((subFocus == 0) && (clientArea[1])) {
- // If not open, open it- this switches focus too
- if (!toolPanelOpen) toggleToolPanel();
- else focusToolPanel(1);
- return 1;
- }
- if ((subFocus < 2) && (clientArea[2])) {
- if (!toolBarOpen) toggleToolBar();
- else focusToolPanel(2);
- return 1;
- }
- focusToolPanel(0);
- */
- return 1;
-
- case VIEW_TOOLPANEL:
- // @TODO:
- /*
- toggleToolPanel();
- */
- return 1;
- case VIEW_TOOLBAR:
- // @TODO:
- /*
- toggleToolBar();
- */
- return 1;
- }
- // Propogate to client- try current panel, then others
- if ((clientArea[subFocus].window) && (exempt != clientArea[subFocus].window)) {
- if (clientArea[subFocus].window->event(hasFocus, &clientEvent)) return 1;
- }
- for (pos = 0; pos < (int)clientArea.size(); ++pos) {
- if (pos != subFocus) {
- if ((clientArea[pos].window) && (exempt != clientArea[pos].window)) {
- if (clientArea[pos].window->event(0, &clientEvent)) return 1;
- }
- }
- }
- return 0;
- case SDL_SPECIAL:
- // Scrollbar repeat?
- if ((event->user.code & SDL_IDLE) && (scrollRepeatDelay)) {
- ticks = SDL_GetTicks();
- // (catch wraparound)
- if (ticks < scrollRepeatTicks) scrollRepeatTicks = SDL_GetTicks();
- else if (ticks - scrollRepeatTicks > scrollRepeatDelay) {
- scrollRepeatTicks = SDL_GetTicks();
- scrollRepeatDelay = DELAY_SCROLLBAR_REPEATAGAIN;
- if (dragMode == FRAME_DRAG_SCROLLBAR_VERT) {
- if (dragItem == FRAME_SCROLL_LESS) scrollTo(scrollX, scrollY + vScrollLine);
- else if (dragItem == FRAME_SCROLL_MORE) scrollTo(scrollX, scrollY - vScrollLine);
- else if (dragItem == FRAME_SCROLL_PAGELESS) scrollTo(scrollX, scrollY + vScrollPage);
- else if (dragItem == FRAME_SCROLL_PAGEMORE) scrollTo(scrollX, scrollY - vScrollPage);
- }
- if (dragMode == FRAME_DRAG_SCROLLBAR_HORIZ) {
- if (dragItem == FRAME_SCROLL_LESS) scrollTo(scrollX + hScrollLine, scrollY);
- else if (dragItem == FRAME_SCROLL_MORE) scrollTo(scrollX - hScrollLine, scrollY);
- else if (dragItem == FRAME_SCROLL_PAGELESS) scrollTo(scrollX + hScrollPage, scrollY);
- else if (dragItem == FRAME_SCROLL_PAGEMORE) scrollTo(scrollX - hScrollPage, scrollY);
- }
- // Force mouse motion to determine new drag mode
- SDL_GetMouseState(&mX, &mY);
- SDL_WarpMouse(mX, mY);
- used = 1;
- }
- }
- // (continue on, to propogate to client)
-
- case SDL_QUIT:
- case SDL_SYSKEY:
- case SDL_OBJECTCHANGE:
- // (exempt window may exist)
- exempt = (Window*)clientEvent.user.data2;
- default:
- // Propogate to client
- for (pos = 0; pos < (int)clientArea.size(); ++pos) {
- if ((clientArea[pos].window) && (exempt != clientArea[pos].window)) {
- used = clientArea[pos].window->event(hasFocus && (subFocus == pos), &clientEvent) || used;
- }
- }
- return used;
- }
- // All mouse and focus events, we use.
- return 1;
- }
- void FrameWindow::doMouseHover(int x, int y, int hasFocus, SDL_Event& clientEvent) { start_func
- DragType newDragMode;
- DragSubType newDragItem;
- whereCoords(x, y, &newDragMode, &newDragItem);
- if (newDragMode == FRAME_DRAG_BORDER) {
- if ((newDragItem == FRAME_RESIZE_BOTTOM) || (newDragItem == FRAME_RESIZE_TOP))
- selectMouse(MOUSE_VERT);
- else if ((newDragItem == FRAME_RESIZE_LEFT) || (newDragItem == FRAME_RESIZE_RIGHT))
- selectMouse(MOUSE_HORIZ);
- else if ((newDragItem == (FRAME_RESIZE_LEFT | FRAME_RESIZE_BOTTOM)) || (newDragItem == (FRAME_RESIZE_RIGHT | FRAME_RESIZE_TOP)))
- selectMouse(MOUSE_DIAGUP);
- else if ((newDragItem == (FRAME_RESIZE_LEFT | FRAME_RESIZE_TOP)) || (newDragItem == (FRAME_RESIZE_RIGHT | FRAME_RESIZE_BOTTOM)))
- selectMouse(MOUSE_DIAGDOWN);
- }
- else if (newDragMode == FRAME_DRAG_TITLE) selectMouse(MOUSE_FOURDIRECTION);
- else if ((newDragMode != hoverMode) || (newDragItem != hoverItem)) selectMouse(MOUSE_NORMAL);
- if ((hoverMode == FRAME_DRAG_CLIENT) && (clientArea[hoverItem].window) && ((newDragMode != hoverMode) || (newDragItem != hoverItem))) {
- // Lose focus
- SDL_Event customEvent;
- customEvent.type = SDL_MOUSEFOCUS;
- customEvent.user.code = 0;
- customEvent.user.data1 = NULL;
- customEvent.user.data2 = NULL;
- clientArea[hoverItem].window->event(hasFocus && (subFocus == hoverItem), &customEvent);
- }
- if (newDragMode == FRAME_DRAG_CLIENT) {
- if (clientArea[newDragItem].window) {
- // Gain focus?
- if ((newDragMode != hoverMode) || (newDragItem != hoverItem)) {
- SDL_Event customEvent;
- customEvent.type = SDL_MOUSEFOCUS;
- customEvent.user.code = 1;
- customEvent.user.data1 = NULL;
- customEvent.user.data2 = NULL;
- clientArea[newDragItem].window->event(hasFocus && (subFocus == newDragItem), &customEvent);
- // Force to be a mouse motion event if gaining focus
- if (clientEvent.type == SDL_MOUSEBUTTONUP) {
- int x = clientEvent.button.x;
- int y = clientEvent.button.y;
- clientEvent.type = SDL_MOUSEMOTION;
- clientEvent.motion.x = x;
- clientEvent.motion.y = y;
- clientEvent.motion.state = SDL_GetMouseState(NULL, NULL);
- clientEvent.motion.xrel = 0;
- clientEvent.motion.yrel = 0;
- }
- }
-
- // Only propogate hovering- MouseUp was alredy done
- if (clientEvent.type != SDL_MOUSEBUTTONUP) {
- // Adjust coordinates to 0-based for client
- if (clientEvent.type == SDL_MOUSEMOTION) {
- clientEvent.motion.x -= clientArea[newDragItem].x + (newDragItem == 0 ? scrollX : 0);
- clientEvent.motion.y -= clientArea[newDragItem].y + (newDragItem == 0 ? scrollY : 0);
- }
- else {
- clientEvent.button.x -= clientArea[newDragItem].x + (newDragItem == 0 ? scrollX : 0);
- clientEvent.button.y -= clientArea[newDragItem].y + (newDragItem == 0 ? scrollY : 0);
- }
-
- // Propogate to client
- clientArea[newDragItem].window->event(hasFocus && (subFocus == newDragItem), &clientEvent);
- }
- }
- }
- hoverMode = newDragMode;
- hoverItem = newDragItem;
- }
|