diff options
author | Eugene Sandulenko | 2016-08-03 14:37:38 +0200 |
---|---|---|
committer | GitHub | 2016-08-03 14:37:38 +0200 |
commit | a00272c62c012ed4f6ee98ada7415064e8faac5a (patch) | |
tree | 1ad50f4d2c7307b1b6cb26f92bafcec406cdd00b | |
parent | 08c881e8eb72072816ab6539dc603f27963cbc65 (diff) | |
parent | ff9b1ccb57fad47b9bb32bb77c83a06c6fd75958 (diff) | |
download | scummvm-rg350-a00272c62c012ed4f6ee98ada7415064e8faac5a.tar.gz scummvm-rg350-a00272c62c012ed4f6ee98ada7415064e8faac5a.tar.bz2 scummvm-rg350-a00272c62c012ed4f6ee98ada7415064e8faac5a.zip |
Merge pull request #796 from blorente/move-macgui
GRAPHICS/WAGE: Extract Mac GUI system.
23 files changed, 1317 insertions, 454 deletions
diff --git a/engines/wage/design.cpp b/engines/wage/design.cpp index 2bfea9df7d..86b325e2b9 100644 --- a/engines/wage/design.cpp +++ b/engines/wage/design.cpp @@ -47,20 +47,20 @@ #include "graphics/managed_surface.h" #include "graphics/primitives.h" +#include "graphics/macgui/macwindowmanager.h" -#include "wage/macwindowmanager.h" #include "wage/design.h" namespace Wage { struct PlotData { Graphics::ManagedSurface *surface; - Patterns *patterns; + Graphics::MacPatterns *patterns; uint fillType; int thickness; Design *design; - PlotData(Graphics::ManagedSurface *s, Patterns *p, int f, int t, Design *d) : + PlotData(Graphics::ManagedSurface *s, Graphics::MacPatterns *p, int f, int t, Design *d) : surface(s), patterns(p), fillType(f), thickness(t), design(d) {} }; @@ -85,7 +85,7 @@ Design::~Design() { delete _surface; } -void Design::paint(Graphics::ManagedSurface *surface, Patterns &patterns, int x, int y) { +void Design::paint(Graphics::ManagedSurface *surface, Graphics::MacPatterns &patterns, int x, int y) { bool needRender = false; if (_surface == NULL) { @@ -141,7 +141,7 @@ void Design::paint(Graphics::ManagedSurface *surface, Patterns &patterns, int x, } } -void Design::render(Patterns &patterns) { +void Design::render(Graphics::MacPatterns &patterns) { Common::MemoryReadStream in(_data, _len); bool needRender = true; @@ -265,7 +265,7 @@ void drawPixelPlain(int x, int y, int color, void *data) { } void Design::drawRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { int16 y1 = in.readSint16BE(); int16 x1 = in.readSint16BE(); int16 y2 = in.readSint16BE(); @@ -294,7 +294,7 @@ void Design::drawRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, } void Design::drawRoundRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { int16 y1 = in.readSint16BE(); int16 x1 = in.readSint16BE(); int16 y2 = in.readSint16BE(); @@ -320,7 +320,7 @@ void Design::drawRoundRect(Graphics::ManagedSurface *surface, Common::ReadStream } void Design::drawPolygon(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { byte ignored = in.readSint16BE(); // ignored @@ -397,7 +397,7 @@ void Design::drawPolygon(Graphics::ManagedSurface *surface, Common::ReadStream & } void Design::drawOval(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { int16 y1 = in.readSint16BE(); int16 x1 = in.readSint16BE(); int16 y2 = in.readSint16BE(); @@ -501,11 +501,11 @@ void Design::drawBitmap(Graphics::ManagedSurface *surface, Common::SeekableReadS tmp.free(); } -void Design::drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType) { drawRect(surface, rect.left, rect.top, rect.right, rect.bottom, thickness, color, patterns, fillType); } -void Design::drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, thickness, nullptr); Graphics::drawLine(x1, y1, x2, y1, kColorBlack, drawPixel, &pd); @@ -515,26 +515,26 @@ void Design::drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, } -void Design::drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType) { +void Design::drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, 1, nullptr); for (int y = rect.top; y <= rect.bottom; y++) Graphics::drawHLine(rect.left, rect.right, y, color, drawPixel, &pd); } -void Design::drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType) { +void Design::drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, 1, nullptr); Graphics::drawRoundRect(rect, arc, color, true, drawPixel, &pd); } -void Design::drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, thickness, nullptr); Graphics::drawHLine(x1, x2, y, color, drawPixel, &pd); } -void Design::drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, thickness, nullptr); Graphics::drawVLine(x, y1, y2, color, drawPixel, &pd); diff --git a/engines/wage/design.h b/engines/wage/design.h index 86225c9224..017fdfc14d 100644 --- a/engines/wage/design.h +++ b/engines/wage/design.h @@ -51,10 +51,15 @@ #include "common/memstream.h" #include "common/rect.h" -#include "wage/macwindowmanager.h" +#include "graphics/nine_patch.h" +#include "graphics/transparent_surface.h" + +#include "graphics/macgui/macwindowmanager.h" namespace Wage { +using namespace Graphics::MacGUIConstants; + class Design { public: Design(Common::SeekableReadStream *data); @@ -68,14 +73,14 @@ public: return _bounds; } - void paint(Graphics::ManagedSurface *canvas, Patterns &patterns, int x, int y); + void paint(Graphics::ManagedSurface *canvas, Graphics::MacPatterns &patterns, int x, int y); bool isPointOpaque(int x, int y); - static void drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType); - static void drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType); - static void drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType); - static void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType); - static void drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType); - static void drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType); + static void drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType); bool isBoundsCalculation() { return _boundsCalculationMode; } void adjustBounds(int16 x, int16 y); @@ -88,15 +93,15 @@ private: bool _boundsCalculationMode; private: - void render(Patterns &patterns); + void render(Graphics::MacPatterns &patterns); void drawRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType); void drawRoundRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType); void drawPolygon(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType); void drawOval(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType); void drawBitmap(Graphics::ManagedSurface *surface, Common::SeekableReadStream &in); }; diff --git a/engines/wage/dialog.cpp b/engines/wage/dialog.cpp index 86080c9a6f..a2013db852 100644 --- a/engines/wage/dialog.cpp +++ b/engines/wage/dialog.cpp @@ -48,8 +48,9 @@ #include "common/system.h" #include "common/events.h" +#include "graphics/macgui/macwindowmanager.h" + #include "wage/wage.h" -#include "wage/macwindowmanager.h" #include "wage/design.h" #include "wage/gui.h" #include "wage/dialog.h" diff --git a/engines/wage/entities.cpp b/engines/wage/entities.cpp index b2babbab4d..28a708b0c3 100644 --- a/engines/wage/entities.cpp +++ b/engines/wage/entities.cpp @@ -146,12 +146,12 @@ void Scene::paint(Graphics::ManagedSurface *surface, int x, int y) { _design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y); for (ObjList::const_iterator it = _objs.begin(); it != _objs.end(); ++it) { - debug(2, "paining Obj: %s, index: %d, type: %d", (*it)->_name.c_str(), (*it)->_index, (*it)->_type); + debug(2, "painting Obj: %s, index: %d, type: %d", (*it)->_name.c_str(), (*it)->_index, (*it)->_type); (*it)->_design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y); } for (ChrList::const_iterator it = _chrs.begin(); it != _chrs.end(); ++it) { - debug(2, "paining Chr: %s", (*it)->_name.c_str()); + debug(2, "painting Chr: %s", (*it)->_name.c_str()); (*it)->_design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y); } } diff --git a/engines/wage/gui-console.cpp b/engines/wage/gui-console.cpp index 8b6fe43a17..1cf98ab991 100644 --- a/engines/wage/gui-console.cpp +++ b/engines/wage/gui-console.cpp @@ -51,12 +51,12 @@ #include "graphics/cursorman.h" #include "graphics/fonts/bdf.h" #include "graphics/palette.h" +#include "graphics/macgui/macwindow.h" +#include "graphics/macgui/macmenu.h" #include "wage/wage.h" #include "wage/design.h" #include "wage/entities.h" -#include "wage/macwindow.h" -#include "wage/macmenu.h" #include "wage/gui.h" #include "wage/world.h" diff --git a/engines/wage/gui.cpp b/engines/wage/gui.cpp index cdc646f649..86c2a9bfad 100644 --- a/engines/wage/gui.cpp +++ b/engines/wage/gui.cpp @@ -49,19 +49,19 @@ #include "common/system.h" #include "graphics/cursorman.h" #include "graphics/primitives.h" +#include "graphics/macgui/macwindowmanager.h" +#include "graphics/macgui/macwindow.h" +#include "graphics/macgui/macmenu.h" #include "wage/wage.h" #include "wage/design.h" #include "wage/entities.h" #include "wage/gui.h" -#include "wage/macwindow.h" -#include "wage/macwindowmanager.h" -#include "wage/macmenu.h" #include "wage/world.h" namespace Wage { -static const MenuData menuSubItems[] = { +static const Graphics::MenuData menuSubItems[] = { { kMenuHighLevel, "File", 0, 0, false }, { kMenuHighLevel, "Edit", 0, 0, false }, { kMenuFile, "New", kMenuActionNew, 0, false }, @@ -168,6 +168,9 @@ Gui::Gui(WageEngine *engine) { _consoleWindow = _wm.addWindow(true, true, true); _consoleWindow->setCallback(consoleWindowCallback, this); + + loadBorders(); + } Gui::~Gui() { @@ -363,4 +366,30 @@ void Gui::executeMenuCommand(int action, Common::String &text) { } } +void Gui::loadBorders() { + // Do not load borders for now + //loadBorder(_sceneWindow, "border_inac.bmp", false); + //loadBorder(_sceneWindow, "border_act.bmp", true); +} + +void Gui::loadBorder(Graphics::MacWindow *target, Common::String filename, bool active) { + Common::File borderfile; + + if (!borderfile.open(filename)) { + debug(1, "Cannot open border file"); + return; + } + + Image::BitmapDecoder bmpDecoder; + Common::SeekableReadStream *stream = borderfile.readStream(borderfile.size()); + if (stream) { + + target->loadBorder(*stream, active, 10, 10, 1, 1); + + borderfile.close(); + + delete stream; + } +} + } // End of namespace Wage diff --git a/engines/wage/gui.h b/engines/wage/gui.h index ba1bb5ef3b..898c7c3162 100644 --- a/engines/wage/gui.h +++ b/engines/wage/gui.h @@ -51,15 +51,25 @@ #include "common/str-array.h" #include "graphics/font.h" #include "graphics/managed_surface.h" +#include "graphics/macgui/macwindowmanager.h" +#include "graphics/macgui/macwindow.h" +#include "graphics/macgui/macmenu.h" +#include "graphics/macgui/macwindowborder.h" + #include "common/events.h" #include "common/rect.h" -#include "wage/macwindow.h" -#include "wage/macwindowmanager.h" +#include "common/file.h" +#include "graphics/pixelformat.h" +#include "image/bmp.h" + +#include "graphics/palette.h" + namespace Wage { -class Menu; +using namespace Graphics::MacWindowConstants; + class Scene; class WageEngine; @@ -67,6 +77,44 @@ enum { kCursorHeight = 12 }; +enum { + kFontStyleBold = 1, + kFontStyleItalic = 2, + kFontStyleUnderline = 4, + kFontStyleOutline = 8, + kFontStyleShadow = 16, + kFontStyleCondensed = 32, + kFontStyleExtended = 64 +}; + +enum { + kMenuHighLevel = -1, + kMenuAbout = 0, + kMenuFile = 1, + kMenuEdit = 2, + kMenuCommands = 3, + kMenuWeapons = 4 +}; + +enum { + kMenuActionAbout, + kMenuActionNew, + kMenuActionOpen, + kMenuActionClose, + kMenuActionSave, + kMenuActionSaveAs, + kMenuActionRevert, + kMenuActionQuit, + + kMenuActionUndo, + kMenuActionCut, + kMenuActionCopy, + kMenuActionPaste, + kMenuActionClear, + + kMenuActionCommand +}; + class Gui { public: Gui(WageEngine *engine); @@ -107,6 +155,9 @@ private: int calcTextX(int x, int textLine); int calcTextY(int y); void updateTextSelection(int x, int y); + + void loadBorders(); + void loadBorder(Graphics::MacWindow *target, Common::String filename, bool active); public: Graphics::ManagedSurface _screen; @@ -121,13 +172,14 @@ public: Scene *_scene; - MacWindowManager _wm; - MacWindow *_sceneWindow; - MacWindow *_consoleWindow; + Graphics::MacWindowManager _wm; + Graphics::MacWindow *_sceneWindow; + Graphics::MacWindow *_consoleWindow; private: + Graphics::ManagedSurface _console; - Menu *_menu; + Graphics::Menu *_menu; bool _sceneDirty; bool _consoleDirty; diff --git a/engines/wage/macwindow.h b/engines/wage/macwindow.h deleted file mode 100644 index 4c6e9efeff..0000000000 --- a/engines/wage/macwindow.h +++ /dev/null @@ -1,161 +0,0 @@ -/* 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. - * - * MIT License: - * - * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef WAGE_MACWINDOW_H -#define WAGE_MACWINDOW_H - -#include "graphics/managed_surface.h" - -namespace Wage { - -class MacWindowManager; - -enum WindowType { - kWindowUnknown, - kWindowWindow, - kWindowMenu -}; - -enum { - kBorderWidth = 17 -}; - -enum WindowClick { - kBorderNone = 0, - kBorderScrollUp, - kBorderScrollDown, - kBorderCloseButton, - kBorderInner, - kBorderBorder, - kBorderResizeButton -}; - -class BaseMacWindow { -public: - BaseMacWindow(int id, bool editable, MacWindowManager *wm); - virtual ~BaseMacWindow() {} - - const Common::Rect &getDimensions() { return _dims; } - int getId() { return _id; } - WindowType getType() { return _type; } - bool isEditable() { return _editable; } - Graphics::ManagedSurface *getSurface() { return &_surface; } - virtual void setActive(bool active) = 0; - void setDirty(bool dirty) { _contentIsDirty = dirty; } - - virtual bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false) = 0; - virtual bool processEvent(Common::Event &event) = 0; - - virtual bool hasAllFocus() = 0; - - void setCallback(bool (*callback)(WindowClick, Common::Event &, void *), void *data) { _callback = callback; _dataPtr = data; } - -protected: - int _id; - WindowType _type; - - bool _editable; - - Graphics::ManagedSurface _surface; - bool _contentIsDirty; - - Common::Rect _dims; - - bool (*_callback)(WindowClick, Common::Event &, void *); - void *_dataPtr; - - MacWindowManager *_wm; -}; - -class MacWindow : public BaseMacWindow { -public: - MacWindow(int id, bool scrollable, bool resizable, bool editable, MacWindowManager *wm); - virtual ~MacWindow(); - void move(int x, int y); - void resize(int w, int h); - void setDimensions(const Common::Rect &r); - const Common::Rect &getInnerDimensions() { return _innerDims; } - - bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false); - - void setActive(bool active); - void setTitle(Common::String &title) { _title = title; } - void setHighlight(WindowClick highlightedPart); - void setScroll(float scrollPos, float scrollSize); - bool processEvent(Common::Event &event); - bool hasAllFocus() { return _beingDragged || _beingResized; } - -private: - void drawBorder(); - void drawBox(Graphics::ManagedSurface *g, int x, int y, int w, int h); - void fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color); - const Graphics::Font *getTitleFont(); - void updateInnerDims(); - WindowClick isInBorder(int x, int y); - -private: - Graphics::ManagedSurface _borderSurface; - Graphics::ManagedSurface _composeSurface; - bool _scrollable; - bool _resizable; - bool _active; - bool _borderIsDirty; - - bool _beingDragged, _beingResized; - int _draggedX, _draggedY; - - WindowClick _highlightedPart; - float _scrollPos, _scrollSize; - - Common::Rect _innerDims; - - Common::String _title; -}; - -} // End of namespace Wage - -#endif diff --git a/engines/wage/macwindowmanager.h b/engines/wage/macwindowmanager.h deleted file mode 100644 index 13f85cddd4..0000000000 --- a/engines/wage/macwindowmanager.h +++ /dev/null @@ -1,141 +0,0 @@ -/* 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. - * - * MIT License: - * - * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef WAGE_MACWINDOWMANAGER_H -#define WAGE_MACWINDOWMANAGER_H - -#include "common/array.h" -#include "common/list.h" -#include "common/events.h" -#include "common/archive.h" - -#include "graphics/fontman.h" - -namespace Graphics { -class ManagedSurface; -} - -namespace Wage { - -enum { - kDesktopArc = 7 -}; - -enum { - kColorBlack = 0, - kColorGray = 1, - kColorWhite = 2, - kColorGreen = 3, - kColorGreen2 = 4 -}; - -enum { - kPatternSolid = 1, - kPatternStripes = 2, - kPatternCheckers = 3, - kPatternCheckers2 = 4 -}; - -class BaseMacWindow; -class MacWindow; -class Menu; - -typedef Common::Array<byte *> Patterns; - -class MacWindowManager { -public: - MacWindowManager(); - ~MacWindowManager(); - - void setScreen(Graphics::ManagedSurface *screen) { _screen = screen; } - bool hasBuiltInFonts() { return _builtInFonts; } - const Graphics::Font *getFont(const char *name, Graphics::FontManager::FontUsage fallback); - - MacWindow *addWindow(bool scrollable, bool resizable, bool editable); - Menu *addMenu(); - void setActive(int id); - - void setFullRefresh(bool redraw) { _fullRefresh = true; } - - void draw(); - - bool processEvent(Common::Event &event); - - BaseMacWindow *getWindow(int id) { return _windows[id]; } - - Patterns &getPatterns() { return _patterns; } - void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color); - - void pushArrowCursor(); - void popCursor(); - -private: - void drawDesktop(); - void loadFonts(); - -private: - Graphics::ManagedSurface *_screen; - - Common::List<BaseMacWindow *> _windowStack; - Common::Array<BaseMacWindow *> _windows; - - int _lastId; - int _activeWindow; - - bool _fullRefresh; - - Patterns _patterns; - - Menu *_menu; - - bool _builtInFonts; - bool _cursorIsArrow; -}; - -} // End of namespace Wage - -#endif diff --git a/engines/wage/module.mk b/engines/wage/module.mk index 1f397b5a71..be148dd439 100644 --- a/engines/wage/module.mk +++ b/engines/wage/module.mk @@ -9,9 +9,6 @@ MODULE_OBJS := \ entities.o \ gui.o \ gui-console.o \ - macmenu.o \ - macwindow.o \ - macwindowmanager.o \ randomhat.o \ saveload.o \ script.o \ diff --git a/engines/wage/world.cpp b/engines/wage/world.cpp index 286ecddf4d..acc2a83d97 100644 --- a/engines/wage/world.cpp +++ b/engines/wage/world.cpp @@ -75,7 +75,7 @@ World::World(WageEngine *engine) { _engine = engine; - _patterns = new Patterns; + _patterns = new Graphics::MacPatterns; } World::~World() { diff --git a/engines/wage/world.h b/engines/wage/world.h index 918616c9c1..5c1aaf319e 100644 --- a/engines/wage/world.h +++ b/engines/wage/world.h @@ -49,10 +49,13 @@ #define WAGE_WORLD_H #include "wage/entities.h" -#include "wage/macwindowmanager.h" +#include "graphics/macgui/macwindowmanager.h" namespace Wage { +// Import the enum definitions +using Graphics::MacPatterns; + class Script; class Sound; @@ -89,7 +92,7 @@ public: ObjArray _orderedObjs; ChrArray _orderedChrs; Common::Array<Sound *> _orderedSounds; - Patterns *_patterns; + Graphics::MacPatterns *_patterns; Scene *_storageScene; Chr *_player; int _signature; diff --git a/engines/wage/macmenu.cpp b/graphics/macgui/macmenu.cpp index b29903c674..6169b3e3cd 100644 --- a/engines/wage/macmenu.cpp +++ b/graphics/macgui/macmenu.cpp @@ -50,12 +50,11 @@ #include "graphics/primitives.h" #include "graphics/font.h" +#include "graphics/macgui/macwindowmanager.h" +#include "graphics/macgui/macwindow.h" +#include "graphics/macgui/macmenu.h" -#include "wage/macwindowmanager.h" -#include "wage/macwindow.h" -#include "wage/macmenu.h" - -namespace Wage { +namespace Graphics { enum { kMenuHeight = 20, @@ -67,6 +66,25 @@ enum { kMenuItemHeight = 20 }; +enum { + kMenuHighLevel = -1 +}; + +enum { + kFontStyleBold = 1, + kFontStyleItalic = 2, + kFontStyleUnderline = 4, + kFontStyleOutline = 8, + kFontStyleShadow = 16, + kFontStyleCondensed = 32, + kFontStyleExtended = 64 +}; + +enum { + kMenuActionCommand +}; + + struct MenuSubItem { Common::String text; int action; @@ -93,7 +111,7 @@ Menu::Menu(int id, const Common::Rect &bounds, MacWindowManager *wm) : BaseMacWindow(id, false, wm) { _font = getMenuFont(); - _screen.create(bounds.width(), bounds.height(), Graphics::PixelFormat::createFormatCLUT8()); + _screen.create(bounds.width(), bounds.height(), PixelFormat::createFormatCLUT8()); _bbox.left = 0; _bbox.top = 0; @@ -107,7 +125,7 @@ Menu::Menu(int id, const Common::Rect &bounds, MacWindowManager *wm) _ccallback = NULL; _cdata = NULL; - _tempSurface.create(_screen.w, _font->getFontHeight(), Graphics::PixelFormat::createFormatCLUT8()); + _tempSurface.create(_screen.w, _font->getFontHeight(), PixelFormat::createFormatCLUT8()); } Menu::~Menu() { @@ -250,8 +268,8 @@ void Menu::createSubMenuFromString(int id, const char *str) { calcMenuBounds(menu); } -const Graphics::Font *Menu::getMenuFont() { - return _wm->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); +const Font *Menu::getMenuFont() { + return _wm->getFont("Chicago-12", FontManager::kBigGUIFont); } const char *Menu::getAcceleratorString(MenuSubItem *item, const char *prefix) { @@ -299,17 +317,17 @@ void Menu::calcMenuBounds(MenuItem *menu) { } static void drawPixelPlain(int x, int y, int color, void *data) { - Graphics::ManagedSurface *surface = (Graphics::ManagedSurface *)data; + ManagedSurface *surface = (ManagedSurface *)data; if (x >= 0 && x < surface->w && y >= 0 && y < surface->h) *((byte *)surface->getBasePtr(x, y)) = (byte)color; } -static void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color) { - Graphics::drawRoundRect(rect, arc, color, true, drawPixelPlain, surface); +static void drawFilledRoundRect(ManagedSurface *surface, Common::Rect &rect, int arc, int color) { + drawRoundRect(rect, arc, color, true, drawPixelPlain, surface); } -bool Menu::draw(Graphics::ManagedSurface *g, bool forceRedraw) { +bool Menu::draw(ManagedSurface *g, bool forceRedraw) { Common::Rect r(_bbox); if (!_contentIsDirty && !forceRedraw) @@ -385,7 +403,7 @@ void Menu::renderSubmenu(MenuItem *menu) { } if (!text.empty()) { - Graphics::ManagedSurface *s = &_screen; + ManagedSurface *s = &_screen; int tx = x, ty = y; if (!menu->subitems[i]->enabled) { diff --git a/engines/wage/macmenu.h b/graphics/macgui/macmenu.h index e73e4c48a9..7114066ae6 100644 --- a/engines/wage/macmenu.h +++ b/graphics/macgui/macmenu.h @@ -45,52 +45,14 @@ * */ -#ifndef WAGE_MACMENU_H -#define WAGE_MACMENU_H +#ifndef GRAPHICS_MACGUI_MACMENU_H +#define GRAPHICS_MACGUI_MACMENU_H -namespace Wage { +namespace Graphics { struct MenuItem; struct MenuSubItem; -enum { - kFontStyleBold = 1, - kFontStyleItalic = 2, - kFontStyleUnderline = 4, - kFontStyleOutline = 8, - kFontStyleShadow = 16, - kFontStyleCondensed = 32, - kFontStyleExtended = 64 -}; - -enum { - kMenuHighLevel = -1, - kMenuAbout = 0, - kMenuFile = 1, - kMenuEdit = 2, - kMenuCommands = 3, - kMenuWeapons = 4 -}; - -enum { - kMenuActionAbout, - kMenuActionNew, - kMenuActionOpen, - kMenuActionClose, - kMenuActionSave, - kMenuActionSaveAs, - kMenuActionRevert, - kMenuActionQuit, - - kMenuActionUndo, - kMenuActionCut, - kMenuActionCopy, - kMenuActionPaste, - kMenuActionClear, - - kMenuActionCommand -}; - struct MenuData { int menunum; const char *title; @@ -114,7 +76,7 @@ public: void createSubMenuFromString(int id, const char *string); void clearSubMenu(int id); - bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false); + bool draw(ManagedSurface *g, bool forceRedraw = false); bool processEvent(Common::Event &event); void enableCommand(int menunum, int action, bool state); @@ -126,11 +88,11 @@ public: Common::Rect _bbox; private: - Graphics::ManagedSurface _screen; - Graphics::ManagedSurface _tempSurface; + ManagedSurface _screen; + ManagedSurface _tempSurface; private: - const Graphics::Font *getMenuFont(); + const Font *getMenuFont(); const char *getAcceleratorString(MenuSubItem *item, const char *prefix); int calculateMenuWidth(MenuItem *menu); void calcMenuBounds(MenuItem *menu); @@ -145,7 +107,7 @@ private: Common::Array<MenuItem *> _items; - const Graphics::Font *_font; + const Font *_font; bool _menuActivated; @@ -156,6 +118,6 @@ private: void *_cdata; }; -} // End of namespace Wage +} // End of namespace Graphics #endif diff --git a/engines/wage/macwindow.cpp b/graphics/macgui/macwindow.cpp index db8ef38c39..dbb600ba82 100644 --- a/engines/wage/macwindow.cpp +++ b/graphics/macgui/macwindow.cpp @@ -48,11 +48,11 @@ #include "graphics/font.h" #include "graphics/primitives.h" #include "common/events.h" +#include "graphics/macgui/macwindowmanager.h" +#include "graphics/macgui/macwindow.h" +#include "image/bmp.h" -#include "wage/macwindow.h" -#include "wage/macwindowmanager.h" - -namespace Wage { +namespace Graphics { BaseMacWindow::BaseMacWindow(int id, bool editable, MacWindowManager *wm) : _id(id), _editable(editable), _wm(wm) { @@ -79,13 +79,17 @@ MacWindow::MacWindow(int id, bool scrollable, bool resizable, bool editable, Mac _draggedX = _draggedY = 0; _type = kWindowWindow; + + _closeable = false; + + _borderWidth = kBorderWidth; } MacWindow::~MacWindow() { } -const Graphics::Font *MacWindow::getTitleFont() { - return _wm->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); +const Font *MacWindow::getTitleFont() { + return _wm->getFont("Chicago-12", FontManager::kBigGUIFont); } void MacWindow::setActive(bool active) { @@ -96,16 +100,18 @@ void MacWindow::setActive(bool active) { _borderIsDirty = true; } +bool MacWindow::isActive() { return _active; } + void MacWindow::resize(int w, int h) { if (_surface.w == w && _surface.h == h) return; _surface.free(); - _surface.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); + _surface.create(w, h, PixelFormat::createFormatCLUT8()); _borderSurface.free(); - _borderSurface.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); + _borderSurface.create(w, h, PixelFormat::createFormatCLUT8()); _composeSurface.free(); - _composeSurface.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); + _composeSurface.create(w, h, PixelFormat::createFormatCLUT8()); _dims.setWidth(w); _dims.setHeight(h); @@ -134,7 +140,7 @@ void MacWindow::setDimensions(const Common::Rect &r) { _contentIsDirty = true; } -bool MacWindow::draw(Graphics::ManagedSurface *g, bool forceRedraw) { +bool MacWindow::draw(ManagedSurface *g, bool forceRedraw) { if (!_borderIsDirty && !_contentIsDirty && !forceRedraw) return false; @@ -152,6 +158,7 @@ bool MacWindow::draw(Graphics::ManagedSurface *g, bool forceRedraw) { return true; } + #define ARROW_W 12 #define ARROW_H 6 const int arrowPixels[ARROW_H][ARROW_W] = { @@ -163,7 +170,7 @@ const int arrowPixels[ARROW_H][ARROW_W] = { {1,1,1,1,1,1,1,1,1,1,1,1}}; static void drawPixelInverted(int x, int y, int color, void *data) { - Graphics::ManagedSurface *surface = (Graphics::ManagedSurface *)data; + ManagedSurface *surface = (ManagedSurface *)data; if (x >= 0 && x < surface->w && y >= 0 && y < surface->h) { byte *p = (byte *)surface->getBasePtr(x, y); @@ -173,26 +180,59 @@ static void drawPixelInverted(int x, int y, int color, void *data) { } void MacWindow::updateInnerDims() { - _innerDims = _dims; - _innerDims.grow(-kBorderWidth); + if (_macBorder.hasBorder(_active) && _macBorder.hasOffsets()) { + _innerDims = Common::Rect( + _dims.left + _macBorder.getOffset(kBorderOffsetLeft), + _dims.top + _macBorder.getOffset(kBorderOffsetTop), + _dims.right - _macBorder.getOffset(kBorderOffsetRight), + _dims.bottom - _macBorder.getOffset(kBorderOffsetBottom)); + } else { + _innerDims = _dims; + _innerDims.grow(-kBorderWidth); + } } void MacWindow::drawBorder() { _borderIsDirty = false; + ManagedSurface *g = &_borderSurface; + + if (_macBorder.hasBorder(_active)) { + drawBorderFromSurface(g); + } else { + drawSimpleBorder(g); + } +} + +void MacWindow::prepareBorderSurface(ManagedSurface *g) { + // We draw rect with outer kColorGreen2 and inner kColorGreen, so on 2 passes we cut out + // scene by external shape of the border + int sz = kBorderWidth / 2; + int width = g->w; + int height = g->h; + g->clear(kColorGreen2); + g->fillRect(Common::Rect(sz, sz, width - sz, height - sz), kColorGreen); +} + +void MacWindow::drawBorderFromSurface(ManagedSurface *g) { + g->clear(kColorGreen2); + Common::Rect inside = _innerDims; + inside.moveTo(_macBorder.getOffset(kBorderOffsetLeft), _macBorder.getOffset(kBorderOffsetTop)); + g->fillRect(inside, kColorGreen); + + _macBorder.blitBorderInto(_borderSurface, _active); +} + +void MacWindow::drawSimpleBorder(ManagedSurface *g) { + bool active = _active, scrollable = _scrollable, closeable = _active, drawTitle = !_title.empty(); const int size = kBorderWidth; int x = 0; int y = 0; int width = _borderSurface.w; int height = _borderSurface.h; - Graphics::ManagedSurface *g = &_borderSurface; - // We draw rect with outer kColorGreen2 and inner kColorGreen, so on 2 passes we cut out - // scene by external shape of the border - int sz = kBorderWidth / 2; - g->clear(kColorGreen2); - g->fillRect(Common::Rect(sz, sz, width - sz, height - sz), kColorGreen); + prepareBorderSurface(g); drawBox(g, x, y, size, size); drawBox(g, x + width - size - 1, y, size, size); @@ -275,15 +315,42 @@ void MacWindow::setScroll(float scrollPos, float scrollSize) { _borderIsDirty = true; } +void MacWindow::loadBorder(Common::SeekableReadStream &file, bool active, int lo, int ro, int to, int bo) { + Image::BitmapDecoder bmpDecoder; + Graphics::Surface source; + Graphics::TransparentSurface *surface = new Graphics::TransparentSurface(); + + bmpDecoder.loadStream(file); + source = *(bmpDecoder.getSurface()); + + source.convertToInPlace(surface->getSupportedPixelFormat(), bmpDecoder.getPalette()); + surface->create(source.w, source.h, source.format); + surface->copyFrom(source); + surface->applyColorKey(255, 0, 255, false); -void MacWindow::drawBox(Graphics::ManagedSurface *g, int x, int y, int w, int h) { + if (active) + _macBorder.addActiveBorder(*surface); + else + _macBorder.addInactiveBorder(*surface); + + if (!_macBorder.hasOffsets()) + _macBorder.setOffsets(lo, ro, to, bo); + + updateInnerDims(); +} + +void MacWindow::setCloseable(bool closeable) { + _closeable = closeable; +} + +void MacWindow::drawBox(ManagedSurface *g, int x, int y, int w, int h) { Common::Rect r(x, y, x + w + 1, y + h + 1); g->fillRect(r, kColorWhite); g->frameRect(r, kColorBlack); } -void MacWindow::fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color) { +void MacWindow::fillRect(ManagedSurface *g, int x, int y, int w, int h, int color) { Common::Rect r(x, y, x + w, y + h); g->fillRect(r, color); @@ -293,18 +360,54 @@ WindowClick MacWindow::isInBorder(int x, int y) { if (_innerDims.contains(x, y)) return kBorderInner; - if (x >= _innerDims.left - kBorderWidth && x < _innerDims.left && y >= _innerDims.top - kBorderWidth && y < _innerDims.top) + if (isInCloseButton(x, y)) return kBorderCloseButton; if (_resizable) - if (x >= _innerDims.right && x < _innerDims.right + kBorderWidth && y >= _innerDims.bottom && y < _innerDims.bottom + kBorderWidth) + if (isInResizeButton(x, y)) return kBorderResizeButton; - if (_scrollable && x >= _innerDims.right && x < _innerDims.right + kBorderWidth) { - if (y < _innerDims.top - kBorderWidth) + if (_scrollable) + return isInScroll(x, y); + + return kBorderBorder; +} + +bool MacWindow::isInCloseButton(int x, int y) { + int bLeft = kBorderWidth; + int bTop = kBorderWidth; + if (_macBorder.hasOffsets()) { + bLeft = _macBorder.getOffset(kBorderOffsetLeft); + bTop = _macBorder.getOffset(kBorderOffsetTop); + } + return (x >= _innerDims.left - bLeft && x < _innerDims.left && y >= _innerDims.top - bTop && y < _innerDims.top); +} + +bool MacWindow::isInResizeButton(int x, int y) { + int bRight = kBorderWidth; + int bBottom = kBorderWidth; + if (_macBorder.hasOffsets()) { + bRight = _macBorder.getOffset(kBorderOffsetRight); + bBottom = _macBorder.getOffset(kBorderOffsetBottom); + } + return (x >= _innerDims.right && x < _innerDims.right + bRight && y >= _innerDims.bottom && y < _innerDims.bottom + bBottom); +} + +WindowClick MacWindow::isInScroll(int x, int y) { + int bTop = kBorderWidth; + int bRight = kBorderWidth; + int bBottom = kBorderWidth; + if (_macBorder.hasOffsets()) { + bTop = _macBorder.getOffset(kBorderOffsetTop); + bRight = _macBorder.getOffset(kBorderOffsetRight); + bBottom = _macBorder.getOffset(kBorderOffsetBottom); + } + + if (x >= _innerDims.right && x < _innerDims.right + bRight) { + if (y < _innerDims.top - bTop) return kBorderBorder; - if (y >= _innerDims.bottom + kBorderWidth) + if (y >= _innerDims.bottom + bBottom) return kBorderBorder; if (y >= _innerDims.top + _innerDims.height() / 2) @@ -313,6 +416,19 @@ WindowClick MacWindow::isInBorder(int x, int y) { return kBorderScrollUp; } + if (y >= _innerDims.bottom && y < _innerDims.bottom + bBottom) { + if (x < _innerDims.left - bTop) + return kBorderBorder; + + if (x >= _innerDims.right + bRight) + return kBorderBorder; + + if (x >= _innerDims.left + _innerDims.width() / 2) + return kBorderScrollRight; + + return kBorderScrollLeft; + } + return kBorderBorder; } @@ -332,8 +448,8 @@ bool MacWindow::processEvent(Common::Event &event) { } if (_beingResized) { - resize(MAX(kBorderWidth * 4, _dims.width() + event.mouse.x - _draggedX), - MAX(kBorderWidth * 4, _dims.height() + event.mouse.y - _draggedY)); + resize(MAX(_borderWidth * 4, _dims.width() + event.mouse.x - _draggedX), + MAX(_borderWidth * 4, _dims.height() + event.mouse.y - _draggedY)); _draggedX = event.mouse.x; _draggedY = event.mouse.y; @@ -359,6 +475,10 @@ bool MacWindow::processEvent(Common::Event &event) { _draggedY = event.mouse.y; } + if (click == kBorderCloseButton && _closeable) { + _wm->removeWindow(this); + } + break; case Common::EVENT_LBUTTONUP: _beingDragged = false; diff --git a/graphics/macgui/macwindow.h b/graphics/macgui/macwindow.h new file mode 100644 index 0000000000..c40c1a4a38 --- /dev/null +++ b/graphics/macgui/macwindow.h @@ -0,0 +1,350 @@ +/* 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. + * + * MIT License: + * + * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef GRAPHICS_MACGUI_MACWINDOW_H +#define GRAPHICS_MACGUI_MACWINDOW_H + +#include "graphics/managed_surface.h" +#include "graphics/transparent_surface.h" +#include "graphics/nine_patch.h" +#include "graphics/palette.h" + +#include "graphics/macgui/macwindowborder.h" + +namespace Graphics { + +class MacWindowManager; +class MacWindowBorder; + +namespace MacWindowConstants { +enum WindowType { + kWindowUnknown, + kWindowWindow, + kWindowMenu +}; + +enum { + kBorderWidth = 17 +}; + +enum WindowClick { + kBorderNone = 0, + kBorderScrollUp, + kBorderScrollDown, + kBorderScrollLeft, + kBorderScrollRight, + kBorderCloseButton, + kBorderInner, + kBorderBorder, + kBorderResizeButton +}; +} +using namespace MacWindowConstants; + +/** + * Abstract class that defines common functionality for all window classes. + * It supports event callbacks and drawing. + */ +class BaseMacWindow { +public: + /** + * Base constructor. + * @param id ID of the window. + * @param editable True if the window is editable. + * @param wm Pointer to the MacWindowManager that owns the window. + */ + BaseMacWindow(int id, bool editable, MacWindowManager *wm); + virtual ~BaseMacWindow() {} + + /** + * Accessor method for the complete dimensions of the window. + * @return Dimensions of the window (including border) relative to the WM's screen. + */ + const Common::Rect &getDimensions() { return _dims; } + + /** + * Accessor method to the id of the window. + * @return The id set in the constructor. + */ + int getId() { return _id; } + + /** + * Accessor method to the type of window. + * Each subclass must indicate it's type. + * @return The type of the window. + */ + WindowType getType() { return _type; } + + /** + * Accessor method to check whether the window is editable (e.g. for resizing). + * @return True if the window is editable as indicated in the constructor. + */ + bool isEditable() { return _editable; } + + /** + * Method to access the entire surface of the window (e.g. to draw an image). + * @return A pointer to the entire surface of the window. + */ + ManagedSurface *getSurface() { return &_surface; } + + /** + * Abstract method for indicating whether the window is active or inactive. + * Used by the WM to handle focus on windows, etc. + * @param active Desired state of the window. + */ + virtual void setActive(bool active) = 0; + + /** + * Method for marking the window for redraw. + * @param dirty True if the window needs to be redrawn. + */ + void setDirty(bool dirty) { _contentIsDirty = dirty; } + + /** + * Method called to draw the window into the target surface. + * This method is most often called by the WM, and relies on + * the window being marked as dirty unless otherwise specified. + * @param g Surface on which to draw the window. + * @param forceRedraw It's behavior depends on the subclass. + */ + virtual bool draw(ManagedSurface *g, bool forceRedraw = false) = 0; + + /** + * Method called by the WM when there is an event concerning the window. + * Note that depending on the subclass of the window, it might not be called + * if the window is not active. + * @param event Event to be processed. + * @return true If the event was successfully consumed and processed. + */ + virtual bool processEvent(Common::Event &event) = 0; + + virtual bool hasAllFocus() = 0; + + /** + * Set the callback that will be used when an event needs to be processed. + * @param callback A function pointer to a function that accepts: + * - A WindowClick, the pert of the window that was clicked. + * - The event to be processed. + * - Any additional required data (e.g. the engine's GUI). + */ + void setCallback(bool (*callback)(WindowClick, Common::Event &, void *), void *data) { _callback = callback; _dataPtr = data; } + +protected: + int _id; + WindowType _type; + + bool _editable; + + ManagedSurface _surface; + bool _contentIsDirty; + + Common::Rect _dims; + + bool (*_callback)(WindowClick, Common::Event &, void *); + void *_dataPtr; + + MacWindowManager *_wm; +}; + +/** + * An implementation of an ordinary window in the Mac interface. + * It supports custom resizing, scrolling, borders, etc. + */ +class MacWindow : public BaseMacWindow { +public: + /** + * Construct a simple window, with the default settings. + * Note that the scroll must be implemented in the event handling, + * even if the scrollable flag is set to true. + * @param id See BaseMacWindow. + * @param scrollable True if the window can be scrolled. + * @param resizable True if the window can be resized. + * @param editable See BaseMacWindow. + * @param wm See BaseMacWindow. + */ + MacWindow(int id, bool scrollable, bool resizable, bool editable, MacWindowManager *wm); + virtual ~MacWindow(); + + /** + * Change the window's location to fixed coordinates (not delta). + * @param x New left position of the window relative to the WM's screen. + * @param y New top position of the window relative to the WM's screen. + */ + void move(int x, int y); + + /* + * Change the width and the height of the window. + * @param w New width of the window. + * @param h New height of the window. + */ + void resize(int w, int h); + + /** + * Change the dimensions of the window ([0, 0, 0, 0] by default). + * Note that this can be used to update both the position and the size + * of the window, although move() and resize() might be more comfortable. + * @param r The desired dimensions of the window. + */ + void setDimensions(const Common::Rect &r); + + /** + * Accessor to retrieve the dimensions of the inner surface of the window + * (i.e. without taking borders into account). + * Note that the returned dimensions' position is relative to the WM's + * screen, just like in getDimensions(). + * @return The inner dimensions of the window. + */ + const Common::Rect &getInnerDimensions() { return _innerDims; } + + /** + * Similar to that described in BaseMacWindow. + * @param g See BaseMacWindow. + * @param forceRedraw If true, the borders are guarranteed to redraw. + */ + bool draw(ManagedSurface *g, bool forceRedraw = false); + + /** + * Mutator to change the active state of the window. + * Most often called from the WM. + * @param active Target state. + */ + void setActive(bool active); + /** + * Accessor to determine whether a window is active. + * @return True if the window is active. + */ + bool isActive(); + + /** + * Mutator to change the title of the window. + * @param title Target title of the window. + */ + void setTitle(Common::String &title) { _title = title; } + /** + * Highlight the target part of the window. + * Used for the default borders. + * @param highlightedPart Part to be highlighted. + */ + void setHighlight(WindowClick highlightedPart); + /** + * Set the scroll poisition. + * @param scrollPos Target scroll position. + * @param scrollSize Size of the scrolling bar. + */ + void setScroll(float scrollPos, float scrollSize); + /** + * See BaseMacWindow. + */ + bool processEvent(Common::Event &event); + bool hasAllFocus() { return _beingDragged || _beingResized; } + + /** + * Set arbitrary border from a BMP data stream, with custom border offsets. + * Note that the BMP has to be 9patch compliant. For examples, go to: + * https://github.com/blorente/MacVenture-Extract-Guide/tree/master/borders + * @param file The BMP data stream with the desired border. + * @param active Whether the border corresponds with the active state of the window. + * @param lo Width of the left side of the border, in pixels. + * @param ro Width of the right side of the border, in pixels. + * @param to Width of the top side of the border, in pixels. + * @param bo Width of the bottom side of the border, in pixels. + */ + void loadBorder(Common::SeekableReadStream &file, bool active, int lo, int ro, int to, int bo); + //void setBorder(TransparentSurface &border, bool active); + + /** + * Indicate whether the window can be closed (false by default). + * @param closeable True if the window can be closed. + */ + void setCloseable(bool closeable); + +private: + void drawBorder(); + void prepareBorderSurface(ManagedSurface *g); + void drawSimpleBorder(ManagedSurface *g); + void drawBorderFromSurface(ManagedSurface *g); + void drawBox(ManagedSurface *g, int x, int y, int w, int h); + void fillRect(ManagedSurface *g, int x, int y, int w, int h, int color); + const Font *getTitleFont(); + void updateInnerDims(); + WindowClick isInBorder(int x, int y); + + bool isInCloseButton(int x, int y); + bool isInResizeButton(int x, int y); + WindowClick isInScroll(int x, int y); + +private: + ManagedSurface _borderSurface; + ManagedSurface _composeSurface; + + MacWindowBorder _macBorder; + + bool _scrollable; + bool _resizable; + bool _active; + bool _borderIsDirty; + + bool _closeable; + + int _borderWidth; + + bool _beingDragged, _beingResized; + int _draggedX, _draggedY; + + WindowClick _highlightedPart; + float _scrollPos, _scrollSize; + + Common::Rect _innerDims; + + Common::String _title; +}; + + + +} // End of namespace Graphics + +#endif diff --git a/graphics/macgui/macwindowborder.cpp b/graphics/macgui/macwindowborder.cpp new file mode 100644 index 0000000000..b77fa35603 --- /dev/null +++ b/graphics/macgui/macwindowborder.cpp @@ -0,0 +1,117 @@ +/* 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. +* +* MIT License: +* +* Copyright (c) 2016 Borja Lorente +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following +* conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +*/ + +#include "common/system.h" + +#include "graphics/macgui/macwindowborder.h" +#include "graphics/macgui/macwindowmanager.h" + +namespace Graphics { + +using namespace Graphics::MacGUIConstants; + +MacWindowBorder::MacWindowBorder() : _activeInitialized(false), _inactiveInitialized(false) { + _activeBorder = nullptr; + _inactiveBorder = nullptr; + _hasOffsets = false; +} + +MacWindowBorder::~MacWindowBorder() { + if (_activeBorder) + delete _activeBorder; + if (_inactiveBorder) + delete _inactiveBorder; +} + +bool MacWindowBorder::hasBorder(bool active) { + return active ? _activeInitialized : _inactiveInitialized; +} + +void MacWindowBorder::addActiveBorder(TransparentSurface &source) { + assert(!_activeBorder); + _activeBorder = new NinePatchBitmap(&source, false); + _activeInitialized = true; +} + +void MacWindowBorder::addInactiveBorder(TransparentSurface &source) { + assert(!_inactiveBorder); + _inactiveBorder = new NinePatchBitmap(&source, false); + _inactiveInitialized = true; +} + +bool MacWindowBorder::hasOffsets() { + return _hasOffsets; +} + +void MacWindowBorder::setOffsets(int left, int right, int top, int bottom) { + _borderOffsets[0] = left; + _borderOffsets[1] = right; + _borderOffsets[2] = top; + _borderOffsets[3] = bottom; + _hasOffsets = true; +} + +int MacWindowBorder::getOffset(MacBorderOffset offset) { + return _borderOffsets[offset]; +} + +void MacWindowBorder::blitBorderInto(ManagedSurface &destination, bool active) { + + TransparentSurface srf; + NinePatchBitmap *src = active ? _activeBorder : _inactiveBorder; + + srf.create(destination.w, destination.h, destination.format); + srf.fillRect(Common::Rect(0, 0, srf.w, srf.h), kColorGreen2); + + byte palette[kColorCount]; + g_system->getPaletteManager()->grabPalette(palette, 0, kColorCount); + + src->blit(srf, 0, 0, srf.w, srf.h, palette, kColorCount); + destination.transBlitFrom(srf, kColorGreen2); +} + +} // End of namespace Graphics diff --git a/graphics/macgui/macwindowborder.h b/graphics/macgui/macwindowborder.h new file mode 100644 index 0000000000..54938e5143 --- /dev/null +++ b/graphics/macgui/macwindowborder.h @@ -0,0 +1,149 @@ +/* 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. +* +* MIT License: +* +* Copyright (c) 2016 Borja Lorente +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following +* conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +*/ + +#ifndef GRAPHICS_MACGUI_MACWINDOWBORDER_H +#define GRAPHICS_MACGUI_MACWINDOWBORDER_H + +#include "common/str.h" +#include "common/list.h" + +#include "graphics/nine_patch.h" +#include "graphics/managed_surface.h" +#include "graphics/transparent_surface.h" + +namespace Graphics { + +enum MacBorderOffset { + kBorderOffsetLeft = 0, + kBorderOffsetRight = 1, + kBorderOffsetTop = 2, + kBorderOffsetBottom = 3 +}; + +/** + * A representation of a custom border, which allows for arbitrary border offsets + * and nine-patch resizable displays for both active and inactive states. + * However, the border offsets are the same for both active and inactive states. + */ +class MacWindowBorder { +public: + MacWindowBorder(); + ~MacWindowBorder(); + + /** + * Accessor to check whether or not a border is loaded. + * @param active State that we want to check. If true it checks for active border, if false it checks for inactive. + * @return True if the checked state has a border loaded, false otherwise. + */ + bool hasBorder(bool active); + + /** + * Add the given surface as the display of the border in the active state. + * Will fail if there is already an active border. + * @param The surface that will be displayed. + */ + void addActiveBorder(TransparentSurface &source); + + /** + * Add the given surface as the display of the border in the inactive state. + * Will fail if there is already an inactive border. + * @param The surface that will be displayed. + */ + void addInactiveBorder(TransparentSurface &source); + + /** + * Accessor function for the custom offsets. + * @return True if custom offsets have been indicated (setOffsets has been called previously). + */ + bool hasOffsets(); + + /** + * Mutator method to indicate the custom border offsets. + * These should be set to the desired thickness of each side of the border. + * e.g. For a border that is 10 pixels wide and 5 pixels tall, the call should be: + * setOffsets(10, 10, 5, 5) + * Note that this function does not check whether those borders form + * a valid rect when combined with the window dimensions. + * @param left Thickness (in pixels) of the left side of the border. + * @param right Thickness (in pixels) of the right side of the border. + * @param top Thickness (in pixels) of the top side of the border. + * @param bottom Thickness (in pixels) of the bottom side of the border. + */ + void setOffsets(int left, int right, int top, int bottom); + + /** + * Accessor method to retrieve a given border. + * Note that it does not check for validity, and thus if setOffsets + * was not called before it might return garbage. + * @param offset The identifier of the offset wanted. + * @return The desired offset in pixels. + */ + int getOffset(MacBorderOffset offset); + + /** + * Blit the desired border (active or inactive) into a destination surface. + * It automatically resizes the border to fit the given surface. + * @param destination The surface we want to blit into. + * @param active True if we want to blit the active border, false otherwise. + */ + void blitBorderInto(ManagedSurface &destination, bool active); + +private: + + NinePatchBitmap *_activeBorder; + NinePatchBitmap *_inactiveBorder; + + bool _activeInitialized; + bool _inactiveInitialized; + + bool _hasOffsets; + int _borderOffsets[4]; + +}; + +} // End of namespace Graphics +#endif diff --git a/engines/wage/macwindowmanager.cpp b/graphics/macgui/macwindowmanager.cpp index 6ca2efd7c9..9d3b729661 100644 --- a/engines/wage/macwindowmanager.cpp +++ b/graphics/macgui/macwindowmanager.cpp @@ -57,12 +57,11 @@ #include "graphics/managed_surface.h" #include "graphics/palette.h" #include "graphics/primitives.h" +#include "graphics/macgui/macwindowmanager.h" +#include "graphics/macgui/macwindow.h" +#include "graphics/macgui/macmenu.h" -#include "wage/macwindowmanager.h" -#include "wage/macwindow.h" -#include "wage/macmenu.h" - -namespace Wage { +namespace Graphics { static const byte palette[] = { 0, 0, 0, // Black @@ -185,13 +184,18 @@ void MacWindowManager::setActive(int id) { _fullRefresh = true; } +void MacWindowManager::removeWindow(MacWindow *target) { + _windowsToRemove.push_back(target); + _needsRemoval = true; +} + struct PlotData { Graphics::ManagedSurface *surface; - Patterns *patterns; + MacPatterns *patterns; uint fillType; int thickness; - PlotData(Graphics::ManagedSurface *s, Patterns *p, int f, int t) : + PlotData(Graphics::ManagedSurface *s, MacPatterns *p, int f, int t) : surface(s), patterns(p), fillType(f), thickness(t) {} }; @@ -243,6 +247,8 @@ void MacWindowManager::drawDesktop() { void MacWindowManager::draw() { assert(_screen); + removeMarked(); + if (_fullRefresh) drawDesktop(); @@ -291,6 +297,7 @@ bool MacWindowManager::processEvent(Common::Event &event) { it--; BaseMacWindow *w = *it; + if (w->hasAllFocus() || w->getDimensions().contains(event.mouse.x, event.mouse.y)) { if (event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_LBUTTONUP) setActive(w->getId()); @@ -302,6 +309,42 @@ bool MacWindowManager::processEvent(Common::Event &event) { return false; } +void MacWindowManager::removeMarked() { + if (!_needsRemoval) return; + + Common::List<BaseMacWindow *>::const_iterator it; + for (it = _windowsToRemove.begin(); it != _windowsToRemove.end(); it++) { + removeFromStack(*it); + removeFromWindowList(*it); + delete *it; + _activeWindow = 0; + _fullRefresh = true; + } + _windowsToRemove.clear(); + _needsRemoval = false; +} + +void MacWindowManager::removeFromStack(BaseMacWindow *target) { + Common::List<BaseMacWindow *>::iterator stackIt; + for (stackIt = _windowStack.begin(); stackIt != _windowStack.end(); stackIt++) { + if (*stackIt == target) { + stackIt = _windowStack.erase(stackIt); + stackIt--; + } + } +} + +void MacWindowManager::removeFromWindowList(BaseMacWindow *target) { + int size = _windows.size(); + int ndx = 0; + for (int i = 0; i < size; i++) { + if (_windows[i] == target) { + ndx = i; + } + } + _windows.remove_at(ndx); +} + ////////////////////// // Font stuff ////////////////////// @@ -376,4 +419,5 @@ void MacWindowManager::popCursor() { CursorMan.popCursor(); } -} // End of namespace Wage + +} // End of namespace Graphics diff --git a/graphics/macgui/macwindowmanager.h b/graphics/macgui/macwindowmanager.h new file mode 100644 index 0000000000..22731a142e --- /dev/null +++ b/graphics/macgui/macwindowmanager.h @@ -0,0 +1,218 @@ +/* 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. + * + * MIT License: + * + * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef GRAPHICS_MACGUI_MACWINDOWMANAGER_H +#define GRAPHICS_MACGUI_MACWINDOWMANAGER_H + +#include "common/array.h" +#include "common/list.h" +#include "common/events.h" +#include "common/archive.h" + +#include "graphics/fontman.h" +#include "graphics/macgui/macwindow.h" + +namespace Graphics { + +namespace MacGUIConstants { +enum { + kDesktopArc = 7 +}; + +enum { + kColorBlack = 0, + kColorGray = 1, + kColorWhite = 2, + kColorGreen = 3, + kColorGreen2 = 4, + kColorCount +}; + +enum { + kPatternSolid = 1, + kPatternStripes = 2, + kPatternCheckers = 3, + kPatternCheckers2 = 4 +}; +} +using namespace MacGUIConstants; + +class ManagedSurface; + +class Menu; + +typedef Common::Array<byte *> MacPatterns; + +/** + * A manager class to handle window creation, destruction, + * drawing, moving and event handling. + */ +class MacWindowManager { +public: + MacWindowManager(); + ~MacWindowManager(); + + /** + * Mutator to indicate the surface onto which the desktop will be drawn. + * Note that this method should be called as soon as the WM is created. + * @param screen Surface on which the desktop will be drawn. + */ + void setScreen(ManagedSurface *screen) { _screen = screen; } + /** + * Accessor method to check the presence of built-in fonts. + * @return True if there are bult-in fonts. + */ + bool hasBuiltInFonts() { return _builtInFonts; } + /** + * Retrieve a font from the available ones. + * @param name Name of the desired font. + * @param fallback Fallback policy in case the desired font isn't there. + * @return The requested font or the fallback. + */ + const Font *getFont(const char *name, FontManager::FontUsage fallback); + + /** + * Create a window with the given parameters. + * Note that this method allocates the necessary memory for the window. + * @param scrollable True if the window has to be scrollable. + * @param resizable True if the window can be resized. + * @param editable True if the window can be edited. + * @return Pointer to the newly created window. + */ + MacWindow *addWindow(bool scrollable, bool resizable, bool editable); + /** + * Add the menu to the desktop. + * Note that the returned menu is empty, and therefore must be filled + * afterwards. + * @return Pointer to a new empty menu. + */ + Menu *addMenu(); + /** + * Set the desired window state to active. + * @param id ID of the window that has to be set to active. + */ + void setActive(int id); + /** + * Mark a window for removal. + * Note that the window data will be destroyed. + * @param target Window to be removed. + */ + void removeWindow(MacWindow *target); + + /** + * Mutator to indicate that the entire desktop must be refreshed. + * @param redraw Currently unused. + */ + void setFullRefresh(bool redraw) { _fullRefresh = true; } + + /** + * Method to draw the desktop into the screen, + * It will take into accout the contents set as dirty. + * Note that this method does not refresh the screen, + * g_system must be called separately. + */ + void draw(); + + /** + * Method to process the events from the engine. + * Most often this method will be called from the engine's GUI, and + * will send the event to the relevant windows for them to process. + * @param event The event to be processed. + * @return True if the event was processed. + */ + bool processEvent(Common::Event &event); + + /** + * Accessor to retrieve an arbitrary window. + * @param id The id of the desired window. + * @return Pointer to the requested window, if it exists. + */ + BaseMacWindow *getWindow(int id) { return _windows[id]; } + + /** + * Retrieve the patterns used to fill surfaces. + * @return A MacPatterns object reference with the patterns. + */ + MacPatterns &getPatterns() { return _patterns; } + void drawFilledRoundRect(ManagedSurface *surface, Common::Rect &rect, int arc, int color); + + void pushArrowCursor(); + void popCursor(); + +private: + void drawDesktop(); + void loadFonts(); + + void removeMarked(); + void removeFromStack(BaseMacWindow *target); + void removeFromWindowList(BaseMacWindow *target); + +private: + ManagedSurface *_screen; + + Common::List<BaseMacWindow *> _windowStack; + Common::Array<BaseMacWindow *> _windows; + + Common::List<BaseMacWindow *> _windowsToRemove; + bool _needsRemoval; + + int _lastId; + int _activeWindow; + + bool _fullRefresh; + + MacPatterns _patterns; + + Menu *_menu; + + bool _builtInFonts; + bool _cursorIsArrow; +}; + +} // End of namespace Graphics + +#endif diff --git a/graphics/module.mk b/graphics/module.mk index 7331a56c93..f0f5af6c00 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -12,6 +12,10 @@ MODULE_OBJS := \ fonts/ttf.o \ fonts/winfont.o \ maccursor.o \ + macgui/macmenu.o \ + macgui/macwindow.o \ + macgui/macwindowborder.o \ + macgui/macwindowmanager.o\ managed_surface.o \ nine_patch.o \ pixelformat.o \ diff --git a/graphics/nine_patch.cpp b/graphics/nine_patch.cpp index 8ac6977eed..fa2ef20a6e 100644 --- a/graphics/nine_patch.cpp +++ b/graphics/nine_patch.cpp @@ -48,6 +48,8 @@ #include "graphics/transparent_surface.h" #include "graphics/nine_patch.h" +#include "graphics/managed_surface.h" + namespace Graphics { NinePatchSide::~NinePatchSide() { @@ -201,7 +203,7 @@ bad_bitmap: } } -void NinePatchBitmap::blit(Graphics::Surface &target, int dx, int dy, int dw, int dh) { +void NinePatchBitmap::blit(Graphics::Surface &target, int dx, int dy, int dw, int dh, byte *palette, byte numColors) { /* don't draw bitmaps that are smaller than the fixed area */ if (dw < _h._fix || dh < _v._fix) return; @@ -223,6 +225,43 @@ void NinePatchBitmap::blit(Graphics::Surface &target, int dx, int dy, int dw, in _cached_dh = dh; } + /* Handle CLUT8 */ + if (target.format.bytesPerPixel == 1) { + if (!palette) + warning("Trying to blit into a surface with 1bpp, you need the palette."); + + Surface srf; + srf.create(target.w, target.h, _bmp->format); + + drawRegions(srf, dx, dy, dw, dh); + + //TODO: This can be further optimized by keeping the data between draws, + // and using a unique identifier for each palette, so that it only gets + // recalculated when the palette changes. + _cached_colors.clear(); + + for (uint i = 0; i < srf.w; ++i) { + for (uint j = 0; j < srf.h; ++j) { + uint32 color = *(uint32*)srf.getBasePtr(i, j); + if (color > 0) { + *((byte *)target.getBasePtr(i, j)) = closestGrayscale(color, palette, numColors); + } + } + } + + return; + } + + /* Else, draw regions normally */ + drawRegions(target, dx, dy, dw, dh); +} + +NinePatchBitmap::~NinePatchBitmap() { + if (_destroy_bmp) + delete _bmp; +} + +void NinePatchBitmap::drawRegions(Graphics::Surface &target, int dx, int dy, int dw, int dh) { /* draw each region */ for (uint i = 0; i < _v._m.size(); ++i) { for (uint j = 0; j < _h._m.size(); ++j) { @@ -271,9 +310,50 @@ void NinePatchBitmap::blitClip(Graphics::Surface &target, Common::Rect clip, int } } -NinePatchBitmap::~NinePatchBitmap() { - if (_destroy_bmp) - delete _bmp; +byte NinePatchBitmap::getColorIndex(uint32 target, byte* palette) { + byte *pal = palette; + uint i = 0; + uint32 color = TS_RGB(pal[0], pal[1], pal[2]); + while (color != target) { + i += 3; + color = TS_RGB(pal[i], pal[i + 1], pal[i + 2]); + } + return (i / 3); +} + +uint32 NinePatchBitmap::grayscale(uint32 color) { + byte r, g, b; + _bmp->format.colorToRGB(color, r, g, b); + return grayscale(r, g, b); +} + +uint32 NinePatchBitmap::grayscale(byte r, byte g, byte b) { + return (0.29 * r + 0.58 * g + 0.11 * b) / 3; +} + +static inline uint32 dist(uint32 a, uint32 b) { + if (a > b) + return (a - b); + + return b - a; +} + +byte NinePatchBitmap::closestGrayscale(uint32 color, byte* palette, byte paletteLength) { + if (!_cached_colors.contains(color)) { + byte target = grayscale(color); + byte bestNdx = 0; + byte bestColor = grayscale(palette[0], palette[1], palette[2]); + for (byte i = 1; i < paletteLength; ++i) { + byte current = grayscale(palette[i * 3], palette[(i * 3) + 1], palette[(i * 3) + 2]); + if (dist(target, bestColor) >= dist(target, current)) { + bestColor = current; + bestNdx = i; + } + } + _cached_colors[color] = bestNdx; + } + + return _cached_colors[color]; } } // end of namespace Graphics diff --git a/graphics/nine_patch.h b/graphics/nine_patch.h index 45e4e0918a..aa81a2fc1f 100644 --- a/graphics/nine_patch.h +++ b/graphics/nine_patch.h @@ -47,9 +47,14 @@ #define GRAPHICS_NINE_PATCH_H #include "common/array.h" +#include "common/rect.h" +#include "common/hashmap.h" namespace Graphics { +class TransparentSurface; +class Surface; + struct NinePatchMark { int offset; int length; @@ -77,12 +82,13 @@ class NinePatchBitmap { bool _destroy_bmp; int _width, _height; int _cached_dw, _cached_dh; + Common::HashMap<uint32, int> _cached_colors; public: NinePatchBitmap(Graphics::TransparentSurface *bmp, bool owns_bitmap); ~NinePatchBitmap(); - void blit(Graphics::Surface &target, int dx, int dy, int dw, int dh); + void blit(Graphics::Surface &target, int dx, int dy, int dw, int dh, byte *palette = NULL, byte numColors = 0); void blitClip(Graphics::Surface &target, Common::Rect clip, int dx, int dy, int dw, int dh); int getWidth() { return _width; } @@ -91,6 +97,16 @@ public: int getMinHeight() { return _v._fix; } Graphics::TransparentSurface *getSource() { return _bmp; } Common::Rect &getPadding() { return _padding; } + +private: + + void drawRegions(Graphics::Surface &target, int dx, int dy, int dw, int dh); + + // Assumes color is in the palette + byte getColorIndex(uint32 target, byte *palette); + uint32 grayscale(uint32 color); + uint32 grayscale(byte r, byte g, byte b); + byte closestGrayscale(uint32 color, byte* palette, byte paletteLength); }; } // end of namespace Graphics |