kwin Library API Documentation

buttons.cpp

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