diff --git a/src/emucore/FBSurface.cxx b/src/emucore/FBSurface.cxx index 0e8eab048..6bcdf8252 100644 --- a/src/emucore/FBSurface.cxx +++ b/src/emucore/FBSurface.cxx @@ -133,13 +133,20 @@ void FBSurface::drawChar(const GUI::Font& font, uInt8 chr, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FBSurface::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty, uInt32 color, uInt32 h) +{ + drawBitmap(bitmap, tx, ty, color, h, h); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FBSurface::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty, + uInt32 color, uInt32 w, uInt32 h) { uInt32* buffer = myPixels + ty * myPitch + tx; for(uInt32 y = 0; y < h; ++y) { - uInt32 mask = 0xF0000000; - for(uInt32 x = 0; x < 8; ++x, mask >>= 4) + uInt32 mask = 1 << (w - 1); + for(uInt32 x = 0; x < w; ++x, mask >>= 1) if(bitmap[y] & mask) buffer[x] = uInt32(myPalette[color]); diff --git a/src/emucore/FBSurface.hxx b/src/emucore/FBSurface.hxx index c470d8487..e8d203765 100644 --- a/src/emucore/FBSurface.hxx +++ b/src/emucore/FBSurface.hxx @@ -128,6 +128,19 @@ class FBSurface virtual void drawBitmap(uInt32* bitmap, uInt32 x, uInt32 y, uInt32 color, uInt32 h = 8); + /** + This method should be called to draw the bitmap image. + + @param bitmap The data to draw + @param x The x coordinate + @param y The y coordinate + @param color The color of the bitmap + @param w The width of the data image + @param h The height of the data image + */ + virtual void drawBitmap(uInt32* bitmap, uInt32 x, uInt32 y, uInt32 color, + uInt32 w, uInt32 h); + /** This method should be called to convert and copy a given row of pixel data into a FrameBuffer surface. The pixels must already be in the diff --git a/src/gui/ContextMenu.cxx b/src/gui/ContextMenu.cxx index e71f60e4a..2146ebd4e 100644 --- a/src/gui/ContextMenu.cxx +++ b/src/gui/ContextMenu.cxx @@ -520,24 +520,24 @@ void ContextMenu::scrollDown(int distance) void ContextMenu::drawDialog() { static uInt32 up_arrow[8] = { - 0x00011000, - 0x00011000, - 0x00111100, - 0x00111100, - 0x01111110, - 0x01111110, - 0x11111111, - 0x11111111 + 0b00011000, + 0b00011000, + 0b00111100, + 0b00111100, + 0b01111110, + 0b01111110, + 0b11111111, + 0b11111111 }; static uInt32 down_arrow[8] = { - 0x11111111, - 0x11111111, - 0x01111110, - 0x01111110, - 0x00111100, - 0x00111100, - 0x00011000, - 0x00011000 + 0b11111111, + 0b11111111, + 0b01111110, + 0b01111110, + 0b00111100, + 0b00111100, + 0b00011000, + 0b00011000 }; // Normally we add widgets and let Dialog::draw() take care of this diff --git a/src/gui/PopUpWidget.cxx b/src/gui/PopUpWidget.cxx index 05ec76d7c..0b2038ce3 100644 --- a/src/gui/PopUpWidget.cxx +++ b/src/gui/PopUpWidget.cxx @@ -25,14 +25,14 @@ // Little up/down arrow static uInt32 up_down_arrows[8] = { - 0x00000000, - 0x00001000, - 0x00011100, - 0x00111110, - 0x00000000, - 0x00111110, - 0x00011100, - 0x00001000, + 0b00000000, + 0b00001000, + 0b00011100, + 0b00111110, + 0b00000000, + 0b00111110, + 0b00011100, + 0b00001000, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/ScrollBarWidget.cxx b/src/gui/ScrollBarWidget.cxx index b00a47124..ddc560126 100644 --- a/src/gui/ScrollBarWidget.cxx +++ b/src/gui/ScrollBarWidget.cxx @@ -32,26 +32,26 @@ // Up arrow static uInt32 up_arrow[8] = { - 0x00011000, - 0x00011000, - 0x00111100, - 0x00111100, - 0x01111110, - 0x01111110, - 0x11111111, - 0x11111111 + 0b00011000, + 0b00011000, + 0b00111100, + 0b00111100, + 0b01111110, + 0b01111110, + 0b11111111, + 0b11111111 }; // Down arrow static uInt32 down_arrow[8] = { - 0x11111111, - 0x11111111, - 0x01111110, - 0x01111110, - 0x00111100, - 0x00111100, - 0x00011000, - 0x00011000 + 0b11111111, + 0b11111111, + 0b01111110, + 0b01111110, + 0b00111100, + 0b00111100, + 0b00011000, + 0b00011000 }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index 82ff2fe8f..98a7f6d13 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -416,7 +416,7 @@ void ButtonWidget::drawWidget(bool hilite) { FBSurface& s = _boss->dialog().surface(); s.drawString(_font, _label, _x, _y + (_h - _fontHeight)/2 + 1, _w, - !isEnabled() ? hilite ? uInt32(kColor) : uInt32(kBGColorLo) : + !isEnabled() ? hilite ? uInt32(kColor) : uInt32(kBGColorLo) : hilite ? _textcolorhi : _textcolor, _align); } @@ -424,38 +424,38 @@ void ButtonWidget::drawWidget(bool hilite) /* 8x8 checkbox bitmap */ static uInt32 checked_img_active[8] = { - 0x11111111, - 0x11111111, - 0x11111111, - 0x11111111, - 0x11111111, - 0x11111111, - 0x11111111, - 0x11111111 + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111 }; static uInt32 checked_img_inactive[8] = { - 0x11111111, - 0x11111111, - 0x11100111, - 0x11000011, - 0x11000011, - 0x11100111, - 0x11111111, - 0x11111111 + 0b11111111, + 0b11111111, + 0b11100111, + 0b11000011, + 0b11000011, + 0b11100111, + 0b11111111, + 0b11111111 }; static uInt32 checked_img_circle[8] = { - 0x00011000, - 0x01111110, - 0x01111110, - 0x11111111, - 0x11111111, - 0x01111110, - 0x01111110, - 0x00011000 + 0b00011000, + 0b01111110, + 0b01111110, + 0b11111111, + 0b11111111, + 0b01111110, + 0b01111110, + 0b00011000 }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -559,14 +559,131 @@ void CheckboxWidget::drawWidget(bool hilite) s.box(_x, _y + _boxY, 14, 14, kColor, kShadowColor); // Do we draw a square or cross? - s.fillRect(_x + 2, _y + _boxY + 2, 10, 10, _bgcolor); - if(isEnabled()) - { - if(_state) - s.drawBitmap(_img, _x + 3, _y + _boxY + 3, kCheckColor); - } + s.fillRect(_x + 2, _y + _boxY + 2, 10, 10, isEnabled() ? _bgcolor : kColor); + if(_state) + s.drawBitmap(_img, _x + 3, _y + _boxY + 3, isEnabled() ? kCheckColor : kShadowColor); + + // Finally draw the label + s.drawString(_font, _label, _x + 20, _y + _textY, _w, + isEnabled() ? kTextColor : kColor); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/* 8x8 radiobutton bitmap */ +static uInt32 radio_img_outercircle[14] = +{ + 0b00001111110000, + 0b00111111111100, + 0b01110000001110, + 0b01100000000110, + 0b11000000000011, + 0b11000000000011, + 0b11000000000011, + 0b11000000000011, + 0b11000000000011, + 0b11000000000011, + 0b01100000000110, + 0b01110000001110, + 0b00111111111100, + 0b00001111110000 +}; + +static uInt32 radio_img_innercircle[10] = +{ + 0b0011111100, + 0b0111111110, + 0b1111111111, + 0b1111111111, + 0b1111111111, + 0b1111111111, + 0b1111111111, + 0b1111111111, + 0b0111111110, + 0b0011111100 +}; + +static uInt32 radio_img_active[8] = +{ + 0b00111100, + 0b01111110, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b01111110, + 0b00111100 +}; + +static uInt32 radio_img_inactive[8] = +{ + 0b00111100, + 0b01111110, + 0b11100111, + 0b11000011, + 0b11000011, + 0b11100111, + 0b01111110, + 0b00111100 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +RadioButtonWidget::RadioButtonWidget(GuiObject* boss, const GUI::Font& font, + int x, int y, const string& label, + int cmd) + : CheckboxWidget(boss, font, x, y, label, cmd) +{ + _flags = WIDGET_ENABLED; + _bgcolor = _bgcolorhi = kWidColor; + + _editable = true; + + if(label == "") + _w = 14; else - s.fillRect(_x + 2, _y + _boxY + 2, 10, 10, kColor); + _w = font.getStringWidth(label) + 20; + _h = font.getFontHeight() < 14 ? 14 : font.getFontHeight(); + + + // Depending on font size, either the font or box will need to be + // centered vertically + if(_h > 14) // center box + _boxY = (_h - 14) / 2; + else // center text + _textY = (14 - _font.getFontHeight()) / 2; + + setFill(CheckboxWidget::Normal); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RadioButtonWidget::setFill(FillType type) +{ + switch(type) + { + case CheckboxWidget::Normal: + _img = radio_img_active; + break; + case CheckboxWidget::Inactive: + _img = radio_img_inactive; + break; + default: + break; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RadioButtonWidget::drawWidget(bool hilite) +{ + FBSurface& s = _boss->dialog().surface(); + + // Draw the outer bounding circle + s.drawBitmap(radio_img_outercircle, _x, _y + _boxY, kShadowColor, 14, 14); + + // Draw the inner bounding circle with enabled color + s.drawBitmap(radio_img_innercircle, _x + 2, _y + _boxY + 2, isEnabled() ? _bgcolor : kColor, 10, 10); + + // draw state + if(_state) + s.drawBitmap(_img, _x + 3, _y + _boxY + 3, isEnabled() ? kCheckColor : kShadowColor); // Finally draw the label s.drawString(_font, _label, _x + 20, _y + _textY, _w, diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index 18bcb2a7e..5b67cdebb 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -276,11 +276,11 @@ class CheckboxWidget : public ButtonWidget uInt32* _img; uInt32 _fillColor; - - private: int _boxY; int _textY; + private: + private: // Following constructors and assignment operators not supported CheckboxWidget() = delete; @@ -290,6 +290,25 @@ class CheckboxWidget : public ButtonWidget CheckboxWidget& operator=(CheckboxWidget&&) = delete; }; +class RadioButtonWidget : public CheckboxWidget +{ +public: + RadioButtonWidget(GuiObject* boss, const GUI::Font& font, int x, int y, + const string& label, int cmd = 0); + +protected: + void setFill(FillType type); + void drawWidget(bool hilite) override; + +private: + // Following constructors and assignment operators not supported + RadioButtonWidget() = delete; + RadioButtonWidget(const RadioButtonWidget&) = delete; + RadioButtonWidget(RadioButtonWidget&&) = delete; + RadioButtonWidget& operator=(const RadioButtonWidget&) = delete; + RadioButtonWidget& operator=(RadioButtonWidget&&) = delete; +}; + /* SliderWidget */ class SliderWidget : public ButtonWidget