wmi

git clone git://oldgit.suckless.org/wmi/
Log | Files | Refs | LICENSE

statusbar.cpp (10242B)


      1 // Copyright (c) 2003 - 2009 Anselm R Garbe <anselm@garbe.us>
      2 // See LICENSE for license details.
      3 
      4 extern "C" {
      5 #include <assert.h>
      6 }
      7 
      8 #include "statusbar.h"
      9 
     10 #include "binder.h"
     11 #include "client.h"
     12 #include "cursors.h"
     13 #include "draw.h"
     14 #include "kernel.h"
     15 #include "inputbar.h"
     16 #include "label.h"
     17 #include "logger.h"
     18 #include "rectangle.h"
     19 #include "workspace.h"
     20 #include "monitor.h"
     21 #include "theme.h"
     22 #include "util.h"
     23 #include "xcore.h"
     24 
     25 StatusBar::StatusBar(Monitor *monitor, Rectangle *rect)
     26     : Bar(monitor, rect)
     27 {
     28     text_ = "window manager improved - " + string(__WMI_VERSION);
     29     buttonPressed_ = false;
     30 }
     31 
     32 void StatusBar::illuminate() {
     33 
     34     if (!isVisible()) {
     35         return;
     36     }
     37 
     38     LOGDEBUG("going to draw border");
     39     drawBorder();
     40 
     41     unsigned int offsetX = 1;
     42 
     43     label_->setAlignment(Label::CENTER);
     44     label_->setText("");
     45     label_->setX(offsetX);
     46     label_->setWidth(width() - 2);
     47     label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT,
     48                    theme_->BAR_SHINE, theme_->BAR_SHADOW);
     49 
     50     updateInputModeButton(&offsetX);
     51     updateWorkspacePager(&offsetX);
     52     updateStatus(&offsetX);
     53     updateMeters(offsetX);
     54 
     55     XCORE->sync();
     56 }
     57 
     58 StatusBar::~StatusBar() {
     59 }
     60 
     61 void StatusBar::updateInputModeButton(unsigned int *offsetX) {
     62 
     63     if (!isButtonVisible_) {
     64         return;
     65     }
     66 
     67     // input mode button
     68     label_->setX(*offsetX);
     69     label_->setText("");
     70     label_->setWidth(monitor()->buttonWidth());
     71     if (!buttonPressed_) {
     72 
     73         Draw::drawInputModeButton(window(), gc(), label_,
     74                 theme_->BUTTON_BACKGROUND_NORMAL,
     75                 theme_->BUTTON_SHINE_BORDER_NORMAL,
     76                 theme_->BUTTON_SHADOW_BORDER_NORMAL,
     77                 theme_->BUTTON_SHINE_FIGURE_NORMAL,
     78                 theme_->BUTTON_SHADOW_FIGURE_NORMAL);
     79     }
     80     else {
     81 
     82         Draw::drawInputModeButton(window(), gc(), label_,
     83                 theme_->BUTTON_BACKGROUND_PRESSED,
     84                 theme_->BUTTON_SHINE_BORDER_PRESSED,
     85                 theme_->BUTTON_SHADOW_BORDER_PRESSED,
     86                 theme_->BUTTON_SHINE_FIGURE_PRESSED,
     87                 theme_->BUTTON_SHADOW_FIGURE_PRESSED);
     88     }
     89     *offsetX += monitor()->buttonWidth() + 2;
     90 }
     91 
     92 unsigned int StatusBar::calculateWorkspaceWidth() {
     93 
     94     // workspace pager stuff
     95     Workspace *focusedWorkspace = monitor()->focused();
     96     assert(focusedWorkspace);
     97 
     98     // first determine maximum workspace label width
     99     unsigned int workspaceWidth = 0;
    100     for (LWorkspace::iterator it = monitor()->begin();
    101          it != monitor()->end(); it++)
    102     {
    103         Workspace *workspace = *it;
    104         label_->setText(workspace->name());
    105         label_->adjustWidth();
    106         if (label_->width() > workspaceWidth) {
    107             workspaceWidth = label_->width();
    108         }
    109     }
    110 
    111     return workspaceWidth;
    112 }
    113 
    114 void StatusBar::updateWorkspacePager(unsigned int *offsetX) {
    115 
    116     // workspace pager stuff
    117     Workspace *focusedWorkspace = monitor()->focused();
    118     assert(focusedWorkspace);
    119     unsigned int workspaceWidth = calculateWorkspaceWidth();
    120     unsigned int i = 0;
    121     label_->setWidth(workspaceWidth);
    122     for (LWorkspace::iterator it = monitor()->begin();
    123          it != monitor()->end(); it++)
    124     {
    125         Workspace *workspace = *it;
    126         label_->setX(i * workspaceWidth + *offsetX);
    127         label_->setText(workspace->name());
    128         if (workspace == focusedWorkspace) {
    129             label_->update(theme_->LABEL_BACKGROUND_FOCUSSED,
    130                            theme_->LABEL_TEXT_FOCUSSED,
    131                            theme_->LABEL_SHINE_FOCUSSED,
    132                            theme_->LABEL_SHADOW_FOCUSSED,
    133                            true, true);
    134         }
    135         else if (workspace->requestsFocus()) {
    136             label_->update(theme_->FOCUSREQ_BACKGROUND,
    137                            theme_->FOCUSREQ_TEXT,
    138                            theme_->FOCUSREQ_SHINE,
    139                            theme_->FOCUSREQ_SHADOW,
    140                            true, true);
    141         }
    142         else {
    143             label_->update(theme_->LABEL_BACKGROUND_NORMAL,
    144                            theme_->LABEL_TEXT_NORMAL,
    145                            theme_->LABEL_SHINE_NORMAL,
    146                            theme_->LABEL_SHADOW_NORMAL,
    147                            true, true);
    148         }
    149         i++;
    150     }
    151     *offsetX += i * workspaceWidth + 2;
    152 }
    153 
    154 unsigned int StatusBar::calculateMetersWidth() {
    155 
    156     unsigned int result = 0;
    157     if (meterText_ != "") {
    158         string percentage = "";
    159         string text = "";
    160         bool isPercentage = true;
    161         unsigned int meterWidth = monitor()->buttonWidth() / 2;
    162         for (string::iterator it = meterText_.begin();
    163                 it != meterText_.end(); )
    164         {
    165 
    166             char c = *it;
    167             it++;
    168             bool isEndreached = it == meterText_.end();
    169             if (c == '%') {
    170                 isPercentage = false;
    171             }
    172             if ((c == ',') || isEndreached) {
    173                 if (isEndreached && (c != '%')) {
    174                     text += c;
    175                 }
    176                 isPercentage = true;
    177                 result += 2 + meterWidth;
    178                 if (text != "") {
    179                     label_->setAlignment(Label::LEFT);
    180                     label_->setText(text);
    181                     result += label_->textWidth();
    182                 }
    183                 text = "";
    184                 percentage = "";
    185             }
    186             else if (isPercentage && (c == '!')) {
    187                 // do nothing here
    188             }
    189             else if (c != '%') {
    190                 if (isPercentage) {
    191                     percentage += c;
    192                 }
    193                 else {
    194                     text += c;
    195                 }
    196             }
    197         }
    198     }
    199     return result;
    200 }
    201 
    202 void StatusBar::updateMeters(unsigned int offsetX) {
    203 
    204     if (meterText_ != "") {
    205 
    206         string percentage = "";
    207         string text = "";
    208         bool isPercentage = true;
    209         bool isNegotiated = false;
    210         unsigned int meterWidth = monitor()->buttonWidth() / 2;
    211         label_->setX(offsetX);
    212         label_->setWidth(0);
    213         for (string::iterator it = meterText_.begin();
    214                 it != meterText_.end(); )
    215         {
    216 
    217             char c = *it;
    218             it++;
    219             bool isEndreached = it == meterText_.end();
    220             if (c == '%') {
    221                 isPercentage = false;
    222             }
    223             if ((c == ',') || isEndreached) {
    224                 if (isEndreached && (c != '%')) {
    225                     text += c;
    226                 }
    227                 label_->setX(label_->x() + label_->width() + 2);
    228                 label_->setWidth(meterWidth);
    229                 int percent = Util::strToUInt(percentage);
    230                 if (percent < 0) {
    231                     percent = 0;
    232                 }
    233                 else if (percent > 99) {
    234                     percent = 99;
    235                 }
    236                 Draw::drawMeter(window(), gc(), label_, percent,
    237                       theme_->METER_BACKGROUND,
    238                       isNegotiated ? theme_->METER_FIGURE_LOW : theme_->METER_FIGURE_HIGH,
    239                       theme_->METER_FIGURE_NORMAL,
    240                       isNegotiated ? theme_->METER_FIGURE_HIGH : theme_->METER_FIGURE_LOW,
    241                       theme_->METER_BORDER_SHINE,
    242                       theme_->METER_BORDER_SHADOW);
    243                 if (text != "") {
    244                     label_->setAlignment(Label::LEFT);
    245                     label_->setX(label_->x() + label_->width());
    246                     label_->setText(text);
    247                     label_->adjustWidth();
    248                     label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT,
    249                                    theme_->BAR_SHINE, theme_->BAR_SHADOW);
    250                 }
    251                 text = "";
    252                 percentage = "";
    253                 isPercentage = true;
    254                 isNegotiated = false;
    255             }
    256             else if (isPercentage && (c == '!')) {
    257                 isNegotiated = true;
    258             }
    259             else if (c != '%') {
    260 
    261                 if (isPercentage) {
    262                     percentage += c;
    263                 }
    264                 else {
    265                     text += c;
    266                 }
    267             }
    268         }
    269     }
    270 }
    271 
    272 void StatusBar::updateStatus(unsigned int *offsetX) {
    273 
    274     unsigned int metersWidth = calculateMetersWidth();
    275 
    276     // user defined status text
    277     label_->setAlignment(Label::RIGHT);
    278     label_->setX(*offsetX);
    279     label_->setWidth(width() - *offsetX - metersWidth - 5);
    280     label_->setText(text_);
    281     label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT,
    282                    theme_->BAR_SHINE, theme_->BAR_SHADOW);
    283 
    284     *offsetX = label_->x() + label_->width() + 2;
    285 }
    286 
    287 void StatusBar::handleButtonRelease(XButtonEvent *event) {
    288 
    289     // TODO: make buttons customizable
    290     if (buttonPressed_) {
    291         if (event->button == Button1) {
    292             LOGDEBUG("toggling interactive mode");
    293             monitor()->inputBar()->runKey(KERNEL->defaultPrompt());
    294             buttonPressed_ = false;
    295         }
    296     }
    297 }
    298 
    299 void StatusBar::handleButtonPress(XButtonEvent *event) {
    300 
    301     if ((event->window != window())) {
    302         return;
    303     }
    304 
    305     XCORE->raise(window());
    306 
    307     // TODO: make buttons customizable
    308     if (event->button == Button1) {
    309         invokeClickedThing(event->x);
    310     }
    311     else if (event->button == Button4) {
    312         monitor()->focus(monitor()->prev());
    313     }
    314     else if (event->button == Button5) {
    315         monitor()->focus(monitor()->next());
    316     }
    317 }
    318 
    319 void StatusBar::handleMotionNotify(XMotionEvent *event) {
    320 
    321     if (buttonPressed_) {
    322         buttonPressed_ = false;
    323         illuminate();
    324     }
    325 }
    326 
    327 void StatusBar::invokeClickedThing(int xPosition) {
    328 
    329     if (isButtonVisible_) {
    330         if (xPosition < (int)monitor()->buttonWidth() + 1) {
    331             buttonPressed_ = true;
    332             illuminate();
    333             return;
    334         }
    335         xPosition -= (monitor()->buttonWidth() + 3);
    336     }
    337 
    338     unsigned int workspaceNum = xPosition / calculateWorkspaceWidth();
    339     if (workspaceNum < monitor()->size()) {
    340         monitor()->focusWorkspaceNum(workspaceNum);
    341     }
    342     illuminate();
    343 }
    344 
    345 void StatusBar::setText(const string text) {
    346     text_ = text;
    347 }
    348 
    349 void StatusBar::setMeterText(const string meterText) {
    350     meterText_ = meterText;
    351 }