diff options
Diffstat (limited to 'gui')
54 files changed, 2155 insertions, 538 deletions
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp index d0371f5e78..3f91cfa259 100644 --- a/gui/EventRecorder.cpp +++ b/gui/EventRecorder.cpp @@ -330,7 +330,7 @@ bool EventRecorder::openRecordFile(const Common::String &fileName) { } bool EventRecorder::checkGameHash(const ADGameDescription *gameDesc) { - if (_playbackFile->getHeader().hashRecords.size() != 0) { + if (_playbackFile->getHeader().hashRecords.size() == 0) { warning("Engine doesn't contain description table"); return false; } @@ -676,4 +676,3 @@ void EventRecorder::deleteTemporarySave() { } // End of namespace GUI #endif // ENABLE_EVENTRECORDER - diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index ed01204180..c850a6a02e 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -44,21 +44,21 @@ namespace GUI { -const char * const ThemeEngine::kImageLogo = "logo.bmp"; -const char * const ThemeEngine::kImageLogoSmall = "logo_small.bmp"; -const char * const ThemeEngine::kImageSearch = "search.bmp"; -const char * const ThemeEngine::kImageEraser = "eraser.bmp"; -const char * const ThemeEngine::kImageDelbtn = "delbtn.bmp"; -const char * const ThemeEngine::kImageList = "list.bmp"; -const char * const ThemeEngine::kImageGrid = "grid.bmp"; -const char * const ThemeEngine::kImageStopbtn = "stopbtn.bmp"; -const char * const ThemeEngine::kImageEditbtn = "editbtn.bmp"; -const char * const ThemeEngine::kImageSwitchModebtn = "switchbtn.bmp"; -const char * const ThemeEngine::kImageFastReplaybtn = "fastreplay.bmp"; -const char * const ThemeEngine::kImageStopSmallbtn = "stopbtn_small.bmp"; -const char * const ThemeEngine::kImageEditSmallbtn = "editbtn_small.bmp"; -const char * const ThemeEngine::kImageSwitchModeSmallbtn = "switchbtn_small.bmp"; -const char * const ThemeEngine::kImageFastReplaySmallbtn = "fastreplay_small.bmp"; +const char *const ThemeEngine::kImageLogo = "logo.bmp"; +const char *const ThemeEngine::kImageLogoSmall = "logo_small.bmp"; +const char *const ThemeEngine::kImageSearch = "search.bmp"; +const char *const ThemeEngine::kImageEraser = "eraser.bmp"; +const char *const ThemeEngine::kImageDelButton = "delbtn.bmp"; +const char *const ThemeEngine::kImageList = "list.bmp"; +const char *const ThemeEngine::kImageGrid = "grid.bmp"; +const char *const ThemeEngine::kImageStopButton = "stopbtn.bmp"; +const char *const ThemeEngine::kImageEditButton = "editbtn.bmp"; +const char *const ThemeEngine::kImageSwitchModeButton = "switchbtn.bmp"; +const char *const ThemeEngine::kImageFastReplayButton = "fastreplay.bmp"; +const char *const ThemeEngine::kImageStopSmallButton = "stopbtn_small.bmp"; +const char *const ThemeEngine::kImageEditSmallButton = "editbtn_small.bmp"; +const char *const ThemeEngine::kImageSwitchModeSmallButton = "switchbtn_small.bmp"; +const char *const ThemeEngine::kImageFastReplaySmallButton = "fastreplay_small.bmp"; struct TextDrawData { const Graphics::Font *_fontPtr; @@ -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 @@ -164,7 +188,7 @@ struct DrawDataInfo { DrawData id; ///< The actual ID of the DrawData item. const char *name; ///< The name of the DrawData item as it appears in the Theme Description files bool buffer; ///< Sets whether this item is buffered on the backbuffer or drawn directly to the screen. - DrawData parent; ///< Parent DrawData item, for items that overlay. E.g. kButtonIdle -> kButtonHover + DrawData parent; ///< Parent DrawData item, for items that overlay. E.g. kDDButtonIdle -> kDDButtonHover }; /** @@ -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); } @@ -739,12 +807,23 @@ bool ThemeEngine::loadDefaultXML() { // Use the Python script "makedeftheme.py" to convert a normal XML theme // into the "default.inc" file, which is ready to be included in the code. #ifndef DISABLE_GUI_BUILTIN_THEME - const char *defaultXML = #include "themes/default.inc" - ; + int xmllen = 0; + + for (int i = 0; i < ARRAYSIZE(defaultXML); i++) + xmllen += strlen(defaultXML[i]); + + byte *tmpXML = (byte *)malloc(xmllen + 1); + tmpXML[0] = '\0'; + + for (int i = 0; i < ARRAYSIZE(defaultXML); i++) + strncat((char *)tmpXML, defaultXML[i], xmllen); + + if (!_parser->loadBuffer(tmpXML, xmllen)) { + free(tmpXML); - if (!_parser->loadBuffer((const byte *)defaultXML, strlen(defaultXML))) return false; + } _themeName = "ScummVM Classic Theme (Builtin Version)"; _themeId = "builtin"; @@ -753,6 +832,8 @@ bool ThemeEngine::loadDefaultXML() { bool result = _parser->parse(); _parser->close(); + free(tmpXML); + return result; #else warning("The built-in theme is not enabled in the current build. Please load an external theme"); @@ -843,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; @@ -862,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; @@ -877,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 @@ -901,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; @@ -908,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; @@ -934,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; @@ -960,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; @@ -980,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; @@ -1001,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; @@ -1033,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; @@ -1044,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; @@ -1065,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; @@ -1072,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; @@ -1095,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; @@ -1123,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; @@ -1196,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; @@ -1210,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); @@ -1246,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) { @@ -1446,7 +1919,7 @@ const Graphics::Font *ThemeEngine::loadScalableFont(const Common::String &filena for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) { Common::SeekableReadStream *stream = (*i)->createReadStream(); if (stream) { - font = Graphics::loadTTFFont(*stream, pointsize, 0, Graphics::kTTFRenderModeLight, + font = Graphics::loadTTFFont(*stream, pointsize, Graphics::kTTFSizeModeCharacter, 0, Graphics::kTTFRenderModeLight, #ifdef USE_TRANSLATION TransMan.getCharsetMapping() #else diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 68be2e0b26..3c259b4f9d 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -36,7 +36,7 @@ #include "graphics/pixelformat.h" -#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.20" +#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.21" class OSystem; @@ -228,17 +228,17 @@ public: static const char *const kImageLogoSmall; ///< ScummVM logo used in the GMM static const char *const kImageSearch; ///< Search tool image used in the launcher static const char *const kImageEraser; ///< Clear input image used in the launcher - static const char *const kImageDelbtn; ///< Delete characters in the predictive dialog + static const char *const kImageDelButton; ///< Delete characters in the predictive dialog static const char *const kImageList; ///< List image used in save/load chooser selection static const char *const kImageGrid; ///< Grid image used in save/load chooser selection - static const char *const kImageStopbtn; ///< Stop recording button in recorder onscreen dialog - static const char *const kImageEditbtn; ///< Edit recording metadata in recorder onscreen dialog - static const char *const kImageSwitchModebtn; ///< Switch mode button in recorder onscreen dialog - static const char *const kImageFastReplaybtn; ///< Fast playback mode button in recorder onscreen dialog - static const char *const kImageStopSmallbtn; ///< Stop recording button in recorder onscreen dialog (for 320xY) - static const char *const kImageEditSmallbtn; ///< Edit recording metadata in recorder onscreen dialog (for 320xY) - static const char *const kImageSwitchModeSmallbtn; ///< Switch mode button in recorder onscreen dialog (for 320xY) - static const char *const kImageFastReplaySmallbtn; ///< Fast playback mode button in recorder onscreen dialog (for 320xY) + static const char *const kImageStopButton; ///< Stop recording button in recorder onscreen dialog + static const char *const kImageEditButton; ///< Edit recording metadata in recorder onscreen dialog + static const char *const kImageSwitchModeButton; ///< Switch mode button in recorder onscreen dialog + static const char *const kImageFastReplayButton; ///< Fast playback mode button in recorder onscreen dialog + static const char *const kImageStopSmallButton; ///< Stop recording button in recorder onscreen dialog (for 320xY) + static const char *const kImageEditSmallButton; ///< Edit recording metadata in recorder onscreen dialog (for 320xY) + static const char *const kImageSwitchModeSmallButton; ///< Switch mode button in recorder onscreen dialog (for 320xY) + static const char *const kImageFastReplaySmallButton; ///< Fast playback mode button in recorder onscreen dialog (for 320xY) /** * Graphics mode enumeration. @@ -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/Tooltip.h b/gui/Tooltip.h index 58b6d8a429..60688412e6 100644 --- a/gui/Tooltip.h +++ b/gui/Tooltip.h @@ -41,6 +41,8 @@ public: void setup(Dialog *parent, Widget *widget, int x, int y); void drawDialog(); + + virtual void receivedFocus(int x = -1, int y = -1) {} protected: virtual void handleMouseDown(int x, int y, int button, int clickCount) { close(); @@ -64,7 +66,6 @@ protected: } virtual void handleMouseMoved(int x, int y, int button) { close(); - _parent->handleMouseMoved(x + (getAbsX() - _parent->getAbsX()), y + (getAbsY() - _parent->getAbsY()), button); } int _maxWidth; diff --git a/gui/about.cpp b/gui/about.cpp index daec2b7e48..211542adb3 100644 --- a/gui/about.cpp +++ b/gui/about.cpp @@ -57,7 +57,7 @@ enum { static const char *copyright_text[] = { "", -"C0""Copyright (C) 2001-2015 The ScummVM Team", +"C0""Copyright (C) 2001-2016 The ScummVM Team", "C0""http://www.scummvm.org", "", "C0""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 binary.", diff --git a/gui/credits.h b/gui/credits.h index 7ae12bf599..c2c4c84ec6 100644 --- a/gui/credits.h +++ b/gui/credits.h @@ -58,10 +58,11 @@ static const char *credits[] = { "C1""AGI", "C0""Stuart George", "C0""Matthew Hoops", +"C2""(retired)", "C0""Filippos Karapetis", +"C0""Martin Kiewitz", "C0""Pawel Kolodziejski", "C0""Walter van Niftrik", -"C2""(retired)", "C0""Kari Salminen", "C0""Eugene Sandulenko", "C0""David Symonds", @@ -77,12 +78,20 @@ static const char *credits[] = { "C0""Ludvig Strigeus", "C2""(retired)", "", +"C1""Access", +"A0""Arnaud Boutonne", +"C0""Arnaud Boutonn\351", +"C0""Paul Gilbert", +"", "C1""Avalanche", "A0""Peter Bozso", "C0""Peter Bozs\363", "A0""Arnaud Boutonne", "C0""Arnaud Boutonn\351", "", +"C1""BBVS", +"C0""Benjamin Haisch", +"", "C1""CGE", "A0""Arnaud Boutonne", "C0""Arnaud Boutonn\351", @@ -119,6 +128,7 @@ static const char *credits[] = { "C1""Drascula", "C0""Filippos Karapetis", "C0""Pawel Kolodziejski", +"C0""Thierry Crozat", "", "C1""DreamWeb", "A0""Torbjorn Andersson", @@ -129,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", @@ -165,6 +180,7 @@ static const char *credits[] = { "", "C1""Lastexpress", "C0""Matthew Hoops", +"C2""(retired)", "C0""Jordi Vilalta Prat", "C0""Julien Templier", "", @@ -184,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", @@ -203,6 +220,7 @@ static const char *credits[] = { "", "C1""Pegasus", "C0""Matthew Hoops", +"C2""(retired)", "", "C1""Queen", "C0""David Eriksson", @@ -228,11 +246,14 @@ static const char *credits[] = { "C0""Filippos Karapetis", "C0""Martin Kiewitz", "C0""Walter van Niftrik", -"C2""(retired)", "C0""Willem Jan Palenstijn", "C0""Jordi Vilalta Prat", "C0""Lars Skovlund", "", +"C1""Sherlock", +"C0""Paul Gilbert", +"C0""Martin Kiewitz", +"", "C1""Sky", "A0""Robert Goeffringmann", "C0""Robert G\366ffringmann", @@ -332,15 +353,21 @@ static const char *credits[] = { "C1""Android", "C0""Andre Heider", "C0""Angus Lees", +"C0""Lubomyr Lisen", "", "C1""Dreamcast", "C0""Marcus Comstedt", "", +"C1""GCW0", +"C0""Eugene Sandulenko", +"", "C1""GPH Devices (GP2X, GP2XWiz & Caanoo)", "C0""John Willis", "", -"C1""iPhone", +"C1""iPhone / iPad", "C0""Oystein Eftevaag", +"A0""Vincent Benony", +"C0""Vincent B\351nony", "", "C1""LinuxMoto", "C0""Lubomyr Lisen", @@ -350,6 +377,9 @@ static const char *credits[] = { "C2""(retired)", "C0""Tarek Soliman", "", +"C1""Nintendo 3DS", +"C0""Thomas Edvalson", +"", "C1""Nintendo 64", "C0""Fabio Battaglia", "", @@ -398,6 +428,9 @@ static const char *credits[] = { "C1""Wii", "C0""Andre Heider", "", +"C1""Raspberry Pi", +"C0""Manuel Alfayate", +"", "", "C1""Other subsystems", "C1""Infrastructure", @@ -458,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", @@ -516,6 +549,7 @@ static const char *credits[] = { "C0""Max Horn", "C2""(retired)", "C0""Oystein Eftevaag", +"C0""Thierry Crozat", "", "C1""Mandriva", "C0""Dominik Scherer", @@ -872,5 +906,9 @@ static const char *credits[] = { "C0""", "C0""Bob Bell, Michel Kripalani, Tommy Yune, from Presto Studios for providing the source code of The Journeyman Project: Pegasus Prime.", "C0""", +"C0""Electronic Arts IP Preservation Team, particularly Stefan Serbicki, and Vasyl Tsvirkunov of Electronic Arts for providing the source code of the two Lost Files of Sherlock Holmes games. James M. Ferguson and Barry Duncan for their tenacious efforts to recover the sources.", +"C0""", +"C0""The mindFactory team for writing Broken Sword 2.5, a splendid fan-made sequel, and for sharing the source code with us.", +"C0""", "", }; diff --git a/gui/debugger.cpp b/gui/debugger.cpp index c9b435963d..72d05e2973 100644 --- a/gui/debugger.cpp +++ b/gui/debugger.cpp @@ -42,6 +42,7 @@ #elif defined(USE_READLINE) #include <readline/readline.h> #include <readline/history.h> + #include "common/events.h" #endif @@ -191,6 +192,15 @@ char *readline_completionFunction(const char *text, int state) { return g_readline_debugger->readlineComplete(text, state); } +void readline_eventFunction() { + Common::EventManager *eventMan = g_system->getEventManager(); + + Common::Event event; + while (eventMan->pollEvent(event)) { + // drop all events + } +} + #ifdef USE_READLINE_INT_COMPLETION typedef int RLCompFunc_t(const char *, int); #else @@ -228,6 +238,7 @@ void Debugger::enter() { g_readline_debugger = this; rl_completion_entry_function = (RLCompFunc_t *)&readline_completionFunction; + rl_event_hook = (rl_hook_func_t *)&readline_eventFunction; char *line_read = 0; do { diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 315c24e9bf..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,16 +113,18 @@ 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() { + _dragWidget = NULL; + if (_tickleWidget) { _tickleWidget->lostFocus(); } diff --git a/gui/dialog.h b/gui/dialog.h index 593ee13458..0e06effabd 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -82,7 +82,7 @@ public: virtual void reflowLayout(); virtual void lostFocus(); - virtual void receivedFocus() {} + virtual void receivedFocus(int x = -1, int y = -1) { if (x >= 0 && y >= 0) handleMouseMoved(x, y, 0); } protected: virtual void open(); diff --git a/gui/filebrowser-dialog.cpp b/gui/filebrowser-dialog.cpp new file mode 100644 index 0000000000..93395ba909 --- /dev/null +++ b/gui/filebrowser-dialog.cpp @@ -0,0 +1,160 @@ +/* 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 "gui/filebrowser-dialog.h" + +#include "common/system.h" +#include "common/algorithm.h" +#include "common/savefile.h" +#include "common/str-array.h" + +#include "common/translation.h" + +#include "gui/widgets/list.h" +#include "gui/message.h" + +namespace GUI { + +enum { + kChooseCmd = 'Chos' +}; + +FileBrowserDialog::FileBrowserDialog(const char *title, const char *fileExtension, int mode) + : Dialog("FileBrowser"), _mode(mode), _fileExt(fileExtension) { + + _fileMask = "*."; + _fileMask += fileExtension; + _fileList = NULL; + + new StaticTextWidget(this, "FileBrowser.Headline", title ? title : + mode == kFBModeLoad ? _("Choose file for loading") : _("Enter filename for saving")); + + _fileName = new EditTextWidget(this, "FileBrowser.Filename", ""); + + if (mode == kFBModeLoad) + _fileName->setEnabled(false); + + // Add file list + _fileList = new ListWidget(this, "FileBrowser.List"); + _fileList->setNumberingMode(kListNumberingOff); + _fileList->setEditable(false); + + _backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain; + + // Buttons + new ButtonWidget(this, "FileBrowser.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "FileBrowser.Choose", _("Choose"), 0, kChooseCmd); +} + +void FileBrowserDialog::open() { + // Call super implementation + Dialog::open(); + + updateListing(); +} + +void FileBrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { + switch (cmd) { + case kChooseCmd: + if (_fileName->getEditString().empty()) + break; + + normalieFileName(); + + if (!isProceedSave()) + break; + + setResult(1); + close(); + break; + case kListSelectionChangedCmd: + _fileName->setEditString(_fileList->getList().operator[](_fileList->getSelected()).c_str()); + _fileName->draw(); + break; + case kListItemActivatedCmd: + case kListItemDoubleClickedCmd: + normalieFileName(); + + if (!isProceedSave()) + break; + + setResult(1); + close(); + break; + default: + Dialog::handleCommand(sender, cmd, data); + } +} + +void FileBrowserDialog::normalieFileName() { + Common::String filename = _fileName->getEditString(); + + if (filename.matchString(_fileMask)) + return; + + _fileName->setEditString(filename + "." + _fileExt); +} + + +bool FileBrowserDialog::isProceedSave() { + bool matched = false; + + if (_mode == kFBModeLoad) + return true; + + for (ListWidget::StringArray::const_iterator file = _fileList->getList().begin(); file != _fileList->getList().end(); ++file) { + if (*file == _fileName->getEditString()) { + matched = true; + break; + } + } + + if (matched) { + GUI::MessageDialog alert(_("Do you really want to overwrite the file?"), _("Yes"), _("No")); + + if (alert.runModal() != GUI::kMessageOK) + return false; + } + + return true; +} + +void FileBrowserDialog::updateListing() { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + + ListWidget::StringArray list; + + Common::StringArray filenames = saveFileMan->listSavefiles(_fileMask); + Common::sort(filenames.begin(), filenames.end()); + + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + list.push_back(file->c_str()); + } + + _fileList->setList(list); + _fileList->scrollTo(0); + + // Finally, redraw + draw(); +} + +} // End of namespace GUI diff --git a/gui/filebrowser-dialog.h b/gui/filebrowser-dialog.h new file mode 100644 index 0000000000..5916d76c80 --- /dev/null +++ b/gui/filebrowser-dialog.h @@ -0,0 +1,64 @@ +/* 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 FILEBROWSER_DIALOG_H +#define FILEBROWSER_DIALOG_H + +#include "gui/dialog.h" +#include "gui/widgets/edittext.h" + +namespace GUI { + +class ListWidget; +class EditTextWidget; +class CommandSender; + +enum { + kFBModeLoad = 0, + kFBModeSave +}; + +class FileBrowserDialog : public Dialog { +public: + FileBrowserDialog(const char *title, const char *fileExtension, int mode); + + virtual void open(); + + virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); + + const char *getResult() { return Dialog::getResult() ? _fileName->getEditString().c_str() : NULL; } + +protected: + EditTextWidget *_fileName; + ListWidget *_fileList; + Common::String _fileMask; + Common::String _fileExt; + int _mode; + + void updateListing(); + void normalieFileName(); + bool isProceedSave(); +}; + +} // End of namespace GUI + +#endif diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index 9b6cf5a0b6..9acd9434ff 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -64,6 +64,8 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), _stateIsSaved(false), _width = _system->getOverlayWidth(); _height = _system->getOverlayHeight(); + _launched = false; + // Clear the cursor memset(_cursor, 0xFF, sizeof(_cursor)); @@ -279,14 +281,9 @@ void GuiManager::runLoop() { redraw(); } - _lastMousePosition.x = _lastMousePosition.y = -1; - _lastMousePosition.time = 0; - Common::EventManager *eventMan = _system->getEventManager(); uint32 lastRedraw = 0; - const uint32 waitTime = 1000 / 45; - - bool tooltipCheck = false; + const uint32 waitTime = 1000 / 60; while (!_dialogStack.empty() && activeDialog == getTopDialog() && !eventMan->shouldQuit()) { redraw(); @@ -302,9 +299,9 @@ void GuiManager::runLoop() { // _system->updateScreen(); if (lastRedraw + waitTime < _system->getMillis(true)) { + lastRedraw = _system->getMillis(true); _theme->updateScreen(); _system->updateScreen(); - lastRedraw = _system->getMillis(true); } Common::Event event; @@ -334,19 +331,14 @@ void GuiManager::runLoop() { processEvent(event, activeDialog); - if (event.type == Common::EVENT_MOUSEMOVE) { - tooltipCheck = true; - } - - if (lastRedraw + waitTime < _system->getMillis(true)) { + lastRedraw = _system->getMillis(true); _theme->updateScreen(); _system->updateScreen(); - lastRedraw = _system->getMillis(true); } } - if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis(true)) { + if (_lastMousePosition.time + kTooltipDelay < _system->getMillis(true)) { Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y); if (wdg && wdg->hasTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) { Tooltip *tooltip = new Tooltip(); @@ -413,7 +405,7 @@ void GuiManager::restoreState() { } void GuiManager::openDialog(Dialog *dialog) { - dialog->receivedFocus(); + giveFocusToDialog(dialog); if (!_dialogStack.empty()) getTopDialog()->lostFocus(); @@ -437,8 +429,10 @@ void GuiManager::closeTopDialog() { // Remove the dialog from the stack _dialogStack.pop()->lostFocus(); - if (!_dialogStack.empty()) - getTopDialog()->receivedFocus(); + if (!_dialogStack.empty()) { + Dialog *dialog = getTopDialog(); + giveFocusToDialog(dialog); + } if (_redrawStatus != kRedrawFull) _redrawStatus = kRedrawCloseDialog; @@ -513,6 +507,7 @@ void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDi int button; uint32 time; Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y); + switch (event.type) { case Common::EVENT_KEYDOWN: activeDialog->handleKeyDown(event.kbd); @@ -521,12 +516,12 @@ void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDi activeDialog->handleKeyUp(event.kbd); break; case Common::EVENT_MOUSEMOVE: + _globalMousePosition.x = event.mouse.x; + _globalMousePosition.y = event.mouse.y; activeDialog->handleMouseMoved(mouse.x, mouse.y, 0); if (mouse.x != _lastMousePosition.x || mouse.y != _lastMousePosition.y) { - _lastMousePosition.x = mouse.x; - _lastMousePosition.y = mouse.y; - _lastMousePosition.time = _system->getMillis(true); + setLastMousePos(mouse.x, mouse.y); } break; @@ -569,4 +564,23 @@ 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; + dialog->receivedFocus(dialogX, dialogY); + setLastMousePos(dialogX, dialogY); +} + +void GuiManager::setLastMousePos(int16 x, int16 y) { + _lastMousePosition.x = x; + _lastMousePosition.y = y; + _lastMousePosition.time = _system->getMillis(true); +} + } // End of namespace GUI diff --git a/gui/gui-manager.h b/gui/gui-manager.h index 4186a93ccb..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(); } @@ -98,6 +99,8 @@ public: */ bool checkScreenChange(); + bool _launched; + protected: enum RedrawStatus { kRedrawDisabled = 0, @@ -122,11 +125,12 @@ protected: bool _useStdCursor; // position and time of last mouse click (used to detect double clicks) - struct { + struct MousePos { + MousePos() : x(-1), y(-1), count(0) { time = 0; } int16 x, y; // Position of mouse when the click occurred uint32 time; // Time int count; // How often was it already pressed? - } _lastClick, _lastMousePosition; + } _lastClick, _lastMousePosition, _globalMousePosition; // mouse cursor state int _cursorAnimateCounter; @@ -153,6 +157,9 @@ protected: Dialog *getTopDialog() const; void screenChange(); + + void giveFocusToDialog(Dialog *dialog); + void setLastMousePos(int16 x, int16 y); }; } // End of namespace GUI diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 5abf0aba26..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")); @@ -683,6 +685,8 @@ LauncherDialog::LauncherDialog() // Create Load dialog _loadDialog = new SaveLoadChooser(_("Load game:"), _("Load"), false); + + GUI::GuiManager::instance()._launched = true; } void LauncherDialog::selectTarget(const String &target) { diff --git a/gui/module.mk b/gui/module.mk index 338e43c6a4..6cbc63d24d 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -8,6 +8,7 @@ MODULE_OBJS := \ dialog.o \ error.o \ EventRecorder.o \ + filebrowser-dialog.o \ gui-manager.o \ launcher.o \ massadd.o \ @@ -29,8 +30,21 @@ 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 +# structure to pick up the right browser implementations for iOS and Mac OS X. +# Please keep it like this or XCode project generation will be broken. +# FIXME: This only works because of a bug in how we handle ifdef statements in +# create_project's module.mk parser. create_project will think that both +# browser.o and browser_osx.o is built when both IPHONE and MACOSX is set. +# When we do proper ifdef handling, only browser.o will be picked up, breaking +# XCode generation. +ifdef IPHONE +MODULE_OBJS += \ + browser.o +else ifdef MACOSX MODULE_OBJS += \ browser_osx.o @@ -38,6 +52,7 @@ else MODULE_OBJS += \ browser.o endif +endif ifdef ENABLE_EVENTRECORDER MODULE_OBJS += \ @@ -51,5 +66,10 @@ MODULE_OBJS += \ fluidsynth-dialog.o endif +ifdef USE_UPDATES +MODULE_OBJS += \ + updates-dialog.o +endif + # Include common rules include $(srcdir)/rules.mk 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/onscreendialog.cpp b/gui/onscreendialog.cpp index 0e37834136..8b338f56df 100644 --- a/gui/onscreendialog.cpp +++ b/gui/onscreendialog.cpp @@ -62,37 +62,37 @@ OnScreenDialog::OnScreenDialog(bool isRecord) : Dialog("OnScreenDialog") { #ifndef DISABLE_FANCY_THEMES if (g_gui.xmlEval()->getVar("Globals.OnScreenDialog.ShowPics") == 1 && g_gui.theme()->supportsImages()) { - GUI::PicButtonWidget *btn; - btn = new PicButtonWidget(this, "OnScreenDialog.StopButton", 0, kStopCmd, 0); - btn->useThemeTransparency(true); + GUI::PicButtonWidget *button; + button = new PicButtonWidget(this, "OnScreenDialog.StopButton", 0, kStopCmd, 0); + button->useThemeTransparency(true); if (g_system->getOverlayWidth() > 320) - btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageStopbtn)); + button->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageStopButton)); else - btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageStopSmallbtn)); + button->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageStopSmallButton)); if (isRecord) { - btn = new PicButtonWidget(this, "OnScreenDialog.EditButton", 0, kEditCmd, 0); - btn->useThemeTransparency(true); + button = new PicButtonWidget(this, "OnScreenDialog.EditButton", 0, kEditCmd, 0); + button->useThemeTransparency(true); if (g_system->getOverlayWidth() > 320) - btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageEditbtn)); + button->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageEditButton)); else - btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageEditSmallbtn)); + button->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageEditSmallButton)); } else { - btn = new PicButtonWidget(this, "OnScreenDialog.SwitchModeButton", 0, kSwitchModeCmd, 0); - btn->useThemeTransparency(true); + button = new PicButtonWidget(this, "OnScreenDialog.SwitchModeButton", 0, kSwitchModeCmd, 0); + button->useThemeTransparency(true); if (g_system->getOverlayWidth() > 320) - btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSwitchModebtn)); + button->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSwitchModeButton)); else - btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSwitchModeSmallbtn)); + button->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSwitchModeSmallButton)); - btn = new PicButtonWidget(this, "OnScreenDialog.FastReplayButton", 0, kFastModeCmd, 0); - btn->useThemeTransparency(true); + button = new PicButtonWidget(this, "OnScreenDialog.FastReplayButton", 0, kFastModeCmd, 0); + button->useThemeTransparency(true); if (g_system->getOverlayWidth() > 320) - btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageFastReplaybtn)); + button->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageFastReplayButton)); else - btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageFastReplaySmallbtn)); + button->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageFastReplaySmallButton)); } } else #endif diff --git a/gui/options.cpp b/gui/options.cpp index ba247e5f15..e410971818 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -36,6 +36,7 @@ #include "common/system.h" #include "common/textconsole.h" #include "common/translation.h" +#include "common/updates.h" #include "audio/mididrv.h" #include "audio/musicplugin.h" @@ -61,7 +62,8 @@ enum { kChooseExtraDirCmd = 'chex', kExtraPathClearCmd = 'clex', kChoosePluginsDirCmd = 'chpl', - kChooseThemeCmd = 'chtf' + kChooseThemeCmd = 'chtf', + kUpdatesCheckCmd = 'updc' }; enum { @@ -70,7 +72,7 @@ enum { kSubtitlesBoth }; -#ifdef SMALL_SCREEN_DEVICE +#ifdef GUI_ENABLE_KEYSDIALOG enum { kChooseKeyMappingCmd = 'chma' }; @@ -110,6 +112,7 @@ void OptionsDialog::init() { _fullscreenCheckbox = 0; _aspectCheckbox = 0; _enableAudioSettings = false; + _midiTabId = 0; _midiPopUp = 0; _midiPopUpDesc = 0; _oplPopUp = 0; @@ -142,6 +145,7 @@ void OptionsDialog::init() { _speechVolumeSlider = 0; _speechVolumeLabel = 0; _muteCheckbox = 0; + _enableSubtitleSettings = false; _subToggleDesc = 0; _subToggleGroup = 0; _subToggleSubOnly = 0; @@ -150,6 +154,8 @@ void OptionsDialog::init() { _subSpeedDesc = 0; _subSpeedSlider = 0; _subSpeedLabel = 0; + + _pathsTabId = 0; _oldTheme = g_gui.theme()->getThemeId(); // Retrieve game GUI options @@ -204,12 +210,12 @@ void OptionsDialog::open() { _renderModePopUp->setSelectedTag(sel); } -#ifdef SMALL_SCREEN_DEVICE +#ifdef GUI_ONLY_FULLSCREEN _fullscreenCheckbox->setState(true); _fullscreenCheckbox->setEnabled(false); - _aspectCheckbox->setState(false); + _aspectCheckbox->setState(ConfMan.getBool("aspect_ratio", _domain)); _aspectCheckbox->setEnabled(false); -#else // !SMALL_SCREEN_DEVICE +#else // !GUI_ONLY_FULLSCREEN // Fullscreen setting _fullscreenCheckbox->setState(ConfMan.getBool("fullscreen", _domain)); @@ -221,7 +227,7 @@ void OptionsDialog::open() { _aspectCheckbox->setEnabled(true); _aspectCheckbox->setState(ConfMan.getBool("aspect_ratio", _domain)); } -#endif // SMALL_SCREEN_DEVICE +#endif // GUI_ONLY_FULLSCREEN } @@ -604,7 +610,7 @@ void OptionsDialog::setGraphicSettingsState(bool enabled) { _gfxPopUp->setEnabled(enabled); _renderModePopUpDesc->setEnabled(enabled); _renderModePopUp->setEnabled(enabled); -#ifndef SMALL_SCREEN_DEVICE +#ifndef GUI_ENABLE_KEYSDIALOG _fullscreenCheckbox->setEnabled(enabled); if (_guioptions.contains(GUIO_NOASPECT)) _aspectCheckbox->setEnabled(false); @@ -868,10 +874,6 @@ void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefi _midiGainSlider->setMaxValue(1000); _midiGainLabel = new StaticTextWidget(boss, prefix + "mcMidiGainLabel", "1.00"); -#ifdef USE_FLUIDSYNTH - new ButtonWidget(boss, prefix + "mcFluidSynthSettings", _("FluidSynth Settings"), 0, kFluidSynthSettingsCmd); -#endif - _enableMIDISettings = true; } @@ -1109,6 +1111,10 @@ GlobalOptionsDialog::GlobalOptionsDialog() _midiTabId = tab->addTab(_("MIDI")); addMIDIControls(tab, "GlobalOptions_MIDI."); +#ifdef USE_FLUIDSYNTH + new ButtonWidget(tab, "GlobalOptions_MIDI.mcFluidSynthSettings", _("FluidSynth Settings"), 0, kFluidSynthSettingsCmd); +#endif + // // 4) The MT-32 tab // @@ -1194,7 +1200,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() _autosavePeriodPopUp->appendEntry(_(savePeriodLabels[i]), savePeriodValues[i]); } -#ifdef SMALL_SCREEN_DEVICE +#ifdef GUI_ENABLE_KEYSDIALOG new ButtonWidget(tab, "GlobalOptions_Misc.KeysButton", _("Keys"), 0, kChooseKeyMappingCmd); #endif @@ -1229,6 +1235,22 @@ GlobalOptionsDialog::GlobalOptionsDialog() #endif // USE_TRANSLATION +#ifdef USE_UPDATES + _updatesPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.UpdatesPopupDesc", _("Update check:"), _("How often to check ScummVM updates")); + _updatesPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.UpdatesPopup"); + + const int *vals = Common::UpdateManager::getUpdateIntervals(); + + while (*vals != -1) { + _updatesPopUp->appendEntry(Common::UpdateManager::updateIntervalToString(*vals), *vals); + vals++; + } + + _updatesPopUp->setSelectedTag(Common::UpdateManager::normalizeInterval(ConfMan.getInt("updates_check"))); + + new ButtonWidget(tab, "GlobalOptions_Misc.UpdatesCheckManuallyButton", _("Check now"), 0, kUpdatesCheckCmd); +#endif + // Activate the first tab tab->setActiveTab(0); _tabWidget = tab; @@ -1237,7 +1259,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() new ButtonWidget(this, "GlobalOptions.Cancel", _("Cancel"), 0, kCloseCmd); new ButtonWidget(this, "GlobalOptions.Ok", _("OK"), 0, kOKCmd); -#ifdef SMALL_SCREEN_DEVICE +#ifdef GUI_ENABLE_KEYSDIALOG _keysDialog = new KeysDialog(); #endif @@ -1247,7 +1269,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() } GlobalOptionsDialog::~GlobalOptionsDialog() { -#ifdef SMALL_SCREEN_DEVICE +#ifdef GUI_ENABLE_KEYSDIALOG delete _keysDialog; #endif @@ -1367,6 +1389,19 @@ void GlobalOptionsDialog::close() { } #endif // USE_TRANSLATION +#ifdef USE_UPDATES + ConfMan.setInt("updates_check", _updatesPopUp->getSelectedTag()); + + if (g_system->getUpdateManager()) { + if (_updatesPopUp->getSelectedTag() == Common::UpdateManager::kUpdateIntervalNotSupported) { + g_system->getUpdateManager()->setAutomaticallyChecksForUpdates(Common::UpdateManager::kUpdateStateDisabled); + } else { + g_system->getUpdateManager()->setAutomaticallyChecksForUpdates(Common::UpdateManager::kUpdateStateEnabled); + g_system->getUpdateManager()->setUpdateCheckInterval(_updatesPopUp->getSelectedTag()); + } + } +#endif + } OptionsDialog::close(); } @@ -1478,7 +1513,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 } break; } -#ifdef SMALL_SCREEN_DEVICE +#ifdef GUI_ENABLE_KEYSDIALOG case kChooseKeyMappingCmd: _keysDialog->runModal(); break; @@ -1488,6 +1523,12 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 _fluidSynthSettingsDialog->runModal(); break; #endif +#ifdef USE_UPDATES + case kUpdatesCheckCmd: + if (g_system->getUpdateManager()) + g_system->getUpdateManager()->checkForUpdates(); + break; +#endif default: OptionsDialog::handleCommand(sender, cmd, data); } diff --git a/gui/options.h b/gui/options.h index 1e65bfd134..294b41794b 100644 --- a/gui/options.h +++ b/gui/options.h @@ -29,7 +29,7 @@ #include "common/str.h" #include "audio/mididrv.h" -#ifdef SMALL_SCREEN_DEVICE +#ifdef GUI_ENABLE_KEYSDIALOG #include "gui/KeysDialog.h" #endif @@ -210,7 +210,7 @@ public: virtual void reflowLayout(); protected: -#ifdef SMALL_SCREEN_DEVICE +#ifdef GUI_ENABLE_KEYSDIALOG KeysDialog *_keysDialog; #endif #ifdef USE_FLUIDSYNTH @@ -236,6 +236,11 @@ protected: PopUpWidget *_autosavePeriodPopUp; StaticTextWidget *_guiLanguagePopUpDesc; PopUpWidget *_guiLanguagePopUp; + +#ifdef USE_UPDATES + StaticTextWidget *_updatesPopUpDesc; + PopUpWidget *_updatesPopUp; +#endif }; } // End of namespace GUI diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp index a894b02f80..933667186e 100644 --- a/gui/predictivedialog.cpp +++ b/gui/predictivedialog.cpp @@ -24,6 +24,7 @@ #include "gui/widget.h" #include "gui/widgets/edittext.h" #include "gui/gui-manager.h" +#include "gui/ThemeEval.h" #include "common/config-manager.h" #include "common/translation.h" @@ -69,74 +70,57 @@ enum { PredictiveDialog::PredictiveDialog() : Dialog("Predictive") { new StaticTextWidget(this, "Predictive.Headline", "Enter Text"); - _btns = (ButtonWidget **)calloc(16, sizeof(ButtonWidget *)); - - _btns[kCancelAct] = new ButtonWidget(this, "Predictive.Cancel", _("Cancel") , 0, kCancelCmd); - _btns[kOkAct] = new ButtonWidget(this, "Predictive.OK", _("Ok") , 0, kOkCmd); - _btns[kBtn1Act] = new ButtonWidget(this, "Predictive.Button1", "1 `-.&" , 0, kBut1Cmd); - _btns[kBtn2Act] = new ButtonWidget(this, "Predictive.Button2", "2 abc" , 0, kBut2Cmd); - _btns[kBtn3Act] = new ButtonWidget(this, "Predictive.Button3", "3 def" , 0, kBut3Cmd); - _btns[kBtn4Act] = new ButtonWidget(this, "Predictive.Button4", "4 ghi" , 0, kBut4Cmd); - _btns[kBtn5Act] = new ButtonWidget(this, "Predictive.Button5", "5 jkl" , 0, kBut5Cmd); - _btns[kBtn6Act] = new ButtonWidget(this, "Predictive.Button6", "6 mno" , 0, kBut6Cmd); - _btns[kBtn7Act] = new ButtonWidget(this, "Predictive.Button7", "7 pqrs" , 0, kBut7Cmd); - _btns[kBtn8Act] = new ButtonWidget(this, "Predictive.Button8", "8 tuv" , 0, kBut8Cmd); - _btns[kBtn9Act] = new ButtonWidget(this, "Predictive.Button9", "9 wxyz" , 0, kBut9Cmd); - _btns[kBtn0Act] = new ButtonWidget(this, "Predictive.Button0", "0" , 0, kBut0Cmd); - // I18N: You must leave "#" as is, only word 'next' is translatable - _btns[kNextAct] = new ButtonWidget(this, "Predictive.Next", _("# next") , 0, kNextCmd); - _btns[kAddAct] = new ButtonWidget(this, "Predictive.Add", _("add") , 0, kAddCmd); - _btns[kAddAct]->setEnabled(false); - - #ifndef DISABLE_FANCY_THEMES - _btns[kDelAct] = new PicButtonWidget(this, "Predictive.Delete", _("Delete char"), kDelCmd); - ((PicButtonWidget *)_btns[kDelAct])->useThemeTransparency(true); - ((PicButtonWidget *)_btns[kDelAct])->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageDelbtn)); - #endif - _btns[kDelAct] = new ButtonWidget(this, "Predictive.Delete" , _("<") , 0, kDelCmd); - // I18N: Pre means 'Predictive', leave '*' as is - _btns[kModeAct] = new ButtonWidget(this, "Predictive.Pre", _("* Pre"), 0, kModeCmd); - _edittext = new EditTextWidget(this, "Predictive.Word", _search, 0, 0, 0); + _button[kCancelAct] = new ButtonWidget(this, "Predictive.Cancel", _("Cancel") , 0, kCancelCmd); + _button[kOkAct] = new ButtonWidget(this, "Predictive.OK", _("Ok") , 0, kOkCmd); + _button[kButton1Act] = new ButtonWidget(this, "Predictive.Button1", "1 `-.&" , 0, kBut1Cmd); + _button[kButton2Act] = new ButtonWidget(this, "Predictive.Button2", "2 abc" , 0, kBut2Cmd); + _button[kButton3Act] = new ButtonWidget(this, "Predictive.Button3", "3 def" , 0, kBut3Cmd); + _button[kButton4Act] = new ButtonWidget(this, "Predictive.Button4", "4 ghi" , 0, kBut4Cmd); + _button[kButton5Act] = new ButtonWidget(this, "Predictive.Button5", "5 jkl" , 0, kBut5Cmd); + _button[kButton6Act] = new ButtonWidget(this, "Predictive.Button6", "6 mno" , 0, kBut6Cmd); + _button[kButton7Act] = new ButtonWidget(this, "Predictive.Button7", "7 pqrs" , 0, kBut7Cmd); + _button[kButton8Act] = new ButtonWidget(this, "Predictive.Button8", "8 tuv" , 0, kBut8Cmd); + _button[kButton9Act] = new ButtonWidget(this, "Predictive.Button9", "9 wxyz" , 0, kBut9Cmd); + _button[kButton0Act] = new ButtonWidget(this, "Predictive.Button0", "0" , 0, kBut0Cmd); + // I18N: You must leave "#" as is, only word 'next' is translatable + _button[kNextAct] = new ButtonWidget(this, "Predictive.Next", _("# next") , 0, kNextCmd); + _button[kAddAct] = new ButtonWidget(this, "Predictive.Add", _("add") , 0, kAddCmd); + _button[kAddAct]->setEnabled(false); + +#ifndef DISABLE_FANCY_THEMES + if (g_gui.xmlEval()->getVar("Globals.Predictive.ShowDeletePic") == 1 && g_gui.theme()->supportsImages()) { + _button[kDelAct] = new PicButtonWidget(this, "Predictive.Delete", _("Delete char"), kDelCmd); + ((PicButtonWidget *)_button[kDelAct])->useThemeTransparency(true); + ((PicButtonWidget *)_button[kDelAct])->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageDelButton)); + } else +#endif + _button[kDelAct] = new ButtonWidget(this, "Predictive.Delete" , _("<") , 0, kDelCmd); + // I18N: Pre means 'Predictive', leave '*' as is + _button[kModeAct] = new ButtonWidget(this, "Predictive.Pre", _("* Pre"), 0, kModeCmd); + _editText = new EditTextWidget(this, "Predictive.Word", _search, 0, 0, 0); _userDictHasChanged = false; _predictiveDict.nameDict = "predictive_dictionary"; - _predictiveDict.fnameDict = "pred.dic"; - _predictiveDict.dictActLine = NULL; + _predictiveDict.defaultFilename = "pred.dic"; _userDict.nameDict = "user_dictionary"; - _userDict.fnameDict = "user.dic"; - _userDict.dictActLine = NULL; - - _unitedDict.nameDict = ""; - _unitedDict.fnameDict = ""; - - _predictiveDict.dictLine = NULL; - _predictiveDict.dictText = NULL; - _predictiveDict.dictLineCount = 0; + _userDict.defaultFilename = "user.dic"; if (!_predictiveDict.dictText) { loadAllDictionary(_predictiveDict); if (!_predictiveDict.dictText) - debug("Predictive Dialog: pred.dic not loaded"); + debug(5, "Predictive Dialog: pred.dic not loaded"); } - _userDict.dictLine = NULL; - _userDict.dictText = NULL; - _userDict.dictTextSize = 0; - _userDict.dictLineCount = 0; - if (!_userDict.dictText) { loadAllDictionary(_userDict); if (!_userDict.dictText) - debug("Predictive Dialog: user.dic not loaded"); + debug(5, "Predictive Dialog: user.dic not loaded"); } mergeDicts(); - _unitedDict.dictActLine = NULL; - _unitedDict.dictText = NULL; - memset(_repeatcount, 0, sizeof(_repeatcount)); _prefix.clear(); @@ -146,18 +130,21 @@ PredictiveDialog::PredictiveDialog() : Dialog("Predictive") { _numMatchingWords = 0; memset(_predictiveResult, 0, sizeof(_predictiveResult)); - _lastbutton = kNoAct; + _lastButton = kNoAct; _mode = kModePre; _lastTime = 0; _curTime = 0; - _lastPressBtn = kNoAct; + _lastPressedButton = kNoAct; _memoryList[0] = _predictiveDict.dictText; _memoryList[1] = _userDict.dictText; _numMemory = 0; - _navigationwithkeys = false; + _navigationWithKeys = false; + + _curPressedButton = kNoAct; + _needRefresh = true; } PredictiveDialog::~PredictiveDialog() { @@ -167,8 +154,25 @@ PredictiveDialog::~PredictiveDialog() { free(_userDict.dictLine); free(_predictiveDict.dictLine); free(_unitedDict.dictLine); +} + +void PredictiveDialog::reflowLayout() { +#ifndef DISABLE_FANCY_THEMES + removeWidget(_button[kDelAct]); + _button[kDelAct]->setNext(0); + delete _button[kDelAct]; + _button[kDelAct] = nullptr; + + if (g_gui.xmlEval()->getVar("Globals.Predictive.ShowDeletePic") == 1 && g_gui.theme()->supportsImages()) { + _button[kDelAct] = new PicButtonWidget(this, "Predictive.Delete", _("Delete char"), kDelCmd); + ((PicButtonWidget *)_button[kDelAct])->useThemeTransparency(true); + ((PicButtonWidget *)_button[kDelAct])->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageDelButton)); + } else { + _button[kDelAct] = new ButtonWidget(this, "Predictive.Delete" , _("<") , 0, kDelCmd); + } +#endif - free(_btns); + Dialog::reflowLayout(); } void PredictiveDialog::saveUserDictToFile() { @@ -188,22 +192,22 @@ void PredictiveDialog::saveUserDictToFile() { } void PredictiveDialog::handleKeyUp(Common::KeyState state) { - if (_currBtn != kNoAct && !_needRefresh) { - _btns[_currBtn]->startAnimatePressedState(); - processBtnActive(_currBtn); + if (_curPressedButton != kNoAct && !_needRefresh) { + _button[_curPressedButton]->setUnpressedState(); + processButton(_curPressedButton); } } void PredictiveDialog::handleKeyDown(Common::KeyState state) { - _currBtn = kNoAct; + _curPressedButton = kNoAct; _needRefresh = false; - if (getFocusWidget() == _edittext) { - setFocusWidget(_btns[kAddAct]); + if (getFocusWidget() == _editText) { + setFocusWidget(_button[kAddAct]); } - if (_lastbutton == kNoAct) { - _lastbutton = kBtn5Act; + if (_lastButton == kNoAct) { + _lastButton = kButton5Act; } switch (state.keycode) { @@ -212,128 +216,128 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) { close(); return; case Common::KEYCODE_LEFT: - _navigationwithkeys = true; - if (_lastbutton == kBtn1Act || _lastbutton == kBtn4Act || _lastbutton == kBtn7Act) - _currBtn = ButtonId(_lastbutton + 2); - else if (_lastbutton == kDelAct) - _currBtn = kBtn1Act; - else if (_lastbutton == kModeAct) - _currBtn = kNextAct; - else if (_lastbutton == kNextAct) - _currBtn = kBtn0Act; - else if (_lastbutton == kAddAct) - _currBtn = kOkAct; - else if (_lastbutton == kCancelAct) - _currBtn = kAddAct; + _navigationWithKeys = true; + if (_lastButton == kButton1Act || _lastButton == kButton4Act || _lastButton == kButton7Act) + _curPressedButton = ButtonId(_lastButton + 2); + else if (_lastButton == kDelAct) + _curPressedButton = kButton1Act; + else if (_lastButton == kModeAct) + _curPressedButton = kNextAct; + else if (_lastButton == kNextAct) + _curPressedButton = kButton0Act; + else if (_lastButton == kAddAct) + _curPressedButton = kOkAct; + else if (_lastButton == kCancelAct) + _curPressedButton = kAddAct; else - _currBtn = ButtonId(_lastbutton - 1); + _curPressedButton = ButtonId(_lastButton - 1); - if (_mode != kModeAbc && _lastbutton == kCancelAct) - _currBtn = kOkAct; + if (_mode != kModeAbc && _lastButton == kCancelAct) + _curPressedButton = kOkAct; _needRefresh = true; break; case Common::KEYCODE_RIGHT: - _navigationwithkeys = true; - if (_lastbutton == kBtn3Act || _lastbutton == kBtn6Act || _lastbutton == kBtn9Act || _lastbutton == kOkAct) - _currBtn = ButtonId(_lastbutton - 2); - else if (_lastbutton == kDelAct) - _currBtn = kBtn3Act; - else if (_lastbutton == kBtn0Act) - _currBtn = kNextAct; - else if (_lastbutton == kNextAct) - _currBtn = kModeAct; - else if (_lastbutton == kAddAct) - _currBtn = kCancelAct; - else if (_lastbutton == kOkAct) - _currBtn = kAddAct; + _navigationWithKeys = true; + if (_lastButton == kButton3Act || _lastButton == kButton6Act || _lastButton == kButton9Act || _lastButton == kOkAct) + _curPressedButton = ButtonId(_lastButton - 2); + else if (_lastButton == kDelAct) + _curPressedButton = kButton3Act; + else if (_lastButton == kButton0Act) + _curPressedButton = kNextAct; + else if (_lastButton == kNextAct) + _curPressedButton = kModeAct; + else if (_lastButton == kAddAct) + _curPressedButton = kCancelAct; + else if (_lastButton == kOkAct) + _curPressedButton = kAddAct; else - _currBtn = ButtonId(_lastbutton + 1); + _curPressedButton = ButtonId(_lastButton + 1); - if (_mode != kModeAbc && _lastbutton == kOkAct) - _currBtn = kCancelAct; + if (_mode != kModeAbc && _lastButton == kOkAct) + _curPressedButton = kCancelAct; _needRefresh = true; break; case Common::KEYCODE_UP: - _navigationwithkeys = true; - if (_lastbutton <= kBtn3Act) - _currBtn = kDelAct; - else if (_lastbutton == kDelAct) - _currBtn = kOkAct; - else if (_lastbutton == kModeAct) - _currBtn = kBtn7Act; - else if (_lastbutton == kBtn0Act) - _currBtn = kBtn8Act; - else if (_lastbutton == kNextAct) - _currBtn = kBtn9Act; - else if (_lastbutton == kAddAct) - _currBtn = kModeAct; - else if (_lastbutton == kCancelAct) - _currBtn = kBtn0Act; - else if (_lastbutton == kOkAct) - _currBtn = kNextAct; + _navigationWithKeys = true; + if (_lastButton <= kButton3Act) + _curPressedButton = kDelAct; + else if (_lastButton == kDelAct) + _curPressedButton = kOkAct; + else if (_lastButton == kModeAct) + _curPressedButton = kButton7Act; + else if (_lastButton == kButton0Act) + _curPressedButton = kButton8Act; + else if (_lastButton == kNextAct) + _curPressedButton = kButton9Act; + else if (_lastButton == kAddAct) + _curPressedButton = kModeAct; + else if (_lastButton == kCancelAct) + _curPressedButton = kButton0Act; + else if (_lastButton == kOkAct) + _curPressedButton = kNextAct; else - _currBtn = ButtonId(_lastbutton - 3); + _curPressedButton = ButtonId(_lastButton - 3); _needRefresh = true; break; case Common::KEYCODE_DOWN: - _navigationwithkeys = true; - if (_lastbutton == kDelAct) - _currBtn = kBtn3Act; - else if (_lastbutton == kBtn7Act) - _currBtn = kModeAct; - else if (_lastbutton == kBtn8Act) - _currBtn = kBtn0Act; - else if (_lastbutton == kBtn9Act) - _currBtn = kNextAct; - else if (_lastbutton == kModeAct) - _currBtn = kAddAct; - else if (_lastbutton == kBtn0Act) - _currBtn = kCancelAct; - else if (_lastbutton == kNextAct) - _currBtn = kOkAct; - else if (_lastbutton == kAddAct || _lastbutton == kCancelAct || _lastbutton == kOkAct) - _currBtn = kDelAct; + _navigationWithKeys = true; + if (_lastButton == kDelAct) + _curPressedButton = kButton3Act; + else if (_lastButton == kButton7Act) + _curPressedButton = kModeAct; + else if (_lastButton == kButton8Act) + _curPressedButton = kButton0Act; + else if (_lastButton == kButton9Act) + _curPressedButton = kNextAct; + else if (_lastButton == kModeAct) + _curPressedButton = kAddAct; + else if (_lastButton == kButton0Act) + _curPressedButton = kCancelAct; + else if (_lastButton == kNextAct) + _curPressedButton = kOkAct; + else if (_lastButton == kAddAct || _lastButton == kCancelAct || _lastButton == kOkAct) + _curPressedButton = kDelAct; else - _currBtn = ButtonId(_lastbutton + 3); + _curPressedButton = ButtonId(_lastButton + 3); - if (_mode != kModeAbc && _lastbutton == kModeAct) - _currBtn = kCancelAct; + if (_mode != kModeAbc && _lastButton == kModeAct) + _curPressedButton = kCancelAct; _needRefresh = true; break; case Common::KEYCODE_KP_ENTER: case Common::KEYCODE_RETURN: if (state.flags & Common::KBD_CTRL) { - _currBtn = kOkAct; + _curPressedButton = kOkAct; break; } - if (_navigationwithkeys) { + if (_navigationWithKeys) { // when the user has utilized arrow key navigation, - // interpret enter as 'click' on the _currBtn button - _currBtn = _lastbutton; + // interpret enter as 'click' on the _curPressedButton button + _curPressedButton = _lastButton; _needRefresh = false; } else { // else it is a shortcut for 'Ok' - _currBtn = kOkAct; + _curPressedButton = kOkAct; } break; case Common::KEYCODE_KP_PLUS: - _currBtn = kAddAct; + _curPressedButton = kAddAct; break; case Common::KEYCODE_BACKSPACE: case Common::KEYCODE_KP_MINUS: - _currBtn = kDelAct; + _curPressedButton = kDelAct; break; case Common::KEYCODE_KP_DIVIDE: - _currBtn = kNextAct; + _curPressedButton = kNextAct; break; case Common::KEYCODE_KP_MULTIPLY: - _currBtn = kModeAct; + _curPressedButton = kModeAct; break; case Common::KEYCODE_KP0: - _currBtn = kBtn0Act; + _curPressedButton = kButton0Act; break; case Common::KEYCODE_KP1: case Common::KEYCODE_KP2: @@ -344,79 +348,79 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) { case Common::KEYCODE_KP7: case Common::KEYCODE_KP8: case Common::KEYCODE_KP9: - _currBtn = ButtonId(state.keycode - Common::KEYCODE_KP1); + _curPressedButton = ButtonId(state.keycode - Common::KEYCODE_KP1); break; default: Dialog::handleKeyDown(state); } - if (_lastbutton != _currBtn) - _btns[_lastbutton]->stopAnimatePressedState(); + if (_lastButton != _curPressedButton) + _button[_lastButton]->setUnpressedState(); - if (_currBtn != kNoAct && !_needRefresh) - _btns[_currBtn]->setPressedState(); + if (_curPressedButton != kNoAct && !_needRefresh) + _button[_curPressedButton]->setPressedState(); else - updateHighLightedButton(_currBtn); + updateHighLightedButton(_curPressedButton); } void PredictiveDialog::updateHighLightedButton(ButtonId act) { - if (_currBtn != kNoAct) { - _btns[_lastbutton]->setHighLighted(false); - _lastbutton = act; - _btns[_lastbutton]->setHighLighted(true); + if (_curPressedButton != kNoAct) { + _button[_lastButton]->setHighLighted(false); + _lastButton = act; + _button[_lastButton]->setHighLighted(true); } } void PredictiveDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { - _currBtn = kNoAct; + _curPressedButton = kNoAct; - _navigationwithkeys = false; + _navigationWithKeys = false; - if (_lastbutton != kNoAct) - _btns[_lastbutton]->setHighLighted(false); + if (_lastButton != kNoAct) + _button[_lastButton]->setHighLighted(false); switch (cmd) { case kDelCmd: - _currBtn = kDelAct; + _curPressedButton = kDelAct; break; case kNextCmd: - _currBtn = kNextAct; + _curPressedButton = kNextAct; break; case kAddCmd: - _currBtn = kAddAct; + _curPressedButton = kAddAct; break; case kModeCmd: - _currBtn = kModeAct; + _curPressedButton = kModeAct; break; case kBut1Cmd: - _currBtn = kBtn1Act; + _curPressedButton = kButton1Act; break; case kBut2Cmd: - _currBtn = kBtn2Act; + _curPressedButton = kButton2Act; break; case kBut3Cmd: - _currBtn = kBtn3Act; + _curPressedButton = kButton3Act; break; case kBut4Cmd: - _currBtn = kBtn4Act; + _curPressedButton = kButton4Act; break; case kBut5Cmd: - _currBtn = kBtn5Act; + _curPressedButton = kButton5Act; break; case kBut6Cmd: - _currBtn = kBtn6Act; + _curPressedButton = kButton6Act; break; case kBut7Cmd: - _currBtn = kBtn7Act; + _curPressedButton = kButton7Act; break; case kBut8Cmd: - _currBtn = kBtn8Act; + _curPressedButton = kButton8Act; break; case kBut9Cmd: - _currBtn = kBtn9Act; + _curPressedButton = kButton9Act; break; case kBut0Cmd: - _currBtn = kBtn0Act; + _curPressedButton = kButton0Act; break; case kCancelCmd: saveUserDictToFile(); @@ -426,19 +430,18 @@ void PredictiveDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 d _predictiveResult[0] = 0; return; case kOkCmd: - _currBtn = kOkAct; + _curPressedButton = kOkAct; break; default: Dialog::handleCommand(sender, cmd, data); } - if (_currBtn != kNoAct) { - processBtnActive(_currBtn); + if (_curPressedButton != kNoAct) { + processButton(_curPressedButton); } } -void PredictiveDialog::processBtnActive(ButtonId button) { - uint8 x; +void PredictiveDialog::processButton(ButtonId button) { static const char *const buttonStr[] = { "1", "2", "3", "4", "5", "6", @@ -457,10 +460,10 @@ void PredictiveDialog::processBtnActive(ButtonId button) { }; if (_mode == kModeAbc) { - if (button >= kBtn1Act && button <= kBtn9Act) { + if (button >= kButton1Act && button <= kButton9Act) { if (!_lastTime) _lastTime = g_system->getMillis(); - if (_lastPressBtn == button) { + if (_lastPressedButton == button) { _curTime = g_system->getMillis(); if ((_curTime - _lastTime) < kRepeatDelay) { button = kNextAct; @@ -469,15 +472,15 @@ void PredictiveDialog::processBtnActive(ButtonId button) { _lastTime = 0; } } else { - _lastPressBtn = button; + _lastPressedButton = button; _lastTime = g_system->getMillis(); } } } - if (button >= kBtn1Act) { - _lastbutton = button; - if (button == kBtn0Act && _mode != kModeNum) { // Space + if (button >= kButton1Act) { + _lastButton = button; + if (button == kButton0Act && _mode != kModeNum) { // Space // bring MRU word at the top of the list when changing words if (_mode == kModePre && _unitedDict.dictActLine && _numMatchingWords > 1 && _wordNumber != 0) bringWordtoTop(_unitedDict.dictActLine, _wordNumber); @@ -491,9 +494,9 @@ void PredictiveDialog::processBtnActive(ButtonId button) { _numMatchingWords = 0; memset(_repeatcount, 0, sizeof(_repeatcount)); _lastTime = 0; - _lastPressBtn = kNoAct; + _lastPressedButton = kNoAct; _curTime = 0; - } else if (button < kNextAct || button == kDelAct || button == kBtn0Act) { // number or backspace + } else if (button < kNextAct || button == kDelAct || button == kButton0Act) { // number or backspace if (button == kDelAct) { // backspace if (_currentCode.size()) { _repeatcount[_currentCode.size() - 1] = 0; @@ -505,7 +508,7 @@ void PredictiveDialog::processBtnActive(ButtonId button) { _prefix.deleteLastChar(); } } else if (_prefix.size() + _currentCode.size() < kMaxWordLen - 1) { // don't overflow the dialog line - if (button == kBtn0Act) { // zero + if (button == kButton0Act) { // zero _currentCode += buttonStr[9]; } else { _currentCode += buttonStr[button]; @@ -524,7 +527,7 @@ void PredictiveDialog::processBtnActive(ButtonId button) { _numMatchingWords = countWordsInString(_unitedDict.dictActLine); break; case kModeAbc: - for (x = 0; x < _currentCode.size(); x++) + for (uint x = 0; x < _currentCode.size(); x++) if (_currentCode[x] >= '1') _temp[x] = buttons[_currentCode[x] - '1'][_repeatcount[x]]; _temp[_currentCode.size()] = 0; @@ -543,7 +546,7 @@ void PredictiveDialog::processBtnActive(ButtonId button) { _currentWord = Common::String(tok, _currentCode.size()); } } else if (_mode == kModeAbc) { - x = _currentCode.size(); + uint x = _currentCode.size(); if (x) { if (_currentCode.lastChar() == '1' || _currentCode.lastChar() == '7' || _currentCode.lastChar() == '9') _repeatcount[x - 1] = (_repeatcount[x - 1] + 1) % 4; @@ -558,25 +561,25 @@ void PredictiveDialog::processBtnActive(ButtonId button) { if (_mode == kModeAbc) addWordToDict(); else - debug("Predictive Dialog: button Add doesn't work in this mode"); + debug(5, "Predictive Dialog: button Add doesn't work in this mode"); } else if (button == kOkAct) { // Ok // bring MRU word at the top of the list when ok'ed out of the dialog if (_mode == kModePre && _unitedDict.dictActLine && _numMatchingWords > 1 && _wordNumber != 0) bringWordtoTop(_unitedDict.dictActLine, _wordNumber); } else if (button == kModeAct) { // Mode _mode++; - _btns[kAddAct]->setEnabled(false); + _button[kAddAct]->setEnabled(false); if (_mode > kModeAbc) { _mode = kModePre; // I18N: Pre means 'Predictive', leave '*' as is - _btns[kModeAct]->setLabel("* Pre"); + _button[kModeAct]->setLabel(_("* Pre")); } else if (_mode == kModeNum) { // I18N: 'Num' means Numbers - _btns[kModeAct]->setLabel("* Num"); + _button[kModeAct]->setLabel(_("* Num")); } else { // I18N: 'Abc' means Latin alphabet input - _btns[kModeAct]->setLabel("* Abc"); - _btns[kAddAct]->setEnabled(true); + _button[kModeAct]->setLabel(_("* Abc")); + _button[kAddAct]->setEnabled(true); } // truncate current input at mode change @@ -588,7 +591,7 @@ void PredictiveDialog::processBtnActive(ButtonId button) { memset(_repeatcount, 0, sizeof(_repeatcount)); _lastTime = 0; - _lastPressBtn = kNoAct; + _lastPressedButton = kNoAct; _curTime = 0; } } @@ -598,21 +601,9 @@ void PredictiveDialog::processBtnActive(ButtonId button) { if (button == kOkAct) close(); - if (button == kCancelAct) { - saveUserDictToFile(); - close(); - } -} - -void PredictiveDialog::handleTickle() { - if (_lastTime) { - if ((_curTime - _lastTime) > kRepeatDelay) { - _lastTime = 0; - } - } - - if (getTickleWidget()) { - getTickleWidget()->handleTickle(); + if (button == kCancelAct) { + saveUserDictToFile(); + close(); } } @@ -621,7 +612,7 @@ void PredictiveDialog::mergeDicts() { _unitedDict.dictLine = (char **)calloc(_unitedDict.dictLineCount, sizeof(char *)); if (!_unitedDict.dictLine) { - debug("Predictive Dialog: cannot allocate memory for united dic"); + debug(5, "Predictive Dialog: cannot allocate memory for united dic"); return; } @@ -658,7 +649,7 @@ uint8 PredictiveDialog::countWordsInString(const char *const str) { ptr = strchr(str, ' '); if (!ptr) { - debug("Predictive Dialog: Invalid dictionary line"); + debug(5, "Predictive Dialog: Invalid dictionary line"); return 0; } @@ -684,7 +675,7 @@ void PredictiveDialog::bringWordtoTop(char *str, int wordnum) { buf[kMaxLineLen - 1] = 0; char *word = strtok(buf, " "); if (!word) { - debug("Predictive Dialog: Invalid dictionary line"); + debug(5, "Predictive Dialog: Invalid dictionary line"); return; } @@ -724,6 +715,10 @@ int PredictiveDialog::binarySearch(const char *const *const dictLine, const Comm } bool PredictiveDialog::matchWord() { + // If there is no dictionary, then there is no match. + if (_unitedDict.dictLineCount <= 0) + return false; + // If no text has been entered, then there is no match. if (_currentCode.empty()) return false; @@ -734,7 +729,7 @@ bool PredictiveDialog::matchWord() { // The entries in the dictionary consist of a code, a space, and then // a space-separated list of words matching this code. - // To ex_currBtnly match a code, we therefore match the code plus the trailing + // To exactly match a code, we therefore match the code plus the trailing // space in the dictionary. Common::String code = _currentCode + " "; @@ -929,7 +924,7 @@ void PredictiveDialog::loadDictionary(Common::SeekableReadStream *in, Dict &dict in->read(dict.dictText, dict.dictTextSize); dict.dictText[dict.dictTextSize] = 0; uint32 time2 = g_system->getMillis(); - debug("Predictive Dialog: Time to read %s: %d bytes, %d ms", ConfMan.get(dict.nameDict).c_str(), dict.dictTextSize, time2 - time1); + debug(5, "Predictive Dialog: Time to read %s: %d bytes, %d ms", ConfMan.get(dict.nameDict).c_str(), dict.dictTextSize, time2 - time1); delete in; char *ptr = dict.dictText; @@ -960,7 +955,7 @@ void PredictiveDialog::loadDictionary(Common::SeekableReadStream *in, Dict &dict lines--; dict.dictLineCount = lines; - debug("Predictive Dialog: Loaded %d lines", dict.dictLineCount); + debug(5, "Predictive Dialog: Loaded %d lines", dict.dictLineCount); // FIXME: We use binary search on _predictiveDict.dictLine, yet we make no at_tempt // to ever sort this array (except for the DS port). That seems risky, doesn't it? @@ -971,23 +966,24 @@ void PredictiveDialog::loadDictionary(Common::SeekableReadStream *in, Dict &dict #endif uint32 time3 = g_system->getMillis(); - debug("Predictive Dialog: Time to parse %s: %d, total: %d", ConfMan.get(dict.nameDict).c_str(), time3 - time2, time3 - time1); + debug(5, "Predictive Dialog: Time to parse %s: %d, total: %d", ConfMan.get(dict.nameDict).c_str(), time3 - time2, time3 - time1); } void PredictiveDialog::loadAllDictionary(Dict &dict) { - ConfMan.registerDefault(dict.nameDict, dict.fnameDict); + ConfMan.registerDefault(dict.nameDict, dict.defaultFilename); if (dict.nameDict == "predictive_dictionary") { Common::File *inFile = new Common::File(); if (!inFile->open(ConfMan.get(dict.nameDict))) { - warning("Predictive Dialog: cannot read file: %s", dict.fnameDict.c_str()); + warning("Predictive Dialog: cannot read file: %s", dict.defaultFilename.c_str()); + delete inFile; return; } loadDictionary(inFile, dict); } else { Common::InSaveFile *inFile = g_system->getSavefileManager()->openForLoading(ConfMan.get(dict.nameDict)); if (!inFile) { - warning("Predictive Dialog: cannot read file: %s", dict.fnameDict.c_str()); + warning("Predictive Dialog: cannot read file: %s", dict.defaultFilename.c_str()); return; } loadDictionary(inFile, dict); @@ -997,9 +993,9 @@ void PredictiveDialog::loadAllDictionary(Dict &dict) { void PredictiveDialog::pressEditText() { Common::strlcpy(_predictiveResult, _prefix.c_str(), sizeof(_predictiveResult)); Common::strlcat(_predictiveResult, _currentWord.c_str(), sizeof(_predictiveResult)); - _edittext->setEditString(_predictiveResult); - //_edittext->setCaretPos(_prefix.size() + _currentWord.size()); - _edittext->draw(); + _editText->setEditString(_predictiveResult); + //_editText->setCaretPos(_prefix.size() + _currentWord.size()); + _editText->draw(); } } // namespace GUI diff --git a/gui/predictivedialog.h b/gui/predictivedialog.h index 32d769d6ca..1f6bdf84e0 100644 --- a/gui/predictivedialog.h +++ b/gui/predictivedialog.h @@ -33,56 +33,65 @@ class EditTextWidget; class ButtonWidget; class PicButtonWidget; -enum ButtonId { - kBtn1Act = 0, - kBtn2Act = 1, - kBtn3Act = 2, - kBtn4Act = 3, - kBtn5Act = 4, - kBtn6Act = 5, - kBtn7Act = 6, - kBtn8Act = 7, - kBtn9Act = 8, - kNextAct = 9, - kAddAct = 10, - kDelAct = 11, - kCancelAct = 12, - kOkAct = 13, - kModeAct = 14, - kBtn0Act = 15, - kNoAct = -1 -}; - -enum { - kRepeatDelay = 500 -}; - -enum { - kMaxLineLen = 80, - kMaxWordLen = 24, - kMaxWord = 50 -}; - class PredictiveDialog : public GUI::Dialog { public: PredictiveDialog(); ~PredictiveDialog(); + virtual void reflowLayout(); + virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); virtual void handleKeyUp(Common::KeyState state); virtual void handleKeyDown(Common::KeyState state); - virtual void handleTickle(); const char *getResult() const { return _predictiveResult; } + private: + enum ButtonId { + kButton1Act = 0, + kButton2Act = 1, + kButton3Act = 2, + kButton4Act = 3, + kButton5Act = 4, + kButton6Act = 5, + kButton7Act = 6, + kButton8Act = 7, + kButton9Act = 8, + kNextAct = 9, + kAddAct = 10, + kDelAct = 11, + kCancelAct = 12, + kOkAct = 13, + kModeAct = 14, + kButton0Act = 15, + kNoAct = -1 + }; + + enum { + kButtonCount = kButton0Act + 1 + }; + + enum { + kRepeatDelay = 500 + }; + + enum { + kMaxLineLen = 80, + kMaxWordLen = 24, + kMaxWord = 50 + }; + struct Dict { + Dict() : dictLine(nullptr), dictText(nullptr), dictActLine(nullptr), + dictLineCount(0), dictTextSize(0) {} + ~Dict() { free(dictText); } char **dictLine; char *dictText; char *dictActLine; // using only for united dict... int32 dictLineCount; int32 dictTextSize; Common::String nameDict; - Common::String fnameDict; + Common::String defaultFilename; }; uint8 countWordsInString(const char *const str); @@ -94,7 +103,7 @@ private: bool searchWord(const char *const where, const Common::String &whatCode); int binarySearch(const char *const *const dictLine, const Common::String &code, const int dictLineCount); bool matchWord(); - void processBtnActive(ButtonId active); + void processButton(ButtonId active); void pressEditText(); void saveUserDictToFile(); @@ -108,7 +117,7 @@ private: Dict _userDict; int _mode; - ButtonId _lastbutton; + ButtonId _lastButton; bool _userDictHasChanged; @@ -121,8 +130,8 @@ private: Common::String _prefix; uint32 _curTime, _lastTime; - ButtonId _lastPressBtn; - ButtonId _currBtn; + ButtonId _lastPressedButton; + ButtonId _curPressedButton; char _temp[kMaxWordLen + 1]; int _repeatcount[kMaxWordLen]; @@ -132,11 +141,11 @@ private: Common::String _search; - bool _navigationwithkeys; + bool _navigationWithKeys; bool _needRefresh; private: - EditTextWidget *_edittext; - ButtonWidget **_btns; + EditTextWidget *_editText; + ButtonWidget *_button[kButtonCount]; }; } // namespace GUI diff --git a/gui/recorderdialog.cpp b/gui/recorderdialog.cpp index 5617d2ba9a..c08b3e149a 100644 --- a/gui/recorderdialog.cpp +++ b/gui/recorderdialog.cpp @@ -33,7 +33,6 @@ #include "gui/editrecorddialog.h" #include "gui/EventRecorder.h" #include "gui/message.h" -#include "gui/saveload.h" #include "common/system.h" #include "gui/ThemeEval.h" #include "gui/gui-manager.h" @@ -171,7 +170,7 @@ void RecorderDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat const EnginePlugin *plugin = 0; GameDescriptor desc = EngineMan.findGame(gameId, &plugin); g_system->getTimeAndDate(t); - EditRecordDialog editDlg("Unknown Author", Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description(), ""); + EditRecordDialog editDlg(_("Unknown Author"), Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description(), ""); if (editDlg.runModal() != kOKCmd) { return; } 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/saveload.cpp b/gui/saveload.cpp index c1c1d12ec5..b94d30289b 100644 --- a/gui/saveload.cpp +++ b/gui/saveload.cpp @@ -25,7 +25,6 @@ #include "gui/saveload.h" #include "gui/saveload-dialog.h" -#include "gui/gui-manager.h" #include "engines/metaengine.h" diff --git a/gui/saveload.h b/gui/saveload.h index 22c26d4c5e..01a78c4924 100644 --- a/gui/saveload.h +++ b/gui/saveload.h @@ -23,7 +23,7 @@ #ifndef GUI_SAVELOAD_H #define GUI_SAVELOAD_H -#include "gui/dialog.h" +#include "common/str.h" #include "engines/metaengine.h" namespace GUI { diff --git a/gui/themes/default.inc b/gui/themes/default.inc index aa2a24bf00..c0ea733de8 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1,5 +1,6 @@ - "<?xml version = '1.0'?>" -"<render_info>" +const char *defaultXML1 = "<?xml version = '1.0'?>" +; + const char *defaultXML2 = "<render_info>" "<palette>" "<color name='black' " "rgb='0,0,0' " @@ -610,7 +611,8 @@ "/>" "</drawdata>" "</render_info>" -"<layout_info resolution='y>399'>" +; + const char *defaultXML3 = "<layout_info resolution='y>399'>" "<globals>" "<def var='Line.Height' value='16' />" "<def var='Font.Height' value='16' />" @@ -631,6 +633,7 @@ "<def var='Tooltip.XDelta' value='16'/> " "<def var='Tooltip.YDelta' value='16'/>" "<def var='Predictive.Button.Width' value='60' />" +"<def var='Predictive.ShowDeletePic' value='0'/>" "<widget name='OptionsLabel' " "size='110,Globals.Line.Height' " "textalign='right' " @@ -771,9 +774,31 @@ "</layout>" "</layout>" "</dialog>" +"<dialog name='FileBrowser' overlays='screen' inset='32' shading='dim'>" +"<layout type='vertical' padding='16,16,16,16'>" +"<widget name='Headline' " +"height='Globals.Line.Height' " +"/>" +"<widget name='Filename' " +"height='Globals.Line.Height' " +"/>" +"<space size='10' />" +"<widget name='List'/>" +"<layout type='vertical' padding='0,0,16,0'>" +"<layout type='horizontal' padding='0,0,0,0'>" +"<widget name='Cancel' " +"type='Button' " +"/>" +"<widget name='Choose' " +"type='Button' " +"/>" +"</layout>" +"</layout>" +"</layout>" +"</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' " @@ -1051,6 +1076,17 @@ "type='PopUp' " "/>" "</layout>" +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'>" +"<widget name='UpdatesPopupDesc' " +"type='OptionsLabel' " +"/>" +"<widget name='UpdatesPopup' " +"type='PopUp' " +"/>" +"<widget name='UpdatesCheckManuallyButton' " +"type='Button' " +"/>" +"</layout>" "<widget name='KeysButton' " "type='Button' " "/>" @@ -1082,7 +1118,7 @@ "</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' " @@ -1369,7 +1405,7 @@ "</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' " @@ -1873,7 +1909,8 @@ "</layout>" "</dialog>" "</layout_info>" -"<layout_info resolution='y<400'>" +; + const char *defaultXML4 = "<layout_info resolution='y<400'>" "<globals>" "<def var='Line.Height' value='12' />" "<def var='Font.Height' value='10' />" @@ -1895,6 +1932,7 @@ "<def var='Tooltip.YDelta' value='8'/>" "<def var='Predictive.Button.Width' value='45' />" "<def var='Predictive.Button.Height' value='15' />" +"<def var='Predictive.ShowDeletePic' value='0'/>" "<widget name='Button' " "size='72,16' " "/>" @@ -1937,7 +1975,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' " @@ -2031,9 +2069,31 @@ "</layout>" "</layout>" "</dialog>" +"<dialog name='FileBrowser' overlays='screen' inset='16' shading='dim'>" +"<layout type='vertical' padding='16,16,16,16'>" +"<widget name='Headline' " +"height='Globals.Line.Height' " +"/>" +"<widget name='Filename' " +"height='Globals.Line.Height' " +"/>" +"<space size='5' />" +"<widget name='List'/>" +"<layout type='vertical' padding='0,0,16,0'>" +"<layout type='horizontal' padding='0,0,0,0'>" +"<widget name='Cancel' " +"type='Button' " +"/>" +"<widget name='Choose' " +"type='Button' " +"/>" +"</layout>" +"</layout>" +"</layout>" +"</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' " @@ -2316,6 +2376,19 @@ "type='PopUp' " "/>" "</layout>" +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'>" +"<widget name='UpdatesPopupDesc' " +"width='80' " +"height='Globals.Line.Height' " +"textalign='right' " +"/>" +"<widget name='UpdatesPopup' " +"type='PopUp' " +"/>" +"<widget name='UpdatesCheckManuallyButton' " +"type='Button' " +"/>" +"</layout>" "<widget name='KeysButton' " "type='Button' " "/>" @@ -2347,7 +2420,7 @@ "</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' " @@ -2643,7 +2716,7 @@ "</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' " @@ -3105,3 +3178,5 @@ "</layout>" "</dialog>" "</layout_info>" +; +const char *defaultXML[] = { defaultXML1, defaultXML2, defaultXML3, defaultXML4 }; diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip Binary files differindex 1b555a6c27..561f2a5dd3 100644 --- a/gui/themes/scummclassic.zip +++ b/gui/themes/scummclassic.zip diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC index 8f40cb2a7e..7e58285d08 100644 --- a/gui/themes/scummclassic/THEMERC +++ b/gui/themes/scummclassic/THEMERC @@ -1 +1 @@ -[SCUMMVM_STX0.8.20:ScummVM Classic Theme:No Author] +[SCUMMVM_STX0.8.21:ScummVM Classic Theme:No Author] diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index cf8268696d..5172326859 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -49,6 +49,7 @@ <def var = 'Tooltip.YDelta' value = '16'/> <def var = 'Predictive.Button.Width' value = '60' /> + <def var = 'Predictive.ShowDeletePic' value = '0'/> <widget name = 'OptionsLabel' size = '110, Globals.Line.Height' @@ -196,9 +197,32 @@ </layout> </dialog> + <dialog name = 'FileBrowser' overlays = 'screen' inset = '32' shading = 'dim'> + <layout type = 'vertical' padding = '16, 16, 16, 16'> + <widget name = 'Headline' + height = 'Globals.Line.Height' + /> + <widget name = 'Filename' + height = 'Globals.Line.Height' + /> + <space size = '10' /> + <widget name = 'List'/> + <layout type = 'vertical' padding = '0, 0, 16, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </layout> + </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' @@ -483,6 +507,17 @@ type = 'PopUp' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'UpdatesPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'UpdatesPopup' + type = 'PopUp' + /> + <widget name = 'UpdatesCheckManuallyButton' + type = 'Button' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -516,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' @@ -673,7 +708,7 @@ /> </layout> </dialog> - + <dialog name = 'GlobalMenu' overlays = 'screen_center'> <layout type = 'vertical' padding = '16, 16, 16, 16' center = 'true'> <widget name = 'Title' @@ -815,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' @@ -1040,7 +1075,7 @@ width = '180' height = '170' /> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> <widget name = 'NextScreenShotButton' width = '25' height = '25' @@ -1115,15 +1150,15 @@ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'> <widget name = 'AuthorLabel' type = 'EditRecordLabel' - /> + /> <widget name = 'AuthorEdit' type = 'EditRecord' - /> + /> </layout> <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'> <widget name = 'NameLabel' type = 'EditRecordLabel' - /> + /> <widget name = 'NameEdit' type = 'EditRecord' /> @@ -1142,11 +1177,11 @@ /> <widget name = 'OK' type = 'Button' - /> + /> </layout> </layout> </dialog> - + <dialog name = 'ScummHelp' overlays = 'screen_center'> <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'> <widget name = 'Title' @@ -1250,7 +1285,7 @@ <layout type = 'horizontal' padding = '5, 5, 5, 5'> <widget name = 'Word' width = '190' - height = 'Globals.Button.Height' + height = 'Globals.Button.Height' /> <widget name = 'Delete' width = '20' @@ -1315,7 +1350,7 @@ /> </layout> <space size = '5' /> - <layout type = 'horizontal' padding = '3, 3, 3, 3'> + <layout type = 'horizontal' padding = '3, 3, 3, 3'> <widget name = 'Add' width = 'Globals.Predictive.Button.Width' height = 'Globals.Button.Height' diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx index 506657ef31..0013b91ee2 100644 --- a/gui/themes/scummclassic/classic_layout_lowres.stx +++ b/gui/themes/scummclassic/classic_layout_lowres.stx @@ -51,6 +51,7 @@ <def var = 'Predictive.Button.Width' value = '45' /> <def var = 'Predictive.Button.Height' value = '15' /> + <def var = 'Predictive.ShowDeletePic' value = '0'/> <widget name = 'Button' size = '72, 16' @@ -96,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' @@ -193,9 +194,32 @@ </layout> </dialog> + <dialog name = 'FileBrowser' overlays = 'screen' inset = '16' shading = 'dim'> + <layout type = 'vertical' padding = '16, 16, 16, 16'> + <widget name = 'Headline' + height = 'Globals.Line.Height' + /> + <widget name = 'Filename' + height = 'Globals.Line.Height' + /> + <space size = '5' /> + <widget name = 'List'/> + <layout type = 'vertical' padding = '0, 0, 16, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </layout> + </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' @@ -486,6 +510,19 @@ type = 'PopUp' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'UpdatesPopupDesc' + width = '80' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'UpdatesPopup' + type = 'PopUp' + /> + <widget name = 'UpdatesCheckManuallyButton' + type = 'Button' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -519,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' @@ -685,7 +722,7 @@ /> </layout> </dialog> - + <dialog name = 'GlobalMenu' overlays = 'screen_center'> <layout type = 'vertical' padding = '2, 2, 2, 6' center = 'true' spacing='0'> <widget name = 'Title' @@ -826,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' @@ -1086,15 +1123,15 @@ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'> <widget name = 'AuthorLabel' type = 'EditRecordLabel' - /> + /> <widget name = 'AuthorEdit' type = 'EditRecord' - /> + /> </layout> <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'> <widget name = 'NameLabel' type = 'EditRecordLabel' - /> + /> <widget name = 'NameEdit' type = 'EditRecord' /> @@ -1113,7 +1150,7 @@ /> <widget name = 'OK' type = 'Button' - /> + /> </layout> </layout> </dialog> @@ -1220,7 +1257,7 @@ <layout type = 'horizontal' padding = '3, 3, 3, 3'> <widget name = 'Word' width = '120' - height = 'Globals.Button.Height' + height = 'Globals.Button.Height' /> <widget name = 'Delete' width = '20' diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip Binary files differindex c7c585654d..d80c481ffc 100644 --- a/gui/themes/scummmodern.zip +++ b/gui/themes/scummmodern.zip diff --git a/gui/themes/scummmodern/THEMERC b/gui/themes/scummmodern/THEMERC index f4304622cb..dc98bdc00e 100644 --- a/gui/themes/scummmodern/THEMERC +++ b/gui/themes/scummmodern/THEMERC @@ -1 +1 @@ -[SCUMMVM_STX0.8.20:ScummVM Modern Theme:No Author] +[SCUMMVM_STX0.8.21:ScummVM Modern Theme:No Author] diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx index 7e61d6820e..026fa7bc64 100644 --- a/gui/themes/scummmodern/scummmodern_layout.stx +++ b/gui/themes/scummmodern/scummmodern_layout.stx @@ -56,6 +56,7 @@ <def var = 'Tooltip.YDelta' value = '32'/> <def var = 'Predictive.Button.Width' value = '60' /> + <def var = 'Predictive.ShowDeletePic' value = '1'/> <widget name = 'OptionsLabel' size = '115, Globals.Line.Height' @@ -67,7 +68,7 @@ <widget name = 'Button' size = '108, 24' - /> + /> <widget name = 'Slider' size = '128, 18' @@ -210,9 +211,32 @@ </layout> </dialog> + <dialog name = 'FileBrowser' overlays = 'screen' inset = '32' shading = 'dim'> + <layout type = 'vertical' padding = '16, 16, 16, 16'> + <widget name = 'Headline' + height = 'Globals.Line.Height' + /> + <widget name = 'Filename' + height = 'Globals.Line.Height' + /> + <space size = '10' /> + <widget name = 'List'/> + <layout type = 'vertical' padding = '0, 0, 16, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </layout> + </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' @@ -497,6 +521,17 @@ type = 'PopUp' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'UpdatesPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'UpdatesPopup' + type = 'PopUp' + /> + <widget name = 'UpdatesCheckManuallyButton' + type = 'Button' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -530,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' @@ -687,7 +722,7 @@ /> </layout> </dialog> - + <dialog name = 'GlobalMenu' overlays = 'screen_center'> <layout type = 'vertical' padding = '16, 16, 16, 16' center = 'true'> <widget name = 'Logo' @@ -829,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' @@ -1054,7 +1089,7 @@ width = '180' height = '170' /> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> <widget name = 'NextScreenShotButton' width = '25' height = '25' @@ -1130,15 +1165,15 @@ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'> <widget name = 'AuthorLabel' type = 'EditRecordLabel' - /> + /> <widget name = 'AuthorEdit' type = 'EditRecord' - /> + /> </layout> <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'> <widget name = 'NameLabel' type = 'EditRecordLabel' - /> + /> <widget name = 'NameEdit' type = 'EditRecord' /> @@ -1157,11 +1192,11 @@ /> <widget name = 'OK' type = 'Button' - /> + /> </layout> </layout> </dialog> - + <dialog name = 'ScummHelp' overlays = 'screen_center'> <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'> <widget name = 'Title' @@ -1252,7 +1287,7 @@ type = 'Button' /> </layout> - </dialog> + </dialog> <dialog name = 'Predictive' overlays = 'screen_center'> <layout type = 'vertical' padding = '5, 5, 5, 5' center = 'true'> <widget name = 'Headline' @@ -1264,7 +1299,7 @@ <layout type = 'horizontal' padding = '5, 5, 5, 5'> <widget name = 'Word' width = '190' - height = 'Globals.Button.Height' + height = 'Globals.Button.Height' /> <widget name = 'Delete' width = '20' diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx index cee1e4af2b..169e61a9bb 100644 --- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx +++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx @@ -41,6 +41,7 @@ <def var = 'Predictive.Button.Width' value = '45' /> <def var = 'Predictive.Button.Height' value = '15' /> + <def var = 'Predictive.ShowDeletePic' value = '0'/> <widget name = 'Button' size = '72, 16' @@ -94,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' @@ -191,9 +192,32 @@ </layout> </dialog> + <dialog name = 'FileBrowser' overlays = 'screen' inset = '16' shading = 'dim'> + <layout type = 'vertical' padding = '16, 16, 16, 16'> + <widget name = 'Headline' + height = 'Globals.Line.Height' + /> + <widget name = 'Filename' + height = 'Globals.Line.Height' + /> + <space size = '5' /> + <widget name = 'List'/> + <layout type = 'vertical' padding = '0, 0, 16, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </layout> + </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' @@ -484,6 +508,19 @@ type = 'PopUp' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'UpdatesPopupDesc' + width = '80' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'UpdatesPopup' + type = 'PopUp' + /> + <widget name = 'UpdatesCheckManuallyButton' + type = 'Button' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -517,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' @@ -683,7 +720,7 @@ /> </layout> </dialog> - + <dialog name = 'GlobalMenu' overlays = 'screen_center'> <layout type = 'vertical' padding = '4, 4, 4, 4' center = 'true' spacing='2'> <widget name = 'Title' @@ -824,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' @@ -1105,15 +1142,15 @@ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'> <widget name = 'AuthorLabel' type = 'EditRecordLabel' - /> + /> <widget name = 'AuthorEdit' type = 'EditRecord' - /> + /> </layout> <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'> <widget name = 'NameLabel' type = 'EditRecordLabel' - /> + /> <widget name = 'NameEdit' type = 'EditRecord' /> @@ -1132,11 +1169,11 @@ /> <widget name = 'OK' type = 'Button' - /> + /> </layout> </layout> </dialog> - + <dialog name = 'ScummHelp' overlays = 'screen' inset = '8'> <layout type = 'vertical' padding = '8, 8, 8, 8'> <widget name = 'Title' @@ -1237,7 +1274,7 @@ <layout type = 'horizontal' padding = '0, 0, 2, 2'> <widget name = 'Word' width = '120' - height = 'Globals.Button.Height' + height = 'Globals.Button.Height' /> <widget name = 'Delete' width = '20' diff --git a/gui/themes/scummtheme.py b/gui/themes/scummtheme.py index 94dc08f1ef..d5fa4dfca7 100755 --- a/gui/themes/scummtheme.py +++ b/gui/themes/scummtheme.py @@ -35,11 +35,15 @@ def buildAllThemes(): if os.path.isdir(os.path.join('.', f)) and not f[0] == '.': buildTheme(f) -def parseSTX(theme_file, def_file): +def parseSTX(theme_file, def_file, subcount): comm = re.compile("<!--(.*?)-->", re.DOTALL) head = re.compile("<\?(.*?)\?>") strlitcount = 0 + subcount += 1 + + def_file.write(";\n const char *defaultXML" + str(subcount) + " = ") + output = "" for line in theme_file: output += line.rstrip("\r\n\t ").lstrip() @@ -55,8 +59,12 @@ def parseSTX(theme_file, def_file): for line in output.splitlines(): if line and not line.isspace(): strlitcount += len(line) + if strlitcount > 65535: + subcount += 1 + def_file.write(";\n const char *defaultXML" + str(subcount) + " = ") + strlitcount = len(line) def_file.write("\"" + line + "\"\n") - return strlitcount + return subcount def buildDefTheme(themeName): def_file = open("default.inc", "w") @@ -64,8 +72,8 @@ def buildDefTheme(themeName): if not os.path.isdir(themeName): print ("Cannot open default theme dir.") - def_file.write(""" "<?xml version = '1.0'?>"\n""") - strlitcount = 24 + def_file.write("""const char *defaultXML1 = "<?xml version = '1.0'?>"\n""") + subcount = 1 filenames = os.listdir(themeName) filenames.sort() @@ -73,16 +81,16 @@ def buildDefTheme(themeName): filename = os.path.join(themeName, filename) if os.path.isfile(filename) and filename.endswith(".stx"): theme_file = open(filename, "r") - strlitcount += parseSTX(theme_file, def_file) + subcount = parseSTX(theme_file, def_file, subcount) theme_file.close() - def_file.close() + def_file.write(";\nconst char *defaultXML[] = { defaultXML1") + for sub in range(2, subcount + 1): + def_file.write(", defaultXML" + str(sub)) - if strlitcount > 65535: - print("WARNING: default.inc string literal is of length %d which exceeds the" % strlitcount) - print(" maximum length of 65536 that C++ compilers are required to support.") - print(" It is likely that bugs will occur dependent on compiler behaviour.") - print(" To avoid this, reduce the size of the theme.") + def_file.write(" };\n") + + def_file.close() def printUsage(): print ("===============================") diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat Binary files differindex 4225994810..7533d41454 100644 --- a/gui/themes/translations.dat +++ b/gui/themes/translations.dat diff --git a/gui/updates-dialog.cpp b/gui/updates-dialog.cpp new file mode 100644 index 0000000000..b82ecc0402 --- /dev/null +++ b/gui/updates-dialog.cpp @@ -0,0 +1,148 @@ +/* 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/system.h" +#include "common/translation.h" +#include "common/updates.h" +#include "common/config-manager.h" + +#include "gui/updates-dialog.h" +#include "gui/gui-manager.h" +#include "gui/ThemeEval.h" +#include "gui/widgets/popup.h" + +namespace GUI { + +enum { + kYesCmd = 'YES ', + kNoCmd = 'NO ', + kCheckBoxCmd = 'CHK ' +}; + + +UpdatesDialog::UpdatesDialog() : Dialog(30, 20, 260, 124) { + + const int screenW = g_system->getOverlayWidth(); + const int screenH = g_system->getOverlayHeight(); + + int buttonWidth = g_gui.xmlEval()->getVar("Globals.Button.Width", 0); + int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0); + + const char *message = _( + "ScummVM now supports automatic check for updates\n" + "which requires access to the Internet.\n" + "\n" + "Would you like to enable this feature?"); + const char *message2 = _("(You can always enable it in the options dialog on the Misc tab)"); + + // First, determine the size the dialog needs. For this we have to break + // down the string into lines, and taking the maximum of their widths. + // Using this, and accounting for the space the button(s) need, we can set + // the real size of the dialog + Common::Array<Common::String> lines, lines2; + int maxlineWidth = g_gui.getFont().wordWrapText(message, screenW - 2 * 20, lines); + int maxlineWidth2 = g_gui.getFont(ThemeEngine::kFontStyleTooltip).wordWrapText(message2, screenW - 2 * 20, lines2); + + _w = MAX(MAX(maxlineWidth, maxlineWidth2), (2 * buttonWidth) + 10) + 20; + + int lineCount = lines.size() + 1 + lines2.size(); + + _h = 16 + 3 * kLineHeight; + _h += buttonHeight + 8; + + _h += lineCount * kLineHeight; + + // Center the dialog + _x = (screenW - _w) / 2; + _y = (screenH - _h) / 2; + + // Each line is represented by one static text item. + 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 (uint i = 0; i < lines2.size(); i++) { + new StaticTextWidget(this, 10, y, maxlineWidth2, kLineHeight, + lines2[i], Graphics::kTextAlignCenter, 0, ThemeEngine::kFontStyleTooltip); + y += kLineHeight; + } + + y += kLineHeight; + _updatesCheckbox = new CheckboxWidget(this, 10, y, _w, kLineHeight, _("Check for updates automatically"), 0, kCheckBoxCmd); + + y += kLineHeight + 3; + + _updatesPopUp = new PopUpWidget(this, 10, y, _w - 20, g_gui.xmlEval()->getVar("Globals.PopUp.Height", kLineHeight)); + + const int *vals = Common::UpdateManager::getUpdateIntervals(); + + while (*vals != -1) { + _updatesPopUp->appendEntry(Common::UpdateManager::updateIntervalToString(*vals), *vals); + vals++; + } + + _updatesPopUp->setSelectedTag(Common::UpdateManager::kUpdateIntervalOneWeek); + + int yesButtonPos = (_w - (buttonWidth * 2)) / 2; + int noButtonPos = ((_w - (buttonWidth * 2)) / 2) + buttonWidth + 10; + + _yesButton = new ButtonWidget(this, yesButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, + _("Proceed"), 0, kYesCmd, Common::ASCII_RETURN); + _noButton = new ButtonWidget(this, noButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, + _("Cancel"), 0, kNoCmd, Common::ASCII_ESCAPE); + + _updatesPopUp->setEnabled(false); + _yesButton->setEnabled(false); +} + +void UpdatesDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { + if (cmd == kYesCmd) { + ConfMan.setInt("updates_check", _updatesPopUp->getSelectedTag()); + + if (g_system->getUpdateManager()) { + if (_updatesCheckbox->getState() == false || + _updatesPopUp->getSelectedTag() == Common::UpdateManager::kUpdateIntervalNotSupported) { + g_system->getUpdateManager()->setAutomaticallyChecksForUpdates(Common::UpdateManager::kUpdateStateDisabled); + } else { + g_system->getUpdateManager()->setAutomaticallyChecksForUpdates(Common::UpdateManager::kUpdateStateEnabled); + g_system->getUpdateManager()->setUpdateCheckInterval(_updatesPopUp->getSelectedTag()); + } + } + close(); + } else if (cmd == kNoCmd) { + ConfMan.setInt("updates_check", Common::UpdateManager::kUpdateIntervalNotSupported); + g_system->getUpdateManager()->setAutomaticallyChecksForUpdates(Common::UpdateManager::kUpdateStateDisabled); + + close(); + } else if (cmd == kCheckBoxCmd) { + _updatesPopUp->setEnabled(_updatesCheckbox->getState()); + _yesButton->setEnabled(_updatesCheckbox->getState()); + + draw(); + } else { + Dialog::handleCommand(sender, cmd, data); + } +} + +} // End of namespace GUI diff --git a/gui/updates-dialog.h b/gui/updates-dialog.h new file mode 100644 index 0000000000..9c429c960c --- /dev/null +++ b/gui/updates-dialog.h @@ -0,0 +1,54 @@ +/* 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_UPDATES_DIALOG_H +#define GUI_UPDATES_DIALOG_H + +#include "gui/dialog.h" + +namespace GUI { + +class CheckboxWidget; +class CommandSender; +class ButtonWidget; +class PopUpWidget; + +/** + * Wizard for updates opt-in + */ +class UpdatesDialog : public Dialog { +public: + UpdatesDialog(); + virtual ~UpdatesDialog() {} + + void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); + +private: + PopUpWidget *_updatesPopUp; + ButtonWidget *_yesButton; + ButtonWidget *_noButton; + CheckboxWidget *_updatesCheckbox; +}; + +} // End of namespace GUI + +#endif diff --git a/gui/widget.cpp b/gui/widget.cpp index 851774fd70..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; } @@ -229,20 +254,22 @@ Common::String Widget::cleanupHotkey(const Common::String &label) { #pragma mark - -StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip) +StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip, ThemeEngine::FontStyle font) : Widget(boss, x, y, w, h, tooltip), _align(align) { setFlags(WIDGET_ENABLED); _type = kStaticTextWidget; _label = text; + _font = font; } -StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip) +StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip, ThemeEngine::FontStyle font) : Widget(boss, name, tooltip) { setFlags(WIDGET_ENABLED); _type = kStaticTextWidget; _label = text; _align = g_gui.xmlEval()->getWidgetTextHAlign(name); + _font = font; } void StaticTextWidget::setValue(int value) { @@ -263,21 +290,32 @@ 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); + g_gui.theme()->drawTextClip( + Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), + _label, _state, _align, ThemeEngine::kTextInversionNone, 0, true, _font + ); } #pragma mark - ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) : StaticTextWidget(boss, x, y, w, h, cleanupHotkey(label), Graphics::kTextAlignCenter, tooltip), CommandSender(boss), - _cmd(cmd), _hotkey(hotkey), _lastTime(0) { + _cmd(cmd), _hotkey(hotkey), _lastTime(0), _duringPress(false) { if (hotkey == 0) _hotkey = parseHotkey(label); @@ -288,7 +326,7 @@ ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Co ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) : StaticTextWidget(boss, name, cleanupHotkey(label), tooltip), CommandSender(boss), - _cmd(cmd), _hotkey(hotkey), _lastTime(0) { + _cmd(cmd), _hotkey(hotkey), _lastTime(0), _duringPress(false) { if (hotkey == 0) _hotkey = parseHotkey(label); setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG); @@ -296,18 +334,23 @@ ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Co } void ButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) { - if (isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) { - startAnimatePressedState(); + if (isEnabled() && _duringPress && x >= 0 && x < _w && y >= 0 && y < _h) { + setUnpressedState(); sendCommand(_cmd, 0); } + _duringPress = false; } void ButtonWidget::handleMouseDown(int x, int y, int button, int clickCount) { + _duringPress = true; setPressedState(); } 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) { @@ -340,39 +383,17 @@ void ButtonWidget::setHighLighted(bool enable) { draw(); } -void ButtonWidget::handleTickle() { - if (_lastTime) { - uint32 curTime = g_system->getMillis(); - if (curTime - _lastTime > kPressedButtonTime) { - stopAnimatePressedState(); - } - } -} - void ButtonWidget::setPressedState() { - wantTickle(true); setFlags(WIDGET_PRESSED); + clearFlags(WIDGET_HILITED); draw(); } -void ButtonWidget::stopAnimatePressedState() { - wantTickle(false); - _lastTime = 0; +void ButtonWidget::setUnpressedState() { clearFlags(WIDGET_PRESSED); draw(); } -void ButtonWidget::startAnimatePressedState() { - _lastTime = g_system->getMillis(); -} - -void ButtonWidget::wantTickle(bool tickled) { - if (tickled) - ((GUI::Dialog *)_boss)->setTickleWidget(this); - else - ((GUI::Dialog *)_boss)->unSetTickleWidget(); -} - #pragma mark - PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd, uint8 hotkey) @@ -428,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 @@ -441,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); } } @@ -460,9 +481,10 @@ CheckboxWidget::CheckboxWidget(GuiObject *boss, const Common::String &name, cons } void CheckboxWidget::handleMouseUp(int x, int y, int button, int clickCount) { - if (isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) { + if (isEnabled() && _duringPress && x >= 0 && x < _w && y >= 0 && y < _h) { toggleState(); } + _duringPress = false; } void CheckboxWidget::setState(bool state) { @@ -475,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 - @@ -523,9 +545,10 @@ RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, const Common::String &name } void RadiobuttonWidget::handleMouseUp(int x, int y, int button, int clickCount) { - if (isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) { + if (isEnabled() && _duringPress && x >= 0 && x < _w && y >= 0 && y < _h) { toggleState(); } + _duringPress = false; } void RadiobuttonWidget::setState(bool state, bool setGroup) { @@ -543,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; } @@ -611,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) { @@ -688,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); } } @@ -725,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 9891f32b36..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; } @@ -168,9 +170,10 @@ class StaticTextWidget : public Widget { protected: Common::String _label; Graphics::TextAlign _align; + ThemeEngine::FontStyle _font; public: - StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip = 0); - StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip = 0); + StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip = 0, ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold); + StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip = 0, ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold); void setValue(int value); void setLabel(const Common::String &label); const Common::String &getLabel() const { return _label; } @@ -198,19 +201,15 @@ public: void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseDown(int x, int y, int button, int clickCount); - void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } + void handleMouseEntered(int button) { if (_duringPress) { setFlags(WIDGET_PRESSED); } else { setFlags(WIDGET_HILITED); } draw(); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED | WIDGET_PRESSED); draw(); } - void handleTickle(); void setHighLighted(bool enable); void setPressedState(); - void startAnimatePressedState(); - void stopAnimatePressedState(); - - void lostFocusWidget() { stopAnimatePressedState(); } + void setUnpressedState(); protected: void drawWidget(); - void wantTickle(bool tickled); + bool _duringPress; private: uint32 _lastTime; }; diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp index af3e5e9b9a..4f7e584c14 100644 --- a/gui/widgets/editable.cpp +++ b/gui/widgets/editable.cpp @@ -79,7 +79,7 @@ bool EditableWidget::tryInsertChar(byte c, int pos) { void EditableWidget::handleTickle() { uint32 time = g_system->getMillis(); - if (_caretTime < time) { + if (_caretTime < time && isEnabled()) { _caretTime = time + kCaretBlinkTime; drawCaret(_caretVisible); } @@ -90,6 +90,9 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) { bool dirty = false; bool forcecaret = false; + if (!isEnabled()) + return false; + // First remove caret if (_caretVisible) drawCaret(true); @@ -271,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; @@ -300,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 550b1bd153..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) { @@ -62,6 +66,9 @@ void EditTextWidget::reflowLayout() { void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) { + if (!isEnabled()) + return; + // First remove caret if (_caretVisible) drawCaret(true); @@ -90,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(); @@ -98,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 6186492339..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,17 @@ 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) + : Widget(boss, x, y, w, h, tooltip), CommandSender(boss) { + setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_IGNORE_DRAG); + _type = kPopUpWidget; + + _selectedItem = -1; + + _leftPadding = _rightPadding = 0; } void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) { @@ -457,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/popup.h b/gui/widgets/popup.h index 102c7fd258..37ddc276ad 100644 --- a/gui/widgets/popup.h +++ b/gui/widgets/popup.h @@ -58,6 +58,7 @@ protected: public: PopUpWidget(GuiObject *boss, const String &name, const char *tooltip = 0); + PopUpWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0); void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseWheel(int x, int y, int direction); 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(); |
