aboutsummaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/ThemeEngine.cpp474
-rw-r--r--gui/ThemeEngine.h31
-rw-r--r--gui/ThemeEval.cpp16
-rw-r--r--gui/ThemeLayout.cpp2
-rw-r--r--gui/ThemeLayout.h40
-rw-r--r--gui/Tooltip.cpp2
-rw-r--r--gui/credits.h16
-rw-r--r--gui/dialog.cpp8
-rw-r--r--gui/gui-manager.cpp6
-rw-r--r--gui/gui-manager.h1
-rw-r--r--gui/launcher.cpp2
-rw-r--r--gui/module.mk1
-rw-r--r--gui/object.cpp13
-rw-r--r--gui/options.cpp6
-rw-r--r--gui/predictivedialog.cpp3
-rw-r--r--gui/saveload-dialog.cpp2
-rw-r--r--gui/themes/default.inc14
-rw-r--r--gui/themes/scummclassic.zipbin112109 -> 115643 bytes
-rw-r--r--gui/themes/scummclassic/classic_layout.stx6
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx8
-rw-r--r--gui/themes/scummmodern.zipbin1487883 -> 1491681 bytes
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx6
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx8
-rw-r--r--gui/themes/translations.datbin567688 -> 570539 bytes
-rw-r--r--gui/updates-dialog.cpp6
-rw-r--r--gui/widget.cpp71
-rw-r--r--gui/widget.h4
-rw-r--r--gui/widgets/editable.cpp4
-rw-r--r--gui/widgets/edittext.cpp8
-rw-r--r--gui/widgets/list.cpp8
-rw-r--r--gui/widgets/popup.cpp21
-rw-r--r--gui/widgets/scrollbar.cpp7
-rw-r--r--gui/widgets/scrollcontainer.cpp147
-rw-r--r--gui/widgets/scrollcontainer.h63
-rw-r--r--gui/widgets/tab.cpp24
-rw-r--r--gui/widgets/tab.h1
36 files changed, 935 insertions, 94 deletions
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index c2deb8c61e..c850a6a02e 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -121,6 +121,19 @@ protected:
const WidgetDrawData *_data;
};
+class ThemeItemDrawDataClip: public ThemeItem{
+public:
+ ThemeItemDrawDataClip(ThemeEngine *engine, const WidgetDrawData *data, const Common::Rect &area, const Common::Rect &clip, uint32 dynData) :
+ ThemeItem(engine, area), _dynamicData(dynData), _data(data), _clip(clip) {}
+
+ void drawSelf(bool draw, bool restore);
+
+protected:
+ uint32 _dynamicData;
+ const WidgetDrawData *_data;
+ const Common::Rect _clip;
+};
+
class ThemeItemTextData : public ThemeItem {
public:
ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const TextColorData *color, const Common::Rect &area, const Common::Rect &textDrawableArea,
@@ -155,7 +168,18 @@ protected:
bool _alpha;
};
+class ThemeItemBitmapClip : public ThemeItem {
+public:
+ ThemeItemBitmapClip(ThemeEngine *engine, const Common::Rect &area, const Common::Rect &clip, const Graphics::Surface *bitmap, bool alpha) :
+ ThemeItem(engine, area), _bitmap(bitmap), _alpha(alpha), _clip(clip) {}
+
+ void drawSelf(bool draw, bool restore);
+protected:
+ const Graphics::Surface *_bitmap;
+ bool _alpha;
+ const Common::Rect _clip;
+};
/**********************************************************
* Data definitions for theme engine elements
@@ -242,16 +266,40 @@ void ThemeItemDrawData::drawSelf(bool draw, bool restore) {
_engine->addDirtyRect(extendedRect);
}
+void ThemeItemDrawDataClip::drawSelf(bool draw, bool restore) {
+
+ Common::Rect extendedRect = _area;
+ extendedRect.grow(_engine->kDirtyRectangleThreshold + _data->_backgroundOffset);
+
+ if (restore)
+ _engine->restoreBackground(extendedRect);
+
+ if (draw) {
+ Common::List<Graphics::DrawStep>::const_iterator step;
+ for (step = _data->_steps.begin(); step != _data->_steps.end(); ++step) {
+ _engine->renderer()->drawStepClip(_area, _clip, *step, _dynamicData);
+ }
+ }
+
+ extendedRect.clip(_clip);
+
+ _engine->addDirtyRect(extendedRect);
+}
+
void ThemeItemTextData::drawSelf(bool draw, bool restore) {
+ Common::Rect dirty = _textDrawableArea;
+ if (dirty.isEmpty()) dirty = _area;
+ else dirty.clip(_area);
+
if (_restoreBg || restore)
- _engine->restoreBackground(_area);
+ _engine->restoreBackground(dirty);
if (draw) {
_engine->renderer()->setFgColor(_color->r, _color->g, _color->b);
_engine->renderer()->drawString(_data->_fontPtr, _text, _area, _alignH, _alignV, _deltax, _ellipsis, _textDrawableArea);
}
- _engine->addDirtyRect(_area);
+ _engine->addDirtyRect(dirty);
}
void ThemeItemBitmap::drawSelf(bool draw, bool restore) {
@@ -268,7 +316,21 @@ void ThemeItemBitmap::drawSelf(bool draw, bool restore) {
_engine->addDirtyRect(_area);
}
+void ThemeItemBitmapClip::drawSelf(bool draw, bool restore) {
+ if (restore)
+ _engine->restoreBackground(_area);
+ if (draw) {
+ if (_alpha)
+ _engine->renderer()->blitAlphaBitmapClip(_bitmap, _area, _clip);
+ else
+ _engine->renderer()->blitSubSurfaceClip(_bitmap, _area, _clip);
+ }
+
+ Common::Rect dirtyRect = _area;
+ dirtyRect.clip(_clip);
+ _engine->addDirtyRect(dirtyRect);
+}
/**********************************************************
* ThemeEngine class
@@ -311,6 +373,12 @@ ThemeEngine::ThemeEngine(Common::String id, GraphicsMode mode) :
_themeArchive = 0;
_initOk = false;
+ _cursorHotspotX = _cursorHotspotY = 0;
+ _cursorWidth = _cursorHeight = 0;
+ _cursorPalSize = 0;
+
+ _needPaletteUpdates = false;
+
// We prefer files in archive bundles over the common search paths.
_themeFiles.add("default", &SearchMan, 0, false);
}
@@ -558,7 +626,7 @@ void ThemeEngine::restoreBackground(Common::Rect r) {
void ThemeEngine::addDrawStep(const Common::String &drawDataId, const Graphics::DrawStep &step) {
DrawData id = parseDrawDataId(drawDataId);
- assert(_widgets[id] != 0);
+ assert(id != kDDNone && _widgets[id] != 0);
_widgets[id]->_steps.push_back(step);
}
@@ -856,10 +924,34 @@ void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic,
}
}
+void ThemeEngine::queueDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic, bool restore) {
+ if (_widgets[type] == 0)
+ return;
+
+ Common::Rect area = r;
+ area.clip(_screen.w, _screen.h);
+
+ ThemeItemDrawDataClip *q = new ThemeItemDrawDataClip(this, _widgets[type], area, clippingRect, dynamic);
+
+ if (_buffering) {
+ if (_widgets[type]->_buffer) {
+ _bufferQueue.push_back(q);
+ } else {
+ if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type)
+ queueDDClip(kDrawDataDefaults[type].parent, r, clippingRect);
+
+ _screenQueue.push_back(q);
+ }
+ } else {
+ q->drawSelf(!_widgets[type]->_buffer, restore || _widgets[type]->_buffer);
+ delete q;
+ }
+}
+
void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax, const Common::Rect &drawableTextArea) {
- if (_texts[type] == 0)
+ if (type == kTextDataNone || _texts[type] == 0)
return;
Common::Rect area = r;
@@ -875,6 +967,28 @@ void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect
}
}
+void ThemeEngine::queueDDTextClip(TextData type, TextColor color, const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &text, bool restoreBg,
+ bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax, const Common::Rect &drawableTextArea) {
+
+ if (_texts[type] == 0)
+ return;
+
+ Common::Rect area = r;
+ area.clip(_screen.w, _screen.h);
+ Common::Rect textArea = drawableTextArea;
+ if (textArea.isEmpty()) textArea = clippingArea;
+ else textArea.clip(clippingArea);
+
+ ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], _textColors[color], area, textArea, text, alignH, alignV, ellipsis, restoreBg, deltax);
+
+ if (_buffering) {
+ _screenQueue.push_back(q);
+ } else {
+ q->drawSelf(true, false);
+ delete q;
+ }
+}
+
void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha) {
Common::Rect area = r;
@@ -890,7 +1004,20 @@ void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rec
}
}
+void ThemeEngine::queueBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &r, const Common::Rect &clip, bool alpha) {
+
+ Common::Rect area = r;
+ area.clip(_screen.w, _screen.h);
+
+ ThemeItemBitmapClip *q = new ThemeItemBitmapClip(this, area, clip, bitmap, alpha);
+ if (_buffering) {
+ _screenQueue.push_back(q);
+ } else {
+ q->drawSelf(true, false);
+ delete q;
+ }
+}
/**********************************************************
* Widget drawing functions
@@ -914,6 +1041,25 @@ void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, W
queueDDText(getTextData(dd), getTextColor(dd), r, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
}
+void ThemeEngine::drawButtonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str, WidgetStateInfo state, uint16 hints) {
+ if (!ready())
+ return;
+
+ DrawData dd = kDDButtonIdle;
+
+ if (state == kStateEnabled)
+ dd = kDDButtonIdle;
+ else if (state == kStateHighlight)
+ dd = kDDButtonHover;
+ else if (state == kStateDisabled)
+ dd = kDDButtonDisabled;
+ else if (state == kStatePressed)
+ dd = kDDButtonPressed;
+
+ queueDDClip(dd, r, clippingRect, 0, hints & WIDGET_CLEARBG);
+ queueDDTextClip(getTextData(dd), getTextColor(dd), r, clippingRect, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
+}
+
void ThemeEngine::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) {
if (!ready())
return;
@@ -921,6 +1067,13 @@ void ThemeEngine::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state
queueDD(kDDSeparator, r);
}
+void ThemeEngine::drawLineSeparatorClip(const Common::Rect &r, const Common::Rect &clippingRect, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ queueDDClip(kDDSeparator, r, clippingRect);
+}
+
void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
if (!ready())
return;
@@ -947,6 +1100,32 @@ void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str,
queueDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
}
+void ThemeEngine::drawCheckboxClip(const Common::Rect &r, const Common::Rect &clip, const Common::String &str, bool checked, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ Common::Rect r2 = r;
+ DrawData dd = kDDCheckboxDefault;
+
+ if (checked)
+ dd = kDDCheckboxSelected;
+
+ if (state == kStateDisabled)
+ dd = kDDCheckboxDisabled;
+
+ const int checkBoxSize = MIN((int)r.height(), getFontHeight());
+
+ r2.bottom = r2.top + checkBoxSize;
+ r2.right = r2.left + checkBoxSize;
+
+ queueDDClip(dd, r2, clip);
+
+ r2.left = r2.right + checkBoxSize;
+ r2.right = r.right;
+
+ queueDDTextClip(getTextData(dd), getTextColor(dd), r2, clip, str, true, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
+}
+
void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
if (!ready())
return;
@@ -973,6 +1152,32 @@ void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &s
queueDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV);
}
+void ThemeEngine::drawRadiobuttonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str, bool checked, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ Common::Rect r2 = r;
+ DrawData dd = kDDRadiobuttonDefault;
+
+ if (checked)
+ dd = kDDRadiobuttonSelected;
+
+ if (state == kStateDisabled)
+ dd = kDDRadiobuttonDisabled;
+
+ const int checkBoxSize = MIN((int)r.height(), getFontHeight());
+
+ r2.bottom = r2.top + checkBoxSize;
+ r2.right = r2.left + checkBoxSize;
+
+ queueDDClip(dd, r2, clippingRect);
+
+ r2.left = r2.right + checkBoxSize;
+ r2.right = r.right;
+
+ queueDDTextClip(getTextData(dd), getTextColor(dd), r2, clippingRect, str, true, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV);
+}
+
void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) {
if (!ready())
return;
@@ -993,6 +1198,26 @@ void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo s
queueDD(dd, r2);
}
+void ThemeEngine::drawSliderClip(const Common::Rect &r, const Common::Rect &clip, int width, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ DrawData dd = kDDSliderFull;
+
+ if (state == kStateHighlight)
+ dd = kDDSliderHover;
+ else if (state == kStateDisabled)
+ dd = kDDSliderDisabled;
+
+ Common::Rect r2 = r;
+ r2.setWidth(MIN((int16)width, r.width()));
+ // r2.top++; r2.bottom--; r2.left++; r2.right--;
+
+ drawWidgetBackgroundClip(r, clip, 0, kWidgetBackgroundSlider, kStateEnabled);
+
+ queueDDClip(dd, r2, clip);
+}
+
void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) {
if (!ready())
return;
@@ -1014,11 +1239,34 @@ void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHe
r2.top += sliderY;
r2.bottom = r2.top + sliderHeight;
- r2.top += r.width() / 5;
- r2.bottom -= r.width() / 5;
+ //r2.top += r.width() / 5;
+ //r2.bottom -= r.width() / 5;
queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2);
}
+void ThemeEngine::drawScrollbarClip(const Common::Rect &r, const Common::Rect &clippingRect, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ queueDDClip(kDDScrollbarBase, r, clippingRect);
+
+ Common::Rect r2 = r;
+ const int buttonExtra = (r.width() * 120) / 100;
+
+ r2.bottom = r2.top + buttonExtra;
+ queueDDClip(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, clippingRect, Graphics::VectorRenderer::kTriangleUp);
+
+ r2.translate(0, r.height() - r2.height());
+ queueDDClip(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, clippingRect, Graphics::VectorRenderer::kTriangleDown);
+
+ r2 = r;
+ r2.left += 1;
+ r2.right -= 1;
+ r2.top += sliderY;
+ r2.bottom = r2.top + sliderHeight;
+ queueDDClip(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2, clippingRect);
+}
+
void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) {
if (!ready())
return;
@@ -1046,6 +1294,33 @@ void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground b
}
}
+void ThemeEngine::drawDialogBackgroundClip(const Common::Rect &r, const Common::Rect &clip, DialogBackground bgtype, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ switch (bgtype) {
+ case kDialogBackgroundMain:
+ queueDDClip(kDDMainDialogBackground, r, clip);
+ break;
+
+ case kDialogBackgroundSpecial:
+ queueDDClip(kDDSpecialColorBackground, r, clip);
+ break;
+
+ case kDialogBackgroundPlain:
+ queueDDClip(kDDPlainColorBackground, r, clip);
+ break;
+
+ case kDialogBackgroundTooltip:
+ queueDDClip(kDDTooltipBackground, r, clip);
+ break;
+
+ case kDialogBackgroundDefault:
+ queueDDClip(kDDDefaultBackground, r, clip);
+ break;
+ }
+}
+
void ThemeEngine::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) {
if (!ready())
return;
@@ -1057,6 +1332,17 @@ void ThemeEngine::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo s
queueDD(kDDCaret, r);
}
+void ThemeEngine::drawCaretClip(const Common::Rect &r, const Common::Rect &clip, bool erase, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ if (erase) {
+ restoreBackground(r);
+ addDirtyRect(r);
+ } else
+ queueDDClip(kDDCaret, r, clip);
+}
+
void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, Graphics::TextAlign align) {
if (!ready())
return;
@@ -1078,6 +1364,27 @@ void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &s
}
}
+void ThemeEngine::drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect &clip, const Common::String &sel, int deltax, WidgetStateInfo state, Graphics::TextAlign align) {
+ if (!ready())
+ return;
+
+ DrawData dd = kDDPopUpIdle;
+
+ if (state == kStateEnabled)
+ dd = kDDPopUpIdle;
+ else if (state == kStateHighlight)
+ dd = kDDPopUpHover;
+ else if (state == kStateDisabled)
+ dd = kDDPopUpDisabled;
+
+ queueDDClip(dd, r, clip);
+
+ if (!sel.empty()) {
+ Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
+ queueDDTextClip(getTextData(dd), getTextColor(dd), text, clip, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax);
+ }
+}
+
void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) {
if (!ready())
return;
@@ -1085,6 +1392,13 @@ void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &su
queueBitmap(&surface, r, themeTrans);
}
+void ThemeEngine::drawSurfaceClip(const Common::Rect &r, const Common::Rect &clip, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) {
+ if (!ready())
+ return;
+
+ queueBitmapClip(&surface, r, clip, themeTrans);
+}
+
void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) {
if (!ready())
return;
@@ -1108,6 +1422,29 @@ void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, Widg
}
}
+void ThemeEngine::drawWidgetBackgroundClip(const Common::Rect &r, const Common::Rect &clip, uint16 hints, WidgetBackground background, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ switch (background) {
+ case kWidgetBackgroundBorderSmall:
+ queueDDClip(kDDWidgetBackgroundSmall, r, clip);
+ break;
+
+ case kWidgetBackgroundEditText:
+ queueDDClip(kDDWidgetBackgroundEditText, r, clip);
+ break;
+
+ case kWidgetBackgroundSlider:
+ queueDDClip(kDDWidgetBackgroundSlider, r, clip);
+ break;
+
+ default:
+ queueDDClip(kDDWidgetBackgroundDefault, r, clip);
+ break;
+ }
+}
+
void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
if (!ready())
return;
@@ -1136,6 +1473,34 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co
}
}
+void ThemeEngine::drawTabClip(const Common::Rect &r, const Common::Rect &clip, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ queueDDClip(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight), clip);
+
+ for (int i = 0; i < (int)tabs.size(); ++i) {
+ if (i == active)
+ continue;
+
+ if (r.left + i * tabWidth > r.right || r.left + (i + 1) * tabWidth > r.right)
+ continue;
+
+ Common::Rect tabRect(r.left + i * tabWidth, r.top, r.left + (i + 1) * tabWidth, r.top + tabHeight);
+ queueDDClip(kDDTabInactive, tabRect, clip);
+ queueDDTextClip(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, clip, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
+ }
+
+ if (active >= 0 &&
+ (r.left + active * tabWidth < r.right) && (r.left + (active + 1) * tabWidth < r.right)) {
+ Common::Rect tabRect(r.left + active * tabWidth, r.top, r.left + (active + 1) * tabWidth, r.top + tabHeight);
+ const uint16 tabLeft = active * tabWidth;
+ const uint16 tabRight = MAX(r.right - tabRect.right, 0);
+ queueDDClip(kDDTabActive, tabRect, clip, (tabLeft << 16) | (tabRight & 0xFFFF));
+ queueDDTextClip(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, clip, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
+ }
+}
+
void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) {
if (!ready())
return;
@@ -1209,6 +1574,79 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid
queueDDText(textId, colorId, r, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea);
}
+void ThemeEngine::drawTextClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) {
+ if (!ready())
+ return;
+
+ TextColor colorId = kTextColorMAX;
+
+ switch (color) {
+ case kFontColorNormal:
+ if (inverted) {
+ colorId = kTextColorNormalInverted;
+ } else {
+ switch (state) {
+ case kStateDisabled:
+ colorId = kTextColorNormalDisabled;
+ break;
+
+ case kStateHighlight:
+ colorId = kTextColorNormalHover;
+ break;
+
+ case kStateEnabled:
+ case kStatePressed:
+ colorId = kTextColorNormal;
+ break;
+ }
+ }
+ break;
+
+ case kFontColorAlternate:
+ if (inverted) {
+ colorId = kTextColorAlternativeInverted;
+ } else {
+ switch (state) {
+ case kStateDisabled:
+ colorId = kTextColorAlternativeDisabled;
+ break;
+
+ case kStateHighlight:
+ colorId = kTextColorAlternativeHover;
+ break;
+
+ case kStateEnabled:
+ case kStatePressed:
+ colorId = kTextColorAlternative;
+ break;
+ }
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ TextData textId = fontStyleToData(font);
+
+ switch (inverted) {
+ case kTextInversion:
+ queueDDClip(kDDTextSelectionBackground, r, clippingArea);
+ restore = false;
+ break;
+
+ case kTextInversionFocus:
+ queueDDClip(kDDTextSelectionFocusBackground, r, clippingArea);
+ restore = false;
+ break;
+
+ default:
+ break;
+ }
+
+ queueDDTextClip(textId, colorId, r, clippingArea, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea);
+}
+
void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state, FontColor color) {
if (!ready())
return;
@@ -1223,6 +1661,21 @@ void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font
addDirtyRect(charArea);
}
+void ThemeEngine::drawCharClip(const Common::Rect &r, const Common::Rect &clip, byte ch, const Graphics::Font *font, WidgetStateInfo state, FontColor color) {
+ if (!ready())
+ return;
+
+ Common::Rect charArea = r;
+ charArea.clip(_screen.w, _screen.h);
+ if (!clip.isEmpty()) charArea.clip(clip);
+
+ uint32 rgbColor = _overlayFormat.RGBToColor(_textColors[color]->r, _textColors[color]->g, _textColors[color]->b);
+
+ restoreBackground(charArea);
+ font->drawChar(&_screen, ch, charArea.left, charArea.top, rgbColor);
+ addDirtyRect(charArea);
+}
+
void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) {
_font->drawString(&_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true);
_screen.hLine(r.left, r.top, r.right, 0xFFFF);
@@ -1259,8 +1712,15 @@ void ThemeEngine::updateScreen(bool render) {
_screenQueue.clear();
}
- if (render)
+ if (render) {
+#ifdef LAYOUT_DEBUG_DIALOG
+ _vectorRenderer->fillSurface();
+ _themeEval->debugDraw(&_screen, _font);
+ _vectorRenderer->copyWholeFrame(_system);
+#else
renderDirtyScreen();
+#endif
+ }
}
void ThemeEngine::addDirtyRect(Common::Rect r) {
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index a5ef49c78b..3c259b4f9d 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -340,42 +340,67 @@ public:
void drawWidgetBackground(const Common::Rect &r, uint16 hints,
WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
+ void drawWidgetBackgroundClip(const Common::Rect &r, const Common::Rect &clippingArea, uint16 hints,
+ WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
void drawButton(const Common::Rect &r, const Common::String &str,
WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
+ void drawButtonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
+ WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
void drawSurface(const Common::Rect &r, const Graphics::Surface &surface,
- WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false);
+ WidgetStateInfo state = kStateEnabled, int alpha = 255, bool themeTrans = false);
+ void drawSurfaceClip(const Common::Rect &r, const Common::Rect &clippingRect, const Graphics::Surface &surface,
+ WidgetStateInfo state = kStateEnabled, int alpha = 255, bool themeTrans = false);
void drawSlider(const Common::Rect &r, int width,
WidgetStateInfo state = kStateEnabled);
+ void drawSliderClip(const Common::Rect &r, const Common::Rect &clippingRect, int width,
+ WidgetStateInfo state = kStateEnabled);
void drawCheckbox(const Common::Rect &r, const Common::String &str,
bool checked, WidgetStateInfo state = kStateEnabled);
+ void drawCheckboxClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
+ bool checked, WidgetStateInfo state = kStateEnabled);
void drawRadiobutton(const Common::Rect &r, const Common::String &str,
bool checked, WidgetStateInfo state = kStateEnabled);
+ void drawRadiobuttonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
+ bool checked, WidgetStateInfo state = kStateEnabled);
void drawTab(const Common::Rect &r, int tabHeight, int tabWidth,
const Common::Array<Common::String> &tabs, int active, uint16 hints,
int titleVPad, WidgetStateInfo state = kStateEnabled);
+ void drawTabClip(const Common::Rect &r, const Common::Rect &clippingRect, int tabHeight, int tabWidth,
+ const Common::Array<Common::String> &tabs, int active, uint16 hints,
+ int titleVPad, WidgetStateInfo state = kStateEnabled);
void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight,
ScrollbarState, WidgetStateInfo state = kStateEnabled);
+ void drawScrollbarClip(const Common::Rect &r, const Common::Rect &clippingRect, int sliderY, int sliderHeight,
+ ScrollbarState scrollState, WidgetStateInfo state = kStateEnabled);
void drawPopUpWidget(const Common::Rect &r, const Common::String &sel,
int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
+ void drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &sel,
+ int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
void drawCaret(const Common::Rect &r, bool erase,
WidgetStateInfo state = kStateEnabled);
+ void drawCaretClip(const Common::Rect &r, const Common::Rect &clip, bool erase,
+ WidgetStateInfo state = kStateEnabled);
void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled);
+ void drawLineSeparatorClip(const Common::Rect &r, const Common::Rect &clippingArea, WidgetStateInfo state = kStateEnabled);
void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled);
+ void drawDialogBackgroundClip(const Common::Rect &r, const Common::Rect &clip, DialogBackground type, WidgetStateInfo state = kStateEnabled);
void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
+ void drawTextClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
+ void drawCharClip(const Common::Rect &r, const Common::Rect &clippingArea, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
//@}
@@ -584,9 +609,13 @@ protected:
* This function is called from all the Widget Drawing methods.
*/
void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool restore = false);
+ void queueDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic = 0, bool restore = false);
void queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
+ void queueDDTextClip(TextData type, TextColor color, const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &text, bool restoreBg,
+ bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha);
+ void queueBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &clippingRect, const Common::Rect &r, bool alpha);
/**
* DEBUG: Draws a white square and writes some text next to it.
diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp
index 9d57d2408b..5255587089 100644
--- a/gui/ThemeEval.cpp
+++ b/gui/ThemeEval.cpp
@@ -91,10 +91,18 @@ void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common
typeAlign = (Graphics::TextAlign)getVar("Globals." + type + ".Align", Graphics::kTextAlignInvalid);
}
- ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name,
- typeW == -1 ? w : typeW,
- typeH == -1 ? h : typeH,
- typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign);
+ ThemeLayoutWidget *widget;
+ if (type == "TabWidget")
+ widget = new ThemeLayoutTabWidget(_curLayout.top(), name,
+ typeW == -1 ? w : typeW,
+ typeH == -1 ? h : typeH,
+ typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign,
+ getVar("Globals.TabWidget.Tab.Height", 0));
+ else
+ widget = new ThemeLayoutWidget(_curLayout.top(), name,
+ typeW == -1 ? w : typeW,
+ typeH == -1 ? h : typeH,
+ typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign);
_curLayout.top()->addChild(widget);
setVar(_curDialog + "." + name + ".Enabled", enabled ? 1 : 0);
diff --git a/gui/ThemeLayout.cpp b/gui/ThemeLayout.cpp
index 6a6fd9e343..71e4b2c9fd 100644
--- a/gui/ThemeLayout.cpp
+++ b/gui/ThemeLayout.cpp
@@ -123,7 +123,7 @@ int16 ThemeLayoutStacked::getParentHeight() {
#ifdef LAYOUT_DEBUG_DIALOG
void ThemeLayout::debugDraw(Graphics::Surface *screen, const Graphics::Font *font) {
- uint16 color = 0xFFFF;
+ uint32 color = 0xFFFFFFFF;
font->drawString(screen, getName(), _x, _y, _w, color, Graphics::kTextAlignRight, 0, true);
screen->hLine(_x, _y, _x + _w, color);
screen->hLine(_x, _y + _h, _x + _w , color);
diff --git a/gui/ThemeLayout.h b/gui/ThemeLayout.h
index ba28fae1ac..e738002aa6 100644
--- a/gui/ThemeLayout.h
+++ b/gui/ThemeLayout.h
@@ -29,7 +29,7 @@
#ifdef LAYOUT_DEBUG_DIALOG
namespace Graphics {
-class Surface;
+struct Surface;
}
#endif
@@ -45,7 +45,8 @@ public:
kLayoutMain,
kLayoutVertical,
kLayoutHorizontal,
- kLayoutWidget
+ kLayoutWidget,
+ kLayoutTabWidget
};
ThemeLayout(ThemeLayout *p) :
@@ -223,6 +224,41 @@ protected:
Common::String _name;
};
+class ThemeLayoutTabWidget : public ThemeLayoutWidget {
+ int _tabHeight;
+
+public:
+ ThemeLayoutTabWidget(ThemeLayout *p, const Common::String &name, int16 w, int16 h, Graphics::TextAlign align, int tabHeight):
+ ThemeLayoutWidget(p, name, w, h, align) {
+ _tabHeight = tabHeight;
+ }
+
+ void reflowLayout() {
+ for (uint i = 0; i < _children.size(); ++i) {
+ _children[i]->resetLayout();
+ _children[i]->reflowLayout();
+ }
+ }
+
+ virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) {
+ if (ThemeLayoutWidget::getWidgetData(name, x, y, w, h)) {
+ h -= _tabHeight;
+ return true;
+ }
+
+ return false;
+ }
+
+protected:
+ LayoutType getLayoutType() { return kLayoutTabWidget; }
+
+ ThemeLayout *makeClone(ThemeLayout *newParent) {
+ ThemeLayoutTabWidget *n = new ThemeLayoutTabWidget(*this);
+ n->_parent = newParent;
+ return n;
+ }
+};
+
class ThemeLayoutSpacing : public ThemeLayout {
public:
ThemeLayoutSpacing(ThemeLayout *p, int size) : ThemeLayout(p) {
diff --git a/gui/Tooltip.cpp b/gui/Tooltip.cpp
index ba313ee34f..09ad7ce5ca 100644
--- a/gui/Tooltip.cpp
+++ b/gui/Tooltip.cpp
@@ -32,7 +32,7 @@ namespace GUI {
Tooltip::Tooltip() :
- Dialog(-1, -1, -1, -1), _maxWidth(-1) {
+ Dialog(-1, -1, -1, -1), _maxWidth(-1), _parent(NULL), _xdelta(0), _ydelta(0) {
_backgroundType = GUI::ThemeEngine::kDialogBackgroundTooltip;
}
diff --git a/gui/credits.h b/gui/credits.h
index d1d3bb2147..c2c4c84ec6 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -58,6 +58,7 @@ static const char *credits[] = {
"C1""AGI",
"C0""Stuart George",
"C0""Matthew Hoops",
+"C2""(retired)",
"C0""Filippos Karapetis",
"C0""Martin Kiewitz",
"C0""Pawel Kolodziejski",
@@ -127,6 +128,7 @@ static const char *credits[] = {
"C1""Drascula",
"C0""Filippos Karapetis",
"C0""Pawel Kolodziejski",
+"C0""Thierry Crozat",
"",
"C1""DreamWeb",
"A0""Torbjorn Andersson",
@@ -137,6 +139,11 @@ static const char *credits[] = {
"C2""(retired)",
"C0""Willem Jan Palenstijn",
"",
+"C1""Gnap",
+"A0""Arnaud Boutonne",
+"C0""Arnaud Boutonn\351",
+"C0""Benjamin Haisch",
+"",
"C1""Gob",
"A0""Torbjorn Andersson",
"C0""Torbj\366rn Andersson",
@@ -173,6 +180,7 @@ static const char *credits[] = {
"",
"C1""Lastexpress",
"C0""Matthew Hoops",
+"C2""(retired)",
"C0""Jordi Vilalta Prat",
"C0""Julien Templier",
"",
@@ -192,6 +200,7 @@ static const char *credits[] = {
"C1""Mohawk",
"C0""Bastien Bouclet",
"C0""Matthew Hoops",
+"C2""(retired)",
"C0""Filippos Karapetis",
"C0""Alyssa Milburn",
"C0""Eugene Sandulenko",
@@ -211,6 +220,7 @@ static const char *credits[] = {
"",
"C1""Pegasus",
"C0""Matthew Hoops",
+"C2""(retired)",
"",
"C1""Queen",
"C0""David Eriksson",
@@ -343,6 +353,7 @@ static const char *credits[] = {
"C1""Android",
"C0""Andre Heider",
"C0""Angus Lees",
+"C0""Lubomyr Lisen",
"",
"C1""Dreamcast",
"C0""Marcus Comstedt",
@@ -366,6 +377,9 @@ static const char *credits[] = {
"C2""(retired)",
"C0""Tarek Soliman",
"",
+"C1""Nintendo 3DS",
+"C0""Thomas Edvalson",
+"",
"C1""Nintendo 64",
"C0""Fabio Battaglia",
"",
@@ -477,7 +491,7 @@ static const char *credits[] = {
"C0""Joachim Eberhard",
"C2""Numerous contributions to documentation (retired)",
"C0""Matthew Hoops",
-"C2""Wiki editor",
+"C2""Numerous contributions to documentation (retired)",
"",
"C1""Retired Team Members",
"C0""Chris Apers",
diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index 075a3bb533..523227a237 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -51,6 +51,8 @@ Dialog::Dialog(int x, int y, int w, int h)
// will for example crash after returning to the launcher when the user
// started a 640x480 game with a non 1x scaler.
g_gui.checkScreenChange();
+
+ _result = -1;
}
Dialog::Dialog(const Common::String &name)
@@ -66,6 +68,8 @@ Dialog::Dialog(const Common::String &name)
// Fixes bug #1590596: "HE: When 3x graphics are choosen, F5 crashes game"
// and bug #1595627: "SCUMM: F5 crashes game (640x480)"
g_gui.checkScreenChange();
+
+ _result = -1;
}
int Dialog::runModal() {
@@ -109,13 +113,13 @@ void Dialog::reflowLayout() {
// changed, so any cached image may be invalid. The subsequent redraw
// should be treated as the very first draw.
+ GuiObject::reflowLayout();
+
Widget *w = _firstWidget;
while (w) {
w->reflowLayout();
w = w->_next;
}
-
- GuiObject::reflowLayout();
}
void Dialog::lostFocus() {
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 3ce8bee020..9acd9434ff 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -564,6 +564,12 @@ void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDi
}
}
+void GuiManager::doFullRedraw() {
+ _redrawStatus = kRedrawFull;
+ redraw();
+ _system->updateScreen();
+}
+
void GuiManager::giveFocusToDialog(Dialog *dialog) {
int16 dialogX = _globalMousePosition.x - dialog->_x;
int16 dialogY = _globalMousePosition.y - dialog->_y;
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index 35779215b2..4dc9af95fb 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -73,6 +73,7 @@ public:
void runLoop();
void processEvent(const Common::Event &event, Dialog *const activeDialog);
+ void doFullRedraw();
bool isActive() const { return ! _dialogStack.empty(); }
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index bae894cba1..9a3300b11f 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -282,6 +282,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
//
// 6) The MIDI tab
//
+ _globalMIDIOverride = NULL;
if (!_guioptions.contains(GUIO_NOMIDI)) {
tab->addTab(_("MIDI"));
@@ -296,6 +297,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
//
// 7) The MT-32 tab
//
+ _globalMT32Override = NULL;
if (!_guioptions.contains(GUIO_NOMIDI)) {
tab->addTab(_("MT-32"));
diff --git a/gui/module.mk b/gui/module.mk
index 9e821e71a7..6cbc63d24d 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -30,6 +30,7 @@ MODULE_OBJS := \
widgets/list.o \
widgets/popup.o \
widgets/scrollbar.o \
+ widgets/scrollcontainer.o \
widgets/tab.o
# HACK: create_project's XCode generator relies on the following ifdef
diff --git a/gui/object.cpp b/gui/object.cpp
index ef2cc9d6e0..de66d95492 100644
--- a/gui/object.cpp
+++ b/gui/object.cpp
@@ -44,19 +44,6 @@ void GuiObject::reflowLayout() {
if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) {
error("Could not load widget position for '%s'", _name.c_str());
}
-
- if (_x < 0)
- error("Widget <%s> has x < 0 (%d)", _name.c_str(), _x);
- if (_x >= g_gui.getWidth())
- error("Widget <%s> has x > %d (%d)", _name.c_str(), g_gui.getWidth(), _x);
- if (_x + _w > g_gui.getWidth())
- error("Widget <%s> has x + w > %d (%d)", _name.c_str(), g_gui.getWidth(), _x + _w);
- if (_y < 0)
- error("Widget <%s> has y < 0 (%d)", _name.c_str(), _y);
- if (_y >= g_gui.getHeight())
- error("Widget <%s> has y > %d (%d)", _name.c_str(), g_gui.getHeight(), _y);
- if (_y + _h > g_gui.getHeight())
- error("Widget <%s> has y + h > %d (%d)", _name.c_str(), g_gui.getHeight(), _y + _h);
}
}
diff --git a/gui/options.cpp b/gui/options.cpp
index 2bb17509eb..e410971818 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -112,6 +112,7 @@ void OptionsDialog::init() {
_fullscreenCheckbox = 0;
_aspectCheckbox = 0;
_enableAudioSettings = false;
+ _midiTabId = 0;
_midiPopUp = 0;
_midiPopUpDesc = 0;
_oplPopUp = 0;
@@ -144,6 +145,7 @@ void OptionsDialog::init() {
_speechVolumeSlider = 0;
_speechVolumeLabel = 0;
_muteCheckbox = 0;
+ _enableSubtitleSettings = false;
_subToggleDesc = 0;
_subToggleGroup = 0;
_subToggleSubOnly = 0;
@@ -152,6 +154,8 @@ void OptionsDialog::init() {
_subSpeedDesc = 0;
_subSpeedSlider = 0;
_subSpeedLabel = 0;
+
+ _pathsTabId = 0;
_oldTheme = g_gui.theme()->getThemeId();
// Retrieve game GUI options
@@ -209,7 +213,7 @@ void OptionsDialog::open() {
#ifdef GUI_ONLY_FULLSCREEN
_fullscreenCheckbox->setState(true);
_fullscreenCheckbox->setEnabled(false);
- _aspectCheckbox->setState(false);
+ _aspectCheckbox->setState(ConfMan.getBool("aspect_ratio", _domain));
_aspectCheckbox->setEnabled(false);
#else // !GUI_ONLY_FULLSCREEN
// Fullscreen setting
diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp
index 63b69a39ea..933667186e 100644
--- a/gui/predictivedialog.cpp
+++ b/gui/predictivedialog.cpp
@@ -142,6 +142,9 @@ PredictiveDialog::PredictiveDialog() : Dialog("Predictive") {
_numMemory = 0;
_navigationWithKeys = false;
+
+ _curPressedButton = kNoAct;
+ _needRefresh = true;
}
PredictiveDialog::~PredictiveDialog() {
diff --git a/gui/saveload-dialog.cpp b/gui/saveload-dialog.cpp
index a333c5fe57..3d4adfff2b 100644
--- a/gui/saveload-dialog.cpp
+++ b/gui/saveload-dialog.cpp
@@ -932,6 +932,8 @@ SavenameDialog::SavenameDialog()
new ButtonWidget(this, "SavenameDialog.Ok", _("OK"), 0, kOKCmd);
_description = new EditTextWidget(this, "SavenameDialog.Description", Common::String(), 0, 0, kOKCmd);
+
+ _targetSlot = 0;
}
void SavenameDialog::setDescription(const Common::String &desc) {
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index a23e2f4c30..c0ea733de8 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -798,7 +798,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</dialog>"
"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'>"
"<layout type='vertical' padding='0,0,0,0'>"
-"<widget name='TabWidget'/>"
+"<widget name='TabWidget' type='TabWidget'/>"
"<layout type='horizontal' padding='16,16,16,16'>"
"<space/>"
"<widget name='Cancel' "
@@ -1118,7 +1118,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</dialog>"
"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'>"
"<layout type='vertical' padding='0,0,0,0' spacing='16'>"
-"<widget name='TabWidget'/>"
+"<widget name='TabWidget' type='TabWidget'/>"
"<layout type='horizontal' padding='16,16,16,4'>"
"<space/>"
"<widget name='Cancel' "
@@ -1405,7 +1405,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</dialog>"
"<dialog name='FluidSynthSettings' overlays='GlobalOptions' shading='dim'>"
"<layout type='vertical' padding='0,0,0,0'>"
-"<widget name='TabWidget'/>"
+"<widget name='TabWidget' type='TabWidget'/>"
"<layout type='horizontal' padding='16,16,16,16'>"
"<space/>"
"<widget name='ResetSettings' "
@@ -1975,7 +1975,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"padding='0,0,2,0' "
"/>"
"<widget name='TabWidget.Body' "
-"padding='0,0,0,-8' "
+"padding='0,0,0,0' "
"/>"
"<widget name='TabWidget.NavButton' "
"size='32,18' "
@@ -2093,7 +2093,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</dialog>"
"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'>"
"<layout type='vertical' padding='0,0,0,0'>"
-"<widget name='TabWidget'/>"
+"<widget name='TabWidget' type='TabWidget'/>"
"<layout type='horizontal' padding='8,8,8,8'>"
"<space/>"
"<widget name='Cancel' "
@@ -2420,7 +2420,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</dialog>"
"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'>"
"<layout type='vertical' padding='0,0,0,0' spacing='16'>"
-"<widget name='TabWidget'/>"
+"<widget name='TabWidget' type='TabWidget'/>"
"<layout type='horizontal' padding='8,8,8,8'>"
"<space/>"
"<widget name='Cancel' "
@@ -2716,7 +2716,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</dialog>"
"<dialog name='FluidSynthSettings' overlays='GlobalOptions' shading='dim'>"
"<layout type='vertical' padding='0,0,0,0'>"
-"<widget name='TabWidget'/>"
+"<widget name='TabWidget' type='TabWidget'/>"
"<layout type='horizontal' padding='8,8,8,8'>"
"<space/>"
"<widget name='ResetSettings' "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 43fcea12fd..561f2a5dd3 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 65724d9faf..5172326859 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -222,7 +222,7 @@
<dialog name = 'GlobalOptions' overlays = 'Dialog.Launcher.GameList' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '16, 16, 16, 16'>
<space/>
<widget name = 'Cancel'
@@ -551,7 +551,7 @@
<dialog name = 'GameOptions' overlays = 'Dialog.Launcher.GameList' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0' spacing = '16'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '16, 16, 16, 4'>
<space/>
<widget name = 'Cancel'
@@ -850,7 +850,7 @@
<dialog name = 'FluidSynthSettings' overlays = 'GlobalOptions' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '16, 16, 16, 16'>
<space/>
<widget name = 'ResetSettings'
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index f73f6e864b..0013b91ee2 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -97,7 +97,7 @@
padding = '0, 0, 2, 0'
/>
<widget name = 'TabWidget.Body'
- padding = '0, 0, 0, -8'
+ padding = '0, 0, 0, 0'
/>
<widget name = 'TabWidget.NavButton'
size = '32, 18'
@@ -219,7 +219,7 @@
<dialog name = 'GlobalOptions' overlays = 'screen' inset = '16' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '8, 8, 8, 8'>
<space/>
<widget name = 'Cancel'
@@ -556,7 +556,7 @@
<dialog name = 'GameOptions' overlays = 'screen' inset = '16' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0' spacing = '16'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '8, 8, 8, 8'>
<space/>
<widget name = 'Cancel'
@@ -863,7 +863,7 @@
<dialog name = 'FluidSynthSettings' overlays = 'GlobalOptions' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '8, 8, 8, 8'>
<space/>
<widget name = 'ResetSettings'
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index 70f7672c57..d80c481ffc 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index c73ffa1f08..026fa7bc64 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -236,7 +236,7 @@
<dialog name = 'GlobalOptions' overlays = 'Dialog.Launcher.GameList' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '16, 16, 16, 16'>
<space/>
<widget name = 'Cancel'
@@ -565,7 +565,7 @@
<dialog name = 'GameOptions' overlays = 'Dialog.Launcher.GameList' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0' spacing = '16'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '16, 16, 16, 4'>
<space/>
<widget name = 'Cancel'
@@ -864,7 +864,7 @@
<dialog name = 'FluidSynthSettings' overlays = 'GlobalOptions' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '16, 16, 16, 16'>
<space/>
<widget name = 'ResetSettings'
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 43ec0cdee1..169e61a9bb 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -95,7 +95,7 @@
padding = '0, 0, 2, 0'
/>
<widget name = 'TabWidget.Body'
- padding = '0, 0, 0, -8'
+ padding = '0, 0, 0, 0'
/>
<widget name = 'TabWidget.NavButton'
size = '32, 18'
@@ -217,7 +217,7 @@
<dialog name = 'GlobalOptions' overlays = 'screen' inset = '16' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '8, 8, 8, 8'>
<space/>
<widget name = 'Cancel'
@@ -554,7 +554,7 @@
<dialog name = 'GameOptions' overlays = 'screen' inset = '16' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '8, 8, 8, 8'>
<space/>
<widget name = 'Cancel'
@@ -861,7 +861,7 @@
<dialog name = 'FluidSynthSettings' overlays = 'GlobalOptions' shading = 'dim'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
- <widget name = 'TabWidget'/>
+ <widget name = 'TabWidget' type = 'TabWidget'/>
<layout type = 'horizontal' padding = '8, 8, 8, 8'>
<space/>
<widget name = 'ResetSettings'
diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat
index 917acdb13d..7533d41454 100644
--- a/gui/themes/translations.dat
+++ b/gui/themes/translations.dat
Binary files differ
diff --git a/gui/updates-dialog.cpp b/gui/updates-dialog.cpp
index 960b3f397a..b82ecc0402 100644
--- a/gui/updates-dialog.cpp
+++ b/gui/updates-dialog.cpp
@@ -76,13 +76,13 @@ UpdatesDialog::UpdatesDialog() : Dialog(30, 20, 260, 124) {
_y = (screenH - _h) / 2;
// Each line is represented by one static text item.
- int y = 10;
- for (int i = 0; i < lines.size(); i++) {
+ uint y = 10;
+ for (uint i = 0; i < lines.size(); i++) {
new StaticTextWidget(this, 10, y, maxlineWidth, kLineHeight,
lines[i], Graphics::kTextAlignCenter);
y += kLineHeight;
}
- for (int i = 0; i < lines2.size(); i++) {
+ for (uint i = 0; i < lines2.size(); i++) {
new StaticTextWidget(this, 10, y, maxlineWidth2, kLineHeight,
lines2[i], Graphics::kTextAlignCenter, 0, ThemeEngine::kFontStyleTooltip);
y += kLineHeight;
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 03540f7b91..f2a29c3100 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -53,6 +53,31 @@ void Widget::init() {
_boss->_firstWidget = this;
}
+Common::Rect Widget::getBossClipRect() const {
+ int bx = _boss->getAbsX();
+ int by = _boss->getAbsY();
+ Common::Rect result = Common::Rect(bx, by, bx + _boss->getWidth(), by + _boss->getHeight());
+ bool needsClipping = false;
+
+ //check whether clipping area is inside the screen
+ if (result.left < 0 && (needsClipping = true))
+ warning("Widget <%s> has clipping area x < 0 (%d)", _name.c_str(), result.left);
+ if (result.left >= g_gui.getWidth() && (needsClipping = true))
+ warning("Widget <%s> has clipping area x > %d (%d)", _name.c_str(), g_gui.getWidth(), result.left);
+ if (result.right > g_gui.getWidth() && (needsClipping = true))
+ warning("Widget <%s> has clipping area x + w > %d (%d)", _name.c_str(), g_gui.getWidth(), result.right);
+ if (result.top < 0 && (needsClipping = true))
+ warning("Widget <%s> has clipping area y < 0 (%d)", _name.c_str(), result.top);
+ if (result.top >= g_gui.getHeight() && (needsClipping = true))
+ warning("Widget <%s> has clipping area y > %d (%d)", _name.c_str(), g_gui.getHeight(), result.top);
+ if (result.bottom > g_gui.getHeight() && (needsClipping = true))
+ warning("Widget <%s> has clipping area y + h > %d (%d)", _name.c_str(), g_gui.getHeight(), result.bottom);
+
+ if (needsClipping)
+ result.clip(g_gui.getWidth(), g_gui.getHeight());
+ return result;
+}
+
Widget::~Widget() {
delete _next;
_next = 0;
@@ -99,7 +124,7 @@ void Widget::draw() {
// Draw border
if (_flags & WIDGET_BORDER) {
- g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, ThemeEngine::kWidgetBackgroundBorder);
+ g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
_x += 4;
_y += 4;
_w -= 8;
@@ -131,7 +156,7 @@ void Widget::draw() {
Widget *Widget::findWidgetInChain(Widget *w, int x, int y) {
while (w) {
// Stop as soon as we find a widget that contains the point (x,y)
- if (x >= w->_x && x < w->_x + w->_w && y >= w->_y && y < w->_y + w->_h)
+ if (x >= w->_x && x < w->_x + w->_w && y >= w->_y && y < w->_y + w->getHeight())
break;
w = w->_next;
}
@@ -265,14 +290,25 @@ void StaticTextWidget::setLabel(const Common::String &label) {
}
void StaticTextWidget::setAlign(Graphics::TextAlign align) {
- _align = align;
- // TODO: We should automatically redraw when the alignment is changed.
- // See setLabel() for more insights.
+ if (_align != align){
+ _align = align;
+
+ // same as setLabel() actually, the text
+ // would be redrawn on top of the old one so
+ // we add the CLEARBG flag
+ setFlags(WIDGET_CLEARBG);
+ draw();
+ clearFlags(WIDGET_CLEARBG);
+ }
+
}
void StaticTextWidget::drawWidget() {
- g_gui.theme()->drawText(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, _align, ThemeEngine::kTextInversionNone, 0, true, _font);
+ g_gui.theme()->drawTextClip(
+ Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(),
+ _label, _state, _align, ThemeEngine::kTextInversionNone, 0, true, _font
+ );
}
#pragma mark -
@@ -311,7 +347,10 @@ void ButtonWidget::handleMouseDown(int x, int y, int button, int clickCount) {
}
void ButtonWidget::drawWidget() {
- g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, getFlags());
+ g_gui.theme()->drawButtonClip(
+ Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(),
+ _label, _state, getFlags()
+ );
}
void ButtonWidget::setLabel(const Common::String &label) {
@@ -410,7 +449,7 @@ void PicButtonWidget::setGfx(int w, int h, int r, int g, int b) {
}
void PicButtonWidget::drawWidget() {
- g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), "", _state, getFlags());
+ g_gui.theme()->drawButtonClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), "", _state, getFlags());
if (_gfx.getPixels()) {
// Check whether the set up surface needs to be converted to the GUI
@@ -423,7 +462,7 @@ void PicButtonWidget::drawWidget() {
const int x = _x + (_w - _gfx.w) / 2;
const int y = _y + (_h - _gfx.h) / 2;
- g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), _gfx, _state, _alpha, _transparency);
+ g_gui.theme()->drawSurfaceClip(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), getBossClipRect(), _gfx, _state, _alpha, _transparency);
}
}
@@ -458,7 +497,7 @@ void CheckboxWidget::setState(bool state) {
}
void CheckboxWidget::drawWidget() {
- g_gui.theme()->drawCheckbox(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, Widget::_state);
+ g_gui.theme()->drawCheckboxClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _label, _state, Widget::_state);
}
#pragma mark -
@@ -527,21 +566,21 @@ void RadiobuttonWidget::setState(bool state, bool setGroup) {
}
void RadiobuttonWidget::drawWidget() {
- g_gui.theme()->drawRadiobutton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, Widget::_state);
+ g_gui.theme()->drawRadiobuttonClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _label, _state, Widget::_state);
}
#pragma mark -
SliderWidget::SliderWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd)
: Widget(boss, x, y, w, h, tooltip), CommandSender(boss),
- _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false) {
+ _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false), _labelWidth(0) {
setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG);
_type = kSliderWidget;
}
SliderWidget::SliderWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd)
: Widget(boss, name, tooltip), CommandSender(boss),
- _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false) {
+ _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false), _labelWidth(0) {
setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG);
_type = kSliderWidget;
}
@@ -595,7 +634,7 @@ void SliderWidget::handleMouseWheel(int x, int y, int direction) {
}
void SliderWidget::drawWidget() {
- g_gui.theme()->drawSlider(Common::Rect(_x, _y, _x + _w, _y + _h), valueToBarWidth(_value), _state);
+ g_gui.theme()->drawSliderClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), valueToBarWidth(_value), _state);
}
int SliderWidget::valueToBarWidth(int value) {
@@ -672,7 +711,7 @@ void GraphicsWidget::drawWidget() {
const int x = _x + (_w - _gfx.w) / 2;
const int y = _y + (_h - _gfx.h) / 2;
- g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), _gfx, _state, _alpha, _transparency);
+ g_gui.theme()->drawSurfaceClip(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), getBossClipRect(), _gfx, _state, _alpha, _transparency);
}
}
@@ -709,7 +748,7 @@ void ContainerWidget::removeWidget(Widget *widget) {
}
void ContainerWidget::drawWidget() {
- g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, ThemeEngine::kWidgetBackgroundBorder);
+ g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
}
} // End of namespace GUI
diff --git a/gui/widget.h b/gui/widget.h
index 7f6f0c0533..0f4b300233 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -68,7 +68,8 @@ enum {
kPopUpWidget = 'POPU',
kTabWidget = 'TABW',
kGraphicsWidget = 'GFXW',
- kContainerWidget = 'CTNR'
+ kContainerWidget = 'CTNR',
+ kScrollContainerWidget = 'SCTR'
};
enum {
@@ -111,6 +112,7 @@ public:
virtual int16 getAbsX() const { return _x + _boss->getChildX(); }
virtual int16 getAbsY() const { return _y + _boss->getChildY(); }
+ virtual Common::Rect getBossClipRect() const;
virtual void setPos(int x, int y) { _x = x; _y = y; }
virtual void setSize(int w, int h) { _w = w; _h = h; }
diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp
index 2d929113b1..4f7e584c14 100644
--- a/gui/widgets/editable.cpp
+++ b/gui/widgets/editable.cpp
@@ -274,7 +274,7 @@ void EditableWidget::drawCaret(bool erase) {
x += getAbsX();
y += getAbsY();
- g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + editRect.height()), erase);
+ g_gui.theme()->drawCaretClip(Common::Rect(x, y, x + 1, y + editRect.height()), getBossClipRect(), erase);
if (erase) {
GUI::EditableWidget::String character;
@@ -303,7 +303,7 @@ void EditableWidget::drawCaret(bool erase) {
// possible glitches due to different methods used.
width = MIN(editRect.width() - caretOffset, width);
if (width > 0) {
- g_gui.theme()->drawText(Common::Rect(x, y, x + width, y + editRect.height()), character, _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
+ g_gui.theme()->drawTextClip(Common::Rect(x, y, x + width, y + editRect.height()), getBossClipRect(), character, _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
}
}
diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp
index 1481bebae3..0a8725ac9e 100644
--- a/gui/widgets/edittext.cpp
+++ b/gui/widgets/edittext.cpp
@@ -36,6 +36,8 @@ EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, cons
setEditString(text);
setFontStyle(ThemeEngine::kFontStyleNormal);
+
+ _leftPadding = _rightPadding = 0;
}
EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String &text, const char *tooltip, uint32 cmd, uint32 finishCmd)
@@ -46,6 +48,8 @@ EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String
setEditString(text);
setFontStyle(ThemeEngine::kFontStyleNormal);
+
+ _leftPadding = _rightPadding = 0;
}
void EditTextWidget::setEditString(const String &str) {
@@ -93,7 +97,7 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
}
void EditTextWidget::drawWidget() {
- g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, ThemeEngine::kWidgetBackgroundEditText);
+ g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundEditText);
// Draw the text
adjustOffset();
@@ -101,7 +105,7 @@ void EditTextWidget::drawWidget() {
const Common::Rect &r = Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 8, _y + _h);
setTextDrawableArea(r);
- g_gui.theme()->drawText(Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 2, _y + _h), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
+ g_gui.theme()->drawTextClip(Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 2, _y + _h), getBossClipRect(), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
}
Common::Rect EditTextWidget::getEditRect() const {
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index 4b69202fdc..f6e5c67510 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -488,7 +488,7 @@ void ListWidget::drawWidget() {
Common::String buffer;
// Draw a thin frame around the list.
- g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, ThemeEngine::kWidgetBackgroundBorder);
+ g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
const int scrollbarW = (_scrollBar && _scrollBar->isVisible()) ? _scrollBarWidth : 0;
// Draw the list items
@@ -507,7 +507,7 @@ void ListWidget::drawWidget() {
// If in numbering mode, we first print a number prefix
if (_numberingMode != kListNumberingOff) {
buffer = Common::String::format("%2d. ", (pos + _numberingMode));
- g_gui.theme()->drawText(Common::Rect(_x, y, _x + r.left + _leftPadding, y + fontHeight - 2),
+ g_gui.theme()->drawTextClip(Common::Rect(_x, y, _x + r.left + _leftPadding, y + fontHeight - 2), getBossClipRect(),
buffer, _state, Graphics::kTextAlignLeft, inverted, _leftPadding, true);
pad = 0;
}
@@ -528,12 +528,12 @@ void ListWidget::drawWidget() {
color = _editColor;
adjustOffset();
width = _w - r.left - _hlRightPadding - _leftPadding - scrollbarW;
- g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), buffer, _state,
+ g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), getBossClipRect(), buffer, _state,
Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
} else {
buffer = _list[pos];
width = _w - r.left - scrollbarW;
- g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), buffer, _state,
+ g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), getBossClipRect(), buffer, _state,
Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
}
diff --git a/gui/widgets/popup.cpp b/gui/widgets/popup.cpp
index b10b4fb5fe..82f4112a97 100644
--- a/gui/widgets/popup.cpp
+++ b/gui/widgets/popup.cpp
@@ -71,6 +71,10 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
: Dialog(0, 0, 16, 16),
_popUpBoss(boss) {
+ _openTime = 0;
+ _buffer = nullptr;
+ _entriesPerColumn = 1;
+
// Copy the selection index
_selection = _popUpBoss->_selectedItem;
@@ -142,8 +146,6 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
// Remember original mouse position
_clickX = clickX - _x;
_clickY = clickY - _y;
-
- _openTime = 0;
}
void PopUpDialog::drawDialog() {
@@ -362,8 +364,11 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
// Draw a separator
g_gui.theme()->drawLineSeparator(Common::Rect(x, y, x+w, y+kLineHeight));
} else {
- g_gui.theme()->drawText(Common::Rect(x+1, y+2, x+w, y+2+kLineHeight), name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
- Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, _leftPadding);
+ g_gui.theme()->drawText(
+ Common::Rect(x+1, y+2, x+w, y+2+kLineHeight),
+ name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
+ Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, _leftPadding
+ );
}
}
@@ -380,6 +385,7 @@ PopUpWidget::PopUpWidget(GuiObject *boss, const String &name, const char *toolti
_type = kPopUpWidget;
_selectedItem = -1;
+ _leftPadding = _rightPadding = 0;
}
PopUpWidget::PopUpWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip)
@@ -388,6 +394,8 @@ PopUpWidget::PopUpWidget(GuiObject *boss, int x, int y, int w, int h, const char
_type = kPopUpWidget;
_selectedItem = -1;
+
+ _leftPadding = _rightPadding = 0;
}
void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) {
@@ -465,7 +473,10 @@ void PopUpWidget::drawWidget() {
Common::String sel;
if (_selectedItem >= 0)
sel = _entries[_selectedItem].name;
- g_gui.theme()->drawPopUpWidget(Common::Rect(_x, _y, _x + _w, _y + _h), sel, _leftPadding, _state, Graphics::kTextAlignLeft);
+ g_gui.theme()->drawPopUpWidgetClip(
+ Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(),
+ sel, _leftPadding, _state, Graphics::kTextAlignLeft
+ );
}
} // End of namespace GUI
diff --git a/gui/widgets/scrollbar.cpp b/gui/widgets/scrollbar.cpp
index f1306b9c4a..d8bcb18336 100644
--- a/gui/widgets/scrollbar.cpp
+++ b/gui/widgets/scrollbar.cpp
@@ -26,6 +26,7 @@
#include "gui/widgets/scrollbar.h"
#include "gui/gui-manager.h"
#include "gui/ThemeEngine.h"
+#include "gui/widgets/scrollcontainer.h"
namespace GUI {
@@ -202,7 +203,11 @@ void ScrollBarWidget::drawWidget() {
state = ThemeEngine::kScrollbarStateSlider;
}
- g_gui.theme()->drawScrollbar(Common::Rect(_x, _y, _x+_w, _y+_h), _sliderPos, _sliderHeight, state, _state);
+ Common::Rect clipRect = getBossClipRect();
+ //scrollbar is not a usual child of ScrollContainerWidget, so it gets this special treatment
+ if (dynamic_cast<ScrollContainerWidget *>(_boss))
+ clipRect.right += _w;
+ g_gui.theme()->drawScrollbarClip(Common::Rect(_x, _y, _x+_w, _y+_h), clipRect, _sliderPos, _sliderHeight, state, _state);
}
} // End of namespace GUI
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
new file mode 100644
index 0000000000..1b38478c11
--- /dev/null
+++ b/gui/widgets/scrollcontainer.cpp
@@ -0,0 +1,147 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/util.h"
+#include "gui/widgets/scrollcontainer.h"
+#include "gui/gui-manager.h"
+
+#include "gui/ThemeEval.h"
+
+namespace GUI {
+
+ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, int x, int y, int w, int h)
+ : Widget(boss, x, y, w, h) {
+ init();
+}
+
+ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, const Common::String &name)
+ : Widget(boss, name) {
+ init();
+}
+
+void ScrollContainerWidget::init() {
+ setFlags(WIDGET_ENABLED);
+ _type = kScrollContainerWidget;
+ _verticalScroll = new ScrollBarWidget(this, _w-16, 0, 16, _h);
+ _verticalScroll->setTarget(this);
+ _scrolledX = 0;
+ _scrolledY = 0;
+ _limitH = 140;
+ recalc();
+}
+
+void ScrollContainerWidget::recalc() {
+ int scrollbarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
+ _limitH = _h;
+
+ //calculate virtual height
+ const int spacing = g_gui.xmlEval()->getVar("Global.Font.Height", 16); //on the bottom
+ int h = 0;
+ int min = spacing, max = 0;
+ Widget *ptr = _firstWidget;
+ while (ptr) {
+ if (ptr != _verticalScroll) {
+ int y = ptr->getAbsY() - getChildY();
+ min = MIN(min, y - spacing);
+ max = MAX(max, y + ptr->getHeight() + spacing);
+ }
+ ptr = ptr->next();
+ }
+ h = max - min;
+
+ _verticalScroll->_numEntries = h;
+ _verticalScroll->_currentPos = _scrolledY;
+ _verticalScroll->_entriesPerPage = _limitH;
+ _verticalScroll->setPos(_w - scrollbarWidth, _scrolledY+1);
+ _verticalScroll->setSize(scrollbarWidth, _limitH -2);
+}
+
+
+ScrollContainerWidget::~ScrollContainerWidget() {}
+
+int16 ScrollContainerWidget::getChildX() const {
+ return getAbsX() - _scrolledX;
+}
+
+int16 ScrollContainerWidget::getChildY() const {
+ return getAbsY() - _scrolledY;
+}
+
+uint16 ScrollContainerWidget::getWidth() const {
+ return _w - (_verticalScroll->isVisible() ? _verticalScroll->getWidth() : 0);
+}
+
+uint16 ScrollContainerWidget::getHeight() const {
+ return _limitH;
+}
+
+void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ Widget::handleCommand(sender, cmd, data);
+ switch (cmd) {
+ case kSetPositionCmd:
+ _scrolledY = _verticalScroll->_currentPos;
+ reflowLayout();
+ draw();
+ g_gui.doFullRedraw();
+ break;
+ }
+}
+
+void ScrollContainerWidget::reflowLayout() {
+ Widget::reflowLayout();
+
+ //reflow layout of inner widgets
+ Widget *ptr = _firstWidget;
+ while (ptr) {
+ ptr->reflowLayout();
+ ptr = ptr->next();
+ }
+
+ //recalculate height
+ recalc();
+
+ //hide those widgets which are out of visible area
+ ptr = _firstWidget;
+ while (ptr) {
+ int y = ptr->getAbsY() - getChildY();
+ int h = ptr->getHeight();
+ bool visible = true;
+ if (y + h - _scrolledY < 0) visible = false;
+ if (y - _scrolledY > _limitH) visible = false;
+ ptr->setVisible(visible);
+ ptr = ptr->next();
+ }
+
+ _verticalScroll->setVisible(_verticalScroll->_numEntries > _limitH); //show when there is something to scroll
+}
+
+void ScrollContainerWidget::drawWidget() {
+ g_gui.theme()->drawDialogBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + getHeight() - 1), getBossClipRect(), ThemeEngine::kDialogBackgroundDefault);
+}
+
+Widget *ScrollContainerWidget::findWidget(int x, int y) {
+ if (_verticalScroll->isVisible() && x >= _w - _verticalScroll->getWidth())
+ return _verticalScroll;
+ return Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
+}
+
+} // End of namespace GUI
diff --git a/gui/widgets/scrollcontainer.h b/gui/widgets/scrollcontainer.h
new file mode 100644
index 0000000000..692c7e3507
--- /dev/null
+++ b/gui/widgets/scrollcontainer.h
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GUI_WIDGETS_SCROLLCONTAINER_H
+#define GUI_WIDGETS_SCROLLCONTAINER_H
+
+#include "gui/widget.h"
+#include "common/str.h"
+#include "scrollbar.h"
+
+namespace GUI {
+
+class ScrollContainerWidget: public Widget {
+ ScrollBarWidget *_verticalScroll;
+ int16 _scrolledX, _scrolledY;
+ uint16 _limitH;
+
+ void recalc();
+
+public:
+ ScrollContainerWidget(GuiObject *boss, int x, int y, int w, int h);
+ ScrollContainerWidget(GuiObject *boss, const Common::String &name);
+ ~ScrollContainerWidget();
+
+ void init();
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+ virtual void reflowLayout();
+
+protected:
+ // We overload getChildY to make sure child widgets are positioned correctly.
+ // Essentially this compensates for the space taken up by the tab title header.
+ virtual int16 getChildX() const;
+ virtual int16 getChildY() const;
+ virtual uint16 getWidth() const;
+ virtual uint16 getHeight() const;
+
+ virtual void drawWidget();
+
+ virtual Widget *findWidget(int x, int y);
+};
+
+} // End of namespace GUI
+
+#endif
diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp
index 756781a04b..15e6a9d370 100644
--- a/gui/widgets/tab.cpp
+++ b/gui/widgets/tab.cpp
@@ -80,9 +80,19 @@ TabWidget::~TabWidget() {
}
int16 TabWidget::getChildY() const {
+ // NOTE: if you change that, make sure to do the same
+ // changes in the ThemeLayoutTabWidget (gui/ThemeLayout.cpp)
return getAbsY() + _tabHeight;
}
+uint16 TabWidget::getHeight() const {
+ // NOTE: if you change that, make sure to do the same
+ // changes in the ThemeLayoutTabWidget (gui/ThemeLayout.cpp)
+ // NOTE: this height is used for clipping, so it *includes*
+ // tabs, because it starts from getAbsY(), not getChildY()
+ return _h + _tabHeight;
+}
+
int TabWidget::addTab(const String &title) {
// Add a new tab page
Tab newTab;
@@ -258,6 +268,12 @@ void TabWidget::adjustTabs(int value) {
void TabWidget::reflowLayout() {
Widget::reflowLayout();
+ // NOTE: if you change that, make sure to do the same
+ // changes in the ThemeLayoutTabWidget (gui/ThemeLayout.cpp)
+ _tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height");
+ _tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width");
+ _titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top");
+
for (uint i = 0; i < _tabs.size(); ++i) {
Widget *w = _tabs[i].firstWidget;
while (w) {
@@ -266,10 +282,6 @@ void TabWidget::reflowLayout() {
}
}
- _tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height");
- _tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width");
- _titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top");
-
if (_tabWidth == 0) {
_tabWidth = 40;
#ifdef __DS__
@@ -304,9 +316,9 @@ void TabWidget::drawWidget() {
for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) {
tabs.push_back(_tabs[i].title);
}
- g_gui.theme()->drawDialogBackground(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP), _bodyBackgroundType);
+ g_gui.theme()->drawDialogBackgroundClip(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP+_tabHeight), getBossClipRect(), _bodyBackgroundType);
- g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
+ g_gui.theme()->drawTabClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
}
void TabWidget::draw() {
diff --git a/gui/widgets/tab.h b/gui/widgets/tab.h
index 148f164fbb..17b85986b5 100644
--- a/gui/widgets/tab.h
+++ b/gui/widgets/tab.h
@@ -110,6 +110,7 @@ protected:
// We overload getChildY to make sure child widgets are positioned correctly.
// Essentially this compensates for the space taken up by the tab title header.
virtual int16 getChildY() const;
+ virtual uint16 getHeight() const;
virtual void drawWidget();