X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2FBasemenu.cc;h=3c096eff59f4423b96f4aefd327e3e38dad6df00;hb=87e63d53af67d5ea98f55a27007663d4c9c8fc6c;hp=5b4acdf001009f2bf96b6f752c1e26a97158e157;hpb=be2f47223c17c399e05436a34ba4140f2fc44fc9;p=chaz%2Fopenbox diff --git a/src/Basemenu.cc b/src/Basemenu.cc index 5b4acdf0..3c096eff 100644 --- a/src/Basemenu.cc +++ b/src/Basemenu.cc @@ -84,21 +84,20 @@ Basemenu::Basemenu(BScreen *scrn) { which_press = which_sbl = -1; + menu.sublevels = + menu.persub = + menu.minsub = 0; + menu.frame_pixmap = menu.title_pixmap = - menu.hilite_pixmap = - menu.sel_pixmap = None; + menu.hilite_pixmap = None; menu.bevel_w = screen->getBevelWidth(); - MenuStyle *style = screen->getMenuStyle(); + const MenuStyle* const style = screen->getMenuStyle(); menu.width = menu.title_h = menu.item_w = menu.frame_h = style->t_font->height() + (menu.bevel_w * 2); - menu.sublevels = - menu.persub = - menu.minsub = 0; - menu.item_h = style->f_font->height() + menu.bevel_w; menu.height = menu.title_h + screen->getBorderWidth() + menu.frame_h; @@ -143,26 +142,25 @@ Basemenu::Basemenu(BScreen *scrn) { // completely created. items must be inserted and it must be update()'d } + Basemenu::~Basemenu(void) { XUnmapWindow(display, menu.window); if (shown && shown->getWindowID() == getWindowID()) shown = (Basemenu *) 0; - MenuItems::const_iterator it = menuitems.begin(); - while (it != menuitems.end()) { - BasemenuItem *item = *it; - if ((! internal_menu)) { - Basemenu *tmp = (Basemenu *) item->submenu(); + MenuItems::const_iterator it = menuitems.begin(), + end = menuitems.end(); + for (; it != end; ++it) { + if (! internal_menu) { + Basemenu *tmp = (*it)->submenu(); if (tmp) { - if (! tmp->internal_menu) { + if (! tmp->internal_menu) delete tmp; - } else { + else tmp->internal_hide(); - } } } - ++it; } std::for_each(menuitems.begin(), menuitems.end(), PointerAssassin()); @@ -176,9 +174,6 @@ Basemenu::~Basemenu(void) { if (menu.hilite_pixmap) image_ctrl->removeImage(menu.hilite_pixmap); - if (menu.sel_pixmap) - image_ctrl->removeImage(menu.sel_pixmap); - blackbox->removeMenuSearch(menu.title); XDestroyWindow(display, menu.title); @@ -202,7 +197,7 @@ int Basemenu::insert(BasemenuItem *item, int pos) { if (pos < 0) { menuitems.push_back(item); } else { - assert(pos < static_cast(menuitems.size())); + assert(pos <= static_cast(menuitems.size())); menuitems.insert((menuitems.begin() + pos), item); } return menuitems.size(); @@ -228,14 +223,13 @@ int Basemenu::remove(int index) { BasemenuItem *item = find(index); if (! item) return -1; - if ((! internal_menu)) { - Basemenu *tmp = (Basemenu *) item->submenu(); + if (! internal_menu) { + Basemenu *tmp = item->submenu(); if (tmp) { - if (! tmp->internal_menu) { + if (! tmp->internal_menu) delete tmp; - } else { + else tmp->internal_hide(); - } } } @@ -253,8 +247,9 @@ int Basemenu::remove(int index) { void Basemenu::update(void) { - MenuStyle *style = screen->getMenuStyle(); - menu.item_h = style->f_font->height() + menu.bevel_w; + const MenuStyle* const style = screen->getMenuStyle(); + menu.item_h = (style->f_font->height() < 9 ? 9 : style->f_font->height()) + + menu.bevel_w; // 9 for the menu pixmaps (checkmarks) menu.title_h = style->t_font->height() + menu.bevel_w * 2; if (title_vis) { @@ -276,7 +271,7 @@ void Basemenu::update(void) { if (! menuitems.empty()) { menu.sublevels = 1; - unsigned int menu_size = menuitems.size(); + const unsigned int menu_size = menuitems.size(); while (((menu.item_h * (menu_size + 1) / menu.sublevels) + menu.title_h + screen->getBorderWidth()) > screen->getHeight()) @@ -341,16 +336,6 @@ void Basemenu::update(void) { } if (tmp) image_ctrl->removeImage(tmp); - tmp = menu.sel_pixmap; - if (texture->texture() == (BTexture::Flat | BTexture::Solid)) { - menu.sel_pixmap = None; - } else { - int hw = menu.item_h / 2; - menu.sel_pixmap = - image_ctrl->renderImage(hw, hw, *texture); - } - if (tmp) image_ctrl->removeImage(tmp); - XResizeWindow(display, menu.window, menu.width, menu.height); if (title_vis) @@ -399,10 +384,10 @@ void Basemenu::show(void) { void Basemenu::hide(void) { - if ((! torn) && hide_tree && parent && parent->isVisible()) { + if (! torn && hide_tree && parent && parent->isVisible()) { Basemenu *p = parent; - while (p->isVisible() && (! p->torn) && p->parent) p = p->parent; + while (p->isVisible() && ! p->torn && p->parent) p = p->parent; p->internal_hide(); } else { internal_hide(); @@ -415,7 +400,7 @@ void Basemenu::internal_hide(void) { if (tmp) tmp->submenu()->internal_hide(); - if (parent && (! torn)) { + if (parent && ! torn) { parent->drawItem(parent->which_sub, False, True); parent->which_sub = -1; @@ -444,7 +429,7 @@ void Basemenu::redrawTitle(void) { i18n(BasemenuSet, BasemenuBlackboxMenu, "Blackbox Menu"); int dx = menu.bevel_w; unsigned int l; - MenuStyle *style = screen->getMenuStyle(); + const MenuStyle* const style = screen->getMenuStyle(); l = style->t_font->measureString(text) + menu.bevel_w * 2; @@ -462,6 +447,7 @@ void Basemenu::redrawTitle(void) { break; } + XClearWindow(display, menu.title); style->t_font->drawString(menu.title, dx, menu.bevel_w, style->t_text, text); } @@ -476,12 +462,13 @@ void Basemenu::drawSubmenu(int index) { item = find(index); if (! item) return; + Basemenu *submenu = item->submenu(); if (submenu && visible && ! submenu->isTorn() && item->isEnabled()) { if (submenu->parent != this) submenu->parent = this; - int sbl = index / menu.persub, i = index - (sbl * menu.persub), - x = menu.x + ((menu.item_w * (sbl + 1)) + screen->getBorderWidth()), y; + const int sbl = index / menu.persub, i = index - (sbl * menu.persub); + int x = menu.x + ((menu.item_w * (sbl + 1)) + screen->getBorderWidth()), y; if (alignment == AlignTop) { y = (((shifted) ? menu.y_shift : menu.y) + @@ -539,15 +526,15 @@ void Basemenu::drawItem(int index, bool highlight, bool clear, BasemenuItem *item = find(index); if (! item) return; - bool dotext = True, dohilite = True, dosel = True; + bool dotext = True, dohilite = True, dosel = True, dooppsel = True; const char *text = item->label(); - int sbl = index / menu.persub, i = index - (sbl * menu.persub); + const int sbl = index / menu.persub, i = index - (sbl * menu.persub); + const unsigned int half_w = menu.item_h / 2, quarter_w = menu.item_h / 4; int item_x = (sbl * menu.item_w), item_y = (i * menu.item_h); int hilite_x = item_x, hilite_y = item_y, hoff_x = 0, hoff_y = 0; - int text_x = 0, text_y = 0, sel_x = 0, sel_y = 0; + int text_x = 0, text_y = 0, sel_x = 0, oppsel_x = 0, sel_y = 0; unsigned int hilite_w = menu.item_w, hilite_h = menu.item_h, text_w = 0, text_h = 0; - unsigned int half_w = menu.item_h / 2, quarter_w = menu.item_h / 4; if (text) { text_w = screen->getMenuStyle()->f_font->measureString(text); @@ -570,15 +557,23 @@ void Basemenu::drawItem(int index, bool highlight, bool clear, text_h = menu.item_h - menu.bevel_w; } - MenuStyle *style = screen->getMenuStyle(); - BPen pen((highlight || item->isSelected()) ? style->h_text : style->f_text), - hipen(style->hilite.color()); + const MenuStyle* const style = screen->getMenuStyle(); + const BPen hipen(style->hilite.color()); + // match the text color + const BPen pen((highlight ? style->h_text : + (item->isEnabled() ? style->f_text : + style->d_text))); sel_x = item_x; if (screen->getMenuStyle()->bullet_pos == Right) sel_x += (menu.item_w - menu.item_h - menu.bevel_w); sel_x += quarter_w; + oppsel_x = sel_x; + if (screen->getMenuStyle()->bullet_pos == Right) + oppsel_x -= (menu.item_w - menu.item_h - menu.bevel_w); + else + oppsel_x += (menu.item_w - menu.item_h - menu.bevel_w); sel_y = item_y + quarter_w; if (clear) { @@ -599,7 +594,7 @@ void Basemenu::drawItem(int index, bool highlight, bool clear, } // check if we need to redraw the text - int text_ry = item_y + (menu.bevel_w / 2); + const int text_ry = item_y + (menu.bevel_w / 2); if (! (max(text_x, x) <= min(text_x + text_w, x + w) && max(text_ry, y) <= min(text_ry + text_h, y + h))) dotext = False; @@ -608,8 +603,19 @@ void Basemenu::drawItem(int index, bool highlight, bool clear, if (! (max(sel_x, x) <= min(sel_x + half_w, x + w) && max(sel_y, y) <= min(sel_y + half_w, y + h))) dosel = False; + + // check if we need to redraw the select pixmap/menu bullet + // on the opposite side of the menu + if (! (max(oppsel_x, x) <= min(oppsel_x + half_w, x + w) && + max(sel_y, y) <= min(sel_y + half_w, y + h))) + dooppsel = False; } +#ifdef XFT + if (dotext) + XClearArea(display, menu.frame, text_x, text_y , text_w, text_h, False); +#endif // XFT + if (dohilite && highlight && (menu.hilite_pixmap != ParentRelative)) { if (menu.hilite_pixmap) XCopyArea(display, menu.hilite_pixmap, menu.frame, @@ -618,13 +624,53 @@ void Basemenu::drawItem(int index, bool highlight, bool clear, else XFillRectangle(display, menu.frame, hipen.gc(), hilite_x, hilite_y, hilite_w, hilite_h); - } else if (dosel && item->isSelected() && - (menu.sel_pixmap != ParentRelative)) { - if (menu.sel_pixmap) - XCopyArea(display, menu.sel_pixmap, menu.frame, hipen.gc(), 0, 0, - half_w, half_w, sel_x, sel_y); - else - XFillRectangle(display, menu.frame, hipen.gc(), sel_x, sel_y, half_w, half_w); + } + + if (dooppsel && item->isSelected()) { +#ifdef BITMAPBUTTONS + if ( style->tick_image.mask != None) { + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), + oppsel_x, item_y + menu.item_h/2 - style->tick_image.h/2); + XSetClipMask(blackbox->getXDisplay(), pen.gc(), + style->tick_image.mask); + + XFillRectangle(blackbox->getXDisplay(), menu.frame, pen.gc(), + oppsel_x, item_y + menu.item_h/2 - style->tick_image.h/2, + style->tick_image.w, + style->tick_image.h); + + XSetClipMask(blackbox->getXDisplay(), pen.gc(), None); + + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), + 0, 0); + } else { +#endif // BITMAPBUTTONS + XPoint pts[6]; + + pts[0].x = oppsel_x + 0; + pts[0].y = sel_y + 2; + + pts[1].x = 0; + pts[1].y = 3; + + pts[2].x = 2; + pts[2].y = 3; + + pts[3].x = 5; + pts[3].y = -5; + + + pts[4].x = 0; + pts[4].y = -3; + + pts[5].x = -5; + pts[5].y = 5; + + XFillPolygon(display, menu.frame, pen.gc(), pts, 6, Nonconvex, + CoordModePrevious); +#ifdef BITMAPBUTTONS + } +#endif // BITMAPBUTTONS } if (dotext && text) { @@ -636,50 +682,73 @@ void Basemenu::drawItem(int index, bool highlight, bool clear, } if (dosel && item->submenu()) { - switch (screen->getMenuStyle()->bullet) { - case Square: - XDrawRectangle(display, menu.frame, pen.gc(), sel_x, sel_y, half_w, half_w); - break; - - case Triangle: - XPoint tri[3]; +#ifdef BITMAPBUTTONS + if ( style->bullet_image.mask != None) { + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), + sel_x, item_y + menu.item_h/2 - style->bullet_image.h/2); + XSetClipMask(blackbox->getXDisplay(), pen.gc(), + style->bullet_image.mask); + + XFillRectangle(blackbox->getXDisplay(), menu.frame, pen.gc(), + sel_x, item_y + menu.item_h/2 - style->bullet_image.h/2, + style->bullet_image.w, style->bullet_image.h); + + XSetClipMask(blackbox->getXDisplay(), pen.gc(), None); + + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), + 0, 0); + } else { +#endif // BITMAPBUTTONS + const int bullet_size = 3; + + switch (screen->getMenuStyle()->bullet) { + case Square: + XDrawRectangle(display, menu.frame, pen.gc(), sel_x, sel_y, + bullet_size * 2, bullet_size * 2); + break; + + case Triangle: + XPoint tri[3]; + + if (screen->getMenuStyle()->bullet_pos == Right) { + tri[0].x = sel_x + quarter_w - bullet_size; + tri[0].y = sel_y + quarter_w - bullet_size; + tri[1].x = 2 * bullet_size; + tri[1].y = bullet_size; + tri[2].x = -(2 * bullet_size); + tri[2].y = bullet_size; + } else { + tri[0].x = sel_x + quarter_w - bullet_size; + tri[0].y = item_y + half_w; + tri[1].x = 2 * bullet_size; + tri[1].y = bullet_size; + tri[2].x = 0; + tri[2].y = -(2 * bullet_size); + } - if (screen->getMenuStyle()->bullet_pos == Right) { - tri[0].x = sel_x + quarter_w - 2; - tri[0].y = sel_y + quarter_w - 2; - tri[1].x = 4; - tri[1].y = 2; - tri[2].x = -4; - tri[2].y = 2; - } else { - tri[0].x = sel_x + quarter_w - 2; - tri[0].y = item_y + half_w; - tri[1].x = 4; - tri[1].y = 2; - tri[2].x = 0; - tri[2].y = -4; + XFillPolygon(display, menu.frame, pen.gc(), tri, 3, Convex, + CoordModePrevious); + break; + + case Diamond: + XPoint dia[4]; + + dia[0].x = sel_x + quarter_w - bullet_size; + dia[0].y = item_y + half_w; + dia[1].x = bullet_size; + dia[1].y = -bullet_size; + dia[2].x = bullet_size; + dia[2].y = bullet_size; + dia[3].x = -bullet_size; + dia[3].y = bullet_size; + + XFillPolygon(display, menu.frame, pen.gc(), dia, 4, Convex, + CoordModePrevious); + break; } - - XFillPolygon(display, menu.frame, pen.gc(), tri, 3, Convex, - CoordModePrevious); - break; - - case Diamond: - XPoint dia[4]; - - dia[0].x = sel_x + quarter_w - 3; - dia[0].y = item_y + half_w; - dia[1].x = 3; - dia[1].y = -3; - dia[2].x = 3; - dia[2].y = 3; - dia[3].x = -3; - dia[3].y = 3; - - XFillPolygon(display, menu.frame, pen.gc(), dia, 4, Convex, - CoordModePrevious); - break; +#ifdef BITMAPBUTTONS } +#endif // BITMAPBUTTONS } } @@ -729,9 +798,9 @@ bool Basemenu::isItemEnabled(int index) { void Basemenu::buttonPressEvent(XButtonEvent *be) { if (be->window == menu.frame) { - int sbl = (be->x / menu.item_w), i = (be->y / menu.item_h); - int w = (sbl * menu.persub) + i; - + const int sbl = (be->x / menu.item_w), i = (be->y / menu.item_h), + w = (sbl * menu.persub) + i; + BasemenuItem *item = find(w); if (item) { which_press = i; @@ -769,7 +838,7 @@ void Basemenu::buttonReleaseEvent(XButtonEvent *re) { if (re->button == 3) { hide(); } else { - int sbl = (re->x / menu.item_w), i = (re->y / menu.item_h), + const int sbl = (re->x / menu.item_w), i = (re->y / menu.item_h), ix = sbl * menu.item_w, iy = i * menu.item_h, w = (sbl * menu.persub) + i, p = (which_sbl * menu.persub) + which_press; @@ -795,7 +864,7 @@ void Basemenu::motionNotifyEvent(XMotionEvent *me) { if (me->window == menu.title && (me->state & Button1Mask)) { if (movable) { if (! moving) { - if (parent && (! torn)) { + if (parent && ! torn) { parent->drawItem(parent->which_sub, False, True); parent->which_sub = -1; } @@ -814,32 +883,34 @@ void Basemenu::motionNotifyEvent(XMotionEvent *me) { drawSubmenu(which_sub); } } - } else if ((! (me->state & Button1Mask)) && me->window == menu.frame && + } else if (me->window == menu.frame && me->x >= 0 && me->x < static_cast(menu.width) && me->y >= 0 && me->y < static_cast(menu.frame_h)) { - int sbl = (me->x / menu.item_w), i = (me->y / menu.item_h), + const int sbl = (me->x / menu.item_w), i = (me->y / menu.item_h), w = (sbl * menu.persub) + i; if ((i != which_press || sbl != which_sbl) && (w >= 0 && w < static_cast(menuitems.size()))) { if (which_press != -1 && which_sbl != -1) { - int p = (which_sbl * menu.persub) + which_press; + const int p = (which_sbl * menu.persub) + which_press; BasemenuItem *item = find(p); + if (! item) return; drawItem(p, False, True); - if (item->submenu()) - if (item->submenu()->isVisible() && - (! item->submenu()->isTorn())) { - item->submenu()->internal_hide(); - which_sub = -1; - } + if (item->submenu() && + item->submenu()->isVisible() && + ! item->submenu()->isTorn()) { + item->submenu()->internal_hide(); + which_sub = -1; + } } which_press = i; which_sbl = sbl; BasemenuItem *itmp = find(w); - + if (! itmp) return; + if (itmp->submenu()) drawSubmenu(w); else @@ -853,27 +924,26 @@ void Basemenu::exposeEvent(XExposeEvent *ee) { if (ee->window == menu.title) { redrawTitle(); } else if (ee->window == menu.frame) { - // this is a compilicated algorithm... lets do it step by step... + // this is a complicated algorithm... lets do it step by step... // first... we see in which sub level the expose starts... and how many // items down in that sublevel - int sbl = (ee->x / menu.item_w), id = (ee->y / menu.item_h), + const int sbl = (ee->x / menu.item_w), id = (ee->y / menu.item_h), // next... figure out how many sublevels over the redraw spans - sbl_d = ((ee->x + ee->width) / menu.item_w), + sbl_d = ((ee->x + ee->width) / menu.item_w); // then we see how many items down to redraw - id_d = ((ee->y + ee->height) / menu.item_h); + int id_d = ((ee->y + ee->height) / menu.item_h); if (id_d > menu.persub) id_d = menu.persub; // draw the sublevels and the number of items the exposure spans MenuItems::iterator it, end = menuitems.end(); - int i, ii; - for (i = sbl; i <= sbl_d; i++) { + for (int i = sbl; i <= sbl_d; i++) { // set the iterator to the first item in the sublevel needing redrawing it = menuitems.begin() + (id + (i * menu.persub)); - for (ii = id; ii <= id_d && it != end; ++it, ii++) { - int index = ii + (i * menu.persub); + for (int ii = id; ii <= id_d && it != end; ++it, ii++) { + const int index = ii + (i * menu.persub); // redraw the item drawItem(index, (which_sub == index), False, ee->x, ee->y, ee->width, ee->height); @@ -910,10 +980,10 @@ void Basemenu::enterNotifyEvent(XCrossingEvent *ce) { if (which_sub != -1) { BasemenuItem *tmp = find(which_sub); if (tmp->submenu()->isVisible()) { - int sbl = (ce->x / menu.item_w), i = (ce->y / menu.item_h), + const int sbl = (ce->x / menu.item_w), i = (ce->y / menu.item_h), w = (sbl * menu.persub) + i; - if (w != which_sub && (! tmp->submenu()->isTorn())) { + if (w != which_sub && ! tmp->submenu()->isTorn()) { tmp->submenu()->internal_hide(); drawItem(which_sub, False, True); @@ -928,7 +998,7 @@ void Basemenu::enterNotifyEvent(XCrossingEvent *ce) { void Basemenu::leaveNotifyEvent(XCrossingEvent *ce) { if (ce->window == menu.frame) { if (which_press != -1 && which_sbl != -1 && menuitems.size() > 0) { - int p = (which_sbl * menu.persub) + which_press; + const int p = (which_sbl * menu.persub) + which_press; drawItem(p, (p == which_sub), True); @@ -959,6 +1029,6 @@ void Basemenu::reconfigure(void) { void Basemenu::changeItemLabel(unsigned int index, const string& label) { BasemenuItem *item = find(index); - assert(item); - item->newLabel(label); + if (item) + item->newLabel(label); }