kwin Library API Documentation

buttons.cpp

00001 /* 00002 This is the new kwindecoration kcontrol module 00003 00004 Copyright (c) 2001 00005 Karol Szwed <gallium@kde.org> 00006 http://gallium.n3.net/ 00007 00008 Supports new kwin configuration plugins, and titlebar button position 00009 modification via dnd interface. 00010 00011 Based on original "kwintheme" (Window Borders) 00012 Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org> 00013 00014 This program is free software; you can redistribute it and/or modify 00015 it under the terms of the GNU General Public License as published by 00016 the Free Software Foundation; either version 2 of the License, or 00017 (at your option) any later version. 00018 00019 This program is distributed in the hope that it will be useful, 00020 but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License 00025 along with this program; if not, write to the Free Software 00026 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00027 00028 */ 00029 00030 #include <qpainter.h> 00031 #include <klocale.h> 00032 #include <kglobalsettings.h> 00033 #include "buttons.h" 00034 #include "pixmaps.h" 00035 00036 00037 // General purpose button globals (I know I shouldn't use them :) 00038 //=============================================================== 00039 00040 enum Buttons{ BtnMenu=0, BtnOnAllDesktops, BtnSpacer, BtnHelp, 00041 BtnMinimize, BtnMaximize, BtnClose, 00042 BtnAboveOthers, BtnBelowOthers, 00043 BtnShade, BtnResize, BtnCount }; 00044 QListBoxPixmap* buttons[ BtnCount ]; 00045 QPixmap* pixmaps[ BtnCount ]; 00046 QPixmap* miniSpacer; 00047 00048 00049 //============================================================== 00050 00051 ButtonDrag::ButtonDrag( char btn, QWidget* parent, const char* name) 00052 : QStoredDrag( "kcontrol/kwindecoration_buttons", parent, name) 00053 { 00054 QByteArray payload(1); 00055 payload[0] = btn; 00056 setEncodedData( payload ); 00057 } 00058 00059 00060 bool ButtonDrag::canDecode( QDragMoveEvent* e ) 00061 { 00062 return e->provides( "kcontrol/kwindecoration_buttons" ); 00063 } 00064 00065 00066 bool ButtonDrag::decode( QDropEvent* e, char& btn ) 00067 { 00068 QByteArray payload = e->data( "kcontrol/kwindecoration_buttons" ); 00069 if ( payload.size() ) 00070 { 00071 e->accept(); 00072 btn = payload[0]; 00073 return TRUE; 00074 } 00075 return FALSE; 00076 } 00077 00078 00079 00081 // Implements the button drag source list box 00083 00084 // Converts the button character value to its index 00085 static int btnIndex( char btn ) 00086 { 00087 switch (btn) 00088 { 00089 case 'M': 00090 return BtnMenu; 00091 break; 00092 case 'S': 00093 return BtnOnAllDesktops; 00094 break; 00095 case '_': 00096 return BtnSpacer; 00097 break; 00098 case 'H': 00099 return BtnHelp; 00100 break; 00101 case 'I': 00102 return BtnMinimize; 00103 break; 00104 case 'A': 00105 return BtnMaximize; 00106 break; 00107 case 'X': 00108 return BtnClose; 00109 break; 00110 case 'F': 00111 return BtnAboveOthers; 00112 break; 00113 case 'B': 00114 return BtnBelowOthers; 00115 break; 00116 case 'L': 00117 return BtnShade; 00118 break; 00119 case 'R': 00120 return BtnResize; 00121 break; 00122 default: 00123 return -1; // Not found... 00124 } 00125 } 00126 00127 00128 // Returns the pixmap of a button item 00129 const QPixmap* btnPixmap( char btn ) 00130 { 00131 if (btn == '_') 00132 return miniSpacer; 00133 00134 int btnindex = btnIndex( btn ); 00135 if (btnindex == -1) 00136 return NULL; 00137 00138 return buttons[btnindex]->pixmap(); 00139 } 00140 00141 00142 00143 ButtonSource::ButtonSource( QWidget* parent, const char* name ) 00144 : QListBox( parent, name) 00145 { 00146 // Create the listbox pixmaps 00147 pixmaps[ BtnMenu ] = new QPixmap( button_menu_xpm ); 00148 pixmaps[ BtnOnAllDesktops ] = new QPixmap( button_on_all_desktops_xpm ); 00149 pixmaps[ BtnSpacer ] = new QPixmap( button_spacer_xpm ); 00150 pixmaps[ BtnHelp ] = new QPixmap( button_help_xpm ); 00151 pixmaps[ BtnMinimize ] = new QPixmap( button_minimize_xpm ); 00152 pixmaps[ BtnMaximize ] = new QPixmap( button_maximize_xpm ); 00153 pixmaps[ BtnClose ] = new QPixmap( button_close_xpm ); 00154 pixmaps[ BtnAboveOthers ] = new QPixmap( button_above_others_xpm ); 00155 pixmaps[ BtnBelowOthers ] = new QPixmap( button_below_others_xpm ); 00156 pixmaps[ BtnShade ] = new QPixmap( button_shade_xpm ); 00157 pixmaps[ BtnResize ] = new QPixmap( button_resize_xpm ); 00158 miniSpacer = new QPixmap( titlebarspacer_xpm ); 00159 00160 // Add all possible button/spacer types to the list box. 00161 buttons[ BtnMenu ] = new QListBoxPixmap( this, *pixmaps[BtnMenu], i18n("Menu") ); 00162 buttons[ BtnOnAllDesktops] = new QListBoxPixmap( this, *pixmaps[BtnOnAllDesktops], i18n("On All Desktops") ); 00163 buttons[ BtnAboveOthers ] = new QListBoxPixmap( this, *pixmaps[BtnAboveOthers], i18n("Keep Above Others") ); 00164 buttons[ BtnBelowOthers ] = new QListBoxPixmap( this, *pixmaps[BtnBelowOthers], i18n("Keep Below Others") ); 00165 buttons[ BtnShade ] = new QListBoxPixmap( this, *pixmaps[BtnShade], i18n("Shade") ); 00166 buttons[ BtnResize ] = new QListBoxPixmap( this, *pixmaps[BtnResize], i18n("Resize") ); 00167 buttons[ BtnSpacer ] = new QListBoxPixmap( this, *pixmaps[BtnSpacer], i18n("Spacer") ); 00168 buttons[ BtnHelp ] = new QListBoxPixmap( this, *pixmaps[BtnHelp], i18n("Help") ); 00169 buttons[ BtnMinimize ] = new QListBoxPixmap( this, *pixmaps[BtnMinimize], i18n("Minimize") ); 00170 buttons[ BtnMaximize ] = new QListBoxPixmap( this, *pixmaps[BtnMaximize], i18n("Maximize") ); 00171 buttons[ BtnClose ] = new QListBoxPixmap( this, *pixmaps[BtnClose], i18n("Close") ); 00172 00173 spacerCount = 0; // No spacers inserted yet 00174 setAcceptDrops( TRUE ); 00175 } 00176 00177 00178 ButtonSource::~ButtonSource() 00179 { 00180 for( int i = 0; i < BtnCount; i++) 00181 if (pixmaps[i]) 00182 delete pixmaps[i]; 00183 00184 if (miniSpacer) 00185 delete miniSpacer; 00186 } 00187 00188 00189 void ButtonSource::hideAllButtons() 00190 { 00191 // Hide all listbox items which are visible 00192 if (index( buttons[BtnMenu] ) != -1) 00193 takeItem( buttons[BtnMenu] ); 00194 if (index( buttons[BtnOnAllDesktops] )!= -1) 00195 takeItem( buttons[BtnOnAllDesktops] ); 00196 if (index( buttons[BtnAboveOthers] )!= -1) 00197 takeItem( buttons[BtnAboveOthers] ); 00198 if (index( buttons[BtnBelowOthers] )!= -1) 00199 takeItem( buttons[BtnBelowOthers] ); 00200 if (index( buttons[BtnResize] )!= -1) 00201 takeItem( buttons[BtnResize] ); 00202 if (index( buttons[BtnShade] )!= -1) 00203 takeItem( buttons[BtnShade] ); 00204 if (index( buttons[BtnHelp] ) != -1) 00205 takeItem( buttons[BtnHelp] ); 00206 if (index( buttons[BtnMinimize] ) != -1) 00207 takeItem( buttons[BtnMinimize] ); 00208 if (index( buttons[BtnMaximize] ) != -1) 00209 takeItem( buttons[BtnMaximize] ); 00210 if (index( buttons[BtnClose] ) != -1) 00211 takeItem( buttons[BtnClose] ); 00212 if (index( buttons[BtnSpacer] ) != -1) 00213 takeItem( buttons[BtnSpacer] ); 00214 00215 spacerCount = 10; // 10 inserted spacers (max) 00216 } 00217 00218 void ButtonSource::showAllButtons() 00219 { 00220 // Hide all listbox items which are visible 00221 if (index( buttons[BtnMenu] ) == -1) 00222 insertItem( buttons[BtnMenu] ); 00223 if (index( buttons[BtnOnAllDesktops] )== -1) 00224 insertItem( buttons[BtnOnAllDesktops] ); 00225 if (index( buttons[BtnAboveOthers] )== -1) 00226 insertItem( buttons[BtnAboveOthers] ); 00227 if (index( buttons[BtnBelowOthers] )== -1) 00228 insertItem( buttons[BtnBelowOthers] ); 00229 if (index( buttons[BtnResize] )== -1) 00230 insertItem( buttons[BtnResize] ); 00231 if (index( buttons[BtnShade] )== -1) 00232 insertItem( buttons[BtnShade] ); 00233 if (index( buttons[BtnHelp] ) == -1) 00234 insertItem( buttons[BtnHelp] ); 00235 if (index( buttons[BtnMinimize] ) == -1) 00236 insertItem( buttons[BtnMinimize] ); 00237 if (index( buttons[BtnMaximize] ) == -1) 00238 insertItem( buttons[BtnMaximize] ); 00239 if (index( buttons[BtnClose] ) == -1) 00240 insertItem( buttons[BtnClose] ); 00241 if (index( buttons[BtnSpacer] ) == -1) 00242 insertItem( buttons[BtnSpacer] ); 00243 00244 spacerCount = 0; // No inserted spacers 00245 } 00246 00247 00248 void ButtonSource::showButton( char btn ) 00249 { 00250 // Ignore spacers (max 10) 00251 if (btn == '_') 00252 spacerCount--; 00253 00254 int btnindex = btnIndex(btn); 00255 00256 // Check if the item is already inserted... 00257 if ( (btnindex != -1) && (index( buttons[btnindex] ) == -1) ) 00258 { 00259 setUpdatesEnabled( FALSE ); 00260 insertItem( buttons[ btnindex ] ); 00261 setUpdatesEnabled( TRUE ); 00262 sort(); 00263 } 00264 } 00265 00266 00267 void ButtonSource::hideButton( char btn ) 00268 { 00269 // Ignore spacers (max 10) 00270 if (btn == '_') 00271 { 00272 spacerCount++; 00273 if (spacerCount != 10) 00274 return; 00275 } 00276 00277 int btnindex = btnIndex(btn); 00278 00279 // Check if the item is already removed... 00280 if ( (btnindex != -1) && (index( buttons[btnindex] ) != -1) ) 00281 { 00282 setUpdatesEnabled( FALSE ); 00283 // De-select before removal 00284 setSelected( buttons[ btnindex ], false ); 00285 takeItem( buttons[ btnindex ] ); 00286 setUpdatesEnabled( TRUE ); 00287 sort(); 00288 } 00289 } 00290 00291 00292 char ButtonSource::convertToChar( QString s ) 00293 { 00294 // Convert the item to its character representation 00295 if (s == i18n("Menu")) 00296 return 'M'; 00297 else if (s == i18n("On All Desktops")) 00298 return 'S'; 00299 else if (s == i18n("Spacer")) 00300 return '_'; 00301 else if (s == i18n("Help")) 00302 return 'H'; 00303 else if (s == i18n("Minimize")) 00304 return 'I'; 00305 else if (s == i18n("Maximize")) 00306 return 'A'; 00307 else if (s == i18n("Close")) 00308 return 'X'; 00309 else if (s == i18n("Keep Above Others")) 00310 return 'F'; 00311 else if (s == i18n("Keep Below Others")) 00312 return 'B'; 00313 else if (s == i18n("Shade")) 00314 return 'L'; 00315 else if (s == i18n("Resize")) 00316 return 'R'; 00317 else 00318 return '?'; 00319 } 00320 00321 00322 void ButtonSource::mousePressEvent( QMouseEvent* e ) 00323 { 00324 // Make a selection before moving the mouse 00325 QListBox::mousePressEvent( e ); 00326 00327 // Make sure we have at laest 1 item in the listbox 00328 if ( count() > 0 ) 00329 { 00330 // Obtain currently selected item 00331 char btn = convertToChar( currentText() ); 00332 ButtonDrag* bd = new ButtonDrag( btn, this ); 00333 bd->dragCopy(); 00334 } 00335 } 00336 00337 00338 void ButtonSource::dragMoveEvent( QDragMoveEvent* /* e */ ) 00339 { 00340 // Do nothing... 00341 } 00342 00343 00344 void ButtonSource::dragEnterEvent( QDragEnterEvent* e ) 00345 { 00346 if ( ButtonDrag::canDecode( e ) ) 00347 e->accept(); 00348 } 00349 00350 00351 void ButtonSource::dragLeaveEvent( QDragLeaveEvent* /* e */ ) 00352 { 00353 // Do nothing... 00354 } 00355 00356 00357 void ButtonSource::dropEvent( QDropEvent* /* e */ ) 00358 { 00359 // Allow the button to be removed from the ButtonDropSite 00360 emit buttonDropped(); 00361 } 00362 00363 00365 // This class renders and handles the demo titlebar dropsite 00367 00368 ButtonDropSite::ButtonDropSite( QWidget* parent, const char* name ) 00369 : QFrame( parent, name ) 00370 { 00371 setAcceptDrops( TRUE ); 00372 setFrameShape( WinPanel ); 00373 setFrameShadow( Raised ); 00374 setMinimumHeight( 26 ); 00375 setMaximumHeight( 26 ); 00376 setMinimumWidth( 250 ); // Ensure buttons will fit 00377 00378 mouseClickPoint.setX(0); 00379 mouseClickPoint.setY(0); 00380 } 00381 00382 00383 ButtonDropSite::~ButtonDropSite() 00384 { 00385 // Do nothing... 00386 } 00387 00388 00389 void ButtonDropSite::dragMoveEvent( QDragMoveEvent* /* e */ ) 00390 { 00391 // Do nothing... 00392 } 00393 00394 00395 void ButtonDropSite::dragEnterEvent( QDragEnterEvent* e ) 00396 { 00397 if ( ButtonDrag::canDecode( e ) ) 00398 e->accept(); 00399 } 00400 00401 00402 void ButtonDropSite::dragLeaveEvent( QDragLeaveEvent* /* e */ ) 00403 { 00404 // Do nothing... 00405 } 00406 00407 00408 void ButtonDropSite::dropEvent( QDropEvent* e ) 00409 { 00410 char btn; 00411 if ( ButtonDrag::decode(e, btn) ) 00412 { 00413 bool isleft; 00414 int strPos; 00415 00416 // If we are moving buttons around, remove the old item first. 00417 if (btn == '*') 00418 { 00419 btn = removeButtonAtPoint( mouseClickPoint ); 00420 if (btn != '?') 00421 emit buttonRemoved( btn ); 00422 } 00423 00424 if (btn != '?') 00425 { 00426 // Add the button to our button strings 00427 buttonInsertedAtPoint( e->pos(), isleft, strPos ); 00428 00429 if (isleft) 00430 buttonsLeft.insert( strPos, btn ); 00431 else 00432 buttonsRight.insert( strPos, btn ); 00433 00434 repaint(false); 00435 00436 // Allow listbox to update itself 00437 emit buttonAdded( btn ); 00438 emit changed(); 00439 } 00440 } 00441 } 00442 00443 00444 // Starts dragging a button... 00445 void ButtonDropSite::mousePressEvent( QMouseEvent* e ) 00446 { 00447 mouseClickPoint = e->pos(); 00448 00449 ButtonDrag* bd = new ButtonDrag( '*', this ); 00450 bd->dragCopy(); 00451 } 00452 00453 00454 int ButtonDropSite::buttonWidth( char btn ) 00455 { 00456 if (btn == '_') 00457 return 6; // ensure this matches with the pixmap widths 00458 else 00459 return 20; // Assume characters given are all valid 00460 } 00461 00462 00463 // Computes the total space the buttons will take in the titlebar 00464 int ButtonDropSite::calcButtonStringWidth( const QString& s ) 00465 { 00466 QChar ch; 00467 unsigned int offset = 0; 00468 00469 for(unsigned int i = 0; i < s.length(); i++) 00470 { 00471 ch = s[i]; 00472 offset += buttonWidth( ch.latin1() ); 00473 } 00474 return (int)offset; 00475 } 00476 00477 00478 // This slot is called after we drop on the item listbox... 00479 void ButtonDropSite::removeClickedButton() 00480 { 00481 if ( !mouseClickPoint.isNull() ) 00482 { 00483 char btn = removeButtonAtPoint( mouseClickPoint ); 00484 mouseClickPoint.setX(0); 00485 mouseClickPoint.setY(0); 00486 repaint(false); 00487 00488 emit buttonRemoved( btn ); 00489 emit changed(); 00490 } 00491 } 00492 00493 00494 // Find the string and position at which to insert the new button... 00495 void ButtonDropSite::buttonInsertedAtPoint( QPoint p, bool& isleft, int& strPos ) 00496 { 00497 int leftoffset = calcButtonStringWidth( buttonsLeft ); 00498 int rightoffset = calcButtonStringWidth( buttonsRight ); 00499 int posx = p.x() - 3; 00500 00501 // The centre of the titlebar text tells us whether to add to the left or right 00502 if ( posx < ( leftoffset - rightoffset + ((geometry().width() - 6) / 2))) 00503 isleft = true; 00504 else 00505 isleft = false; 00506 00507 QString s = isleft ? buttonsLeft : buttonsRight; 00508 int offset = isleft ? 0 : geometry().width() - 6 - rightoffset; 00509 QChar ch; 00510 00511 strPos = s.length(); 00512 00513 for (unsigned int i = 0; i < s.length(); i++) 00514 { 00515 if ( posx < (offset + 5 )) 00516 { 00517 strPos = i; 00518 break; 00519 } 00520 ch = s[i]; 00521 offset += buttonWidth( ch.latin1() ); 00522 } 00523 } 00524 00525 00526 char ButtonDropSite::removeButtonAtPoint( QPoint p ) 00527 { 00528 int offset = -1; 00529 bool isleft = false; 00530 00531 // Shrink contents rect by 1 to fit in the titlebar border 00532 QRect r = contentsRect(); 00533 r.moveBy(1 , 1); 00534 r.setWidth( r.width() - 2 ); 00535 r.setHeight( r.height() - 2 ); 00536 00537 // Bail out if the borders were clicked 00538 if ( !r.contains(p) ) 00539 return '?'; 00540 00541 int posx = p.x(); 00542 00543 // Is the point in the LHS/RHS button area? 00544 if ( (!buttonsLeft.isEmpty()) && (posx <= (calcButtonStringWidth( buttonsLeft )+3)) ) 00545 { 00546 offset = 3; 00547 isleft = true; 00548 } 00549 else if ( (!buttonsRight.isEmpty()) && (posx >= geometry().width() - calcButtonStringWidth(buttonsRight) - 3)) 00550 { 00551 offset = geometry().width() - calcButtonStringWidth(buttonsRight) - 3; 00552 isleft = false; 00553 } 00554 00555 // Step through the button strings and remove the appropriate button 00556 if (offset != -1) 00557 { 00558 QChar ch; 00559 QString s = isleft ? buttonsLeft : buttonsRight; 00560 00561 // Step through the items, to find the appropriate one to remove. 00562 for (unsigned int i = 0; i < s.length(); i++) 00563 { 00564 ch = s[i]; 00565 offset += buttonWidth( ch.latin1() ); 00566 if (posx <= offset) 00567 { 00568 s.remove( i, 1 ); // Remove the current button item 00569 if (isleft) 00570 buttonsLeft = s; 00571 else 00572 buttonsRight = s; 00573 return ch.latin1(); 00574 } 00575 } 00576 } 00577 00578 return '?'; 00579 } 00580 00581 00582 void ButtonDropSite::drawButtonString( QPainter* p, QString& s, int offset ) 00583 { 00584 QChar ch; 00585 00586 for(unsigned int i = 0; i < s.length(); i++) 00587 { 00588 ch = s[i]; 00589 p->drawPixmap( offset, 3, *btnPixmap(ch.latin1()) ); 00590 offset += buttonWidth(ch.latin1()); 00591 } 00592 } 00593 00594 00595 void ButtonDropSite::drawContents( QPainter* p ) 00596 { 00597 int leftoffset = calcButtonStringWidth( buttonsLeft ); 00598 int rightoffset = calcButtonStringWidth( buttonsRight ); 00599 int offset = 3; 00600 00601 QRect r = contentsRect(); 00602 00603 // Shrink by 1 00604 r.moveBy(1 + leftoffset, 1); 00605 r.setWidth( r.width() - 2 - leftoffset - rightoffset ); 00606 r.setHeight( r.height() - 2 ); 00607 00608 drawButtonString( p, buttonsLeft, offset ); 00609 00610 QColor c1( 0x0A, 0x5F, 0x89 ); // KDE 2 titlebar default colour 00611 p->fillRect( r, c1 ); 00612 p->setPen( Qt::white ); 00613 p->setFont( QFont( KGlobalSettings::generalFont().family(), 12, QFont::Bold) ); 00614 p->drawText( r, AlignLeft | AlignVCenter, i18n("KDE") ); 00615 00616 offset = geometry().width() - 3 - rightoffset; 00617 drawButtonString( p, buttonsRight, offset ); 00618 } 00619 00620 #include "buttons.moc" 00621 // vim: ts=4
KDE Logo
This file is part of the documentation for kwin Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 13 21:47:04 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003