Initial commit
This commit is contained in:
130
graphics/macgui/datafiles.cpp
Normal file
130
graphics/macgui/datafiles.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on MacVenture engine, based on
|
||||
* WebVenture (c) 2010, Sean Kasun
|
||||
* https://github.com/mrkite/webventure, https://seancode.com/webventure/
|
||||
*
|
||||
* Used with explicit permission from the author
|
||||
*/
|
||||
|
||||
#include "graphics/macgui/macwindowmanager.h"
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/compression/unzip.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
static const char * const MACGUI_DATA_BUNDLE = "macgui.dat";
|
||||
|
||||
struct BorderName {
|
||||
uint32 type;
|
||||
const char *name;
|
||||
BorderOffsets offsets;
|
||||
};
|
||||
|
||||
static const BorderName borders[] = {
|
||||
{0x00, "StandardClose", { 1, 2, 19, 2, 2, 2, false, 25, 15, 8, 11, -1, 0, 0, 0, 0}},
|
||||
{0x01, "ThickNoTitle", { 5, 5, 5, 5, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x02, "ThinNoTitle", { 1, 1, 1, 1, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x03, "ThinNoTitleShadow", { 1, 3, 1, 3, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x04, "StandardClose", { 1, 2, 19, 2, 2, 2, false, 25, 15, 8, 11, -1, 0, 0, 0, 0}},
|
||||
{0x05, "Thick", { 5, 5, 20, 5, 2, 3, false, 13, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x06, "ThinNoTitle", { 1, 1, 1, 1, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x07, "ThinNoTitleShadow", { 1, 3, 1, 3, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x08, "StandardCloseZoom", { 1, 2, 19, 2, 2, 2, false, 25, 15, 8, 11, -1, 0, 0, 0, 0}},
|
||||
{0x09, "ThickZoom", { 5, 5, 20, 5, 2, 3, false, 13, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x0A, "ThinNoTitle", { 1, 1, 1, 1, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x0B, "ThinNoTitleShadow", { 1, 3, 1, 3, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x0C, "StandardCloseZoom", { 1, 2, 19, 2, 2, 2, false, 25, 15, 8, 11, -1, 0, 0, 0, 0}},
|
||||
{0x0D, "ThickZoom", { 5, 5, 20, 5, 2, 3, false, 13, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x0E, "ThinNoTitle", { 1, 1, 1, 1, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x0F, "ThinNoTitleShadow", { 1, 3, 1, 3, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}},
|
||||
{0x10, "RoundClose", { 1, 1, 19, 6, 1, 1, true, 25, 15, 8, 11, -1, 0, 0, 0, 0}},
|
||||
{kBorderScroll + 0x00, "Win95BorderScrollbar", { 1, 17, 1, 1, 1, 1, true, 25, -1, -1, 0, -1, 0, 15, 17, 8}},
|
||||
{kBorderScroll + 0x01, "Win95NoBorderScrollbar", { 1, 17, 1, 1, 1, 1, true, 25, -1, -1, 0, -1, 0, 15, 17, 8}},
|
||||
{kBorderScroll + 0x02, "MacOSNoBorderScrollbar", { 1, 17, 1, 1, 1, 1, true, 25, -1, -1, 0, -1, 0, 17, 17, 8}},
|
||||
{0xFF, "No type", {-1, -1, -1, -1, -1, -1, false, 0, -1, -1, 0, -1, 0, 0, 0, 0}}
|
||||
};
|
||||
|
||||
Common::String windowTypeName(uint32 windowType) {
|
||||
int i = 0;
|
||||
while (borders[i].type != 0xFF) {
|
||||
if (borders[i].type == windowType) {
|
||||
return borders[i].name;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return "ThinNoTitle";
|
||||
}
|
||||
|
||||
void MacWindowManager::loadDataBundle() {
|
||||
_dataBundle = Common::makeZipArchive(MACGUI_DATA_BUNDLE);
|
||||
if (!_dataBundle) {
|
||||
warning("MACGUI: Couldn't load data bundle '%s'.", MACGUI_DATA_BUNDLE);
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindowManager::cleanupDataBundle() {
|
||||
delete _dataBundle;
|
||||
}
|
||||
|
||||
const BorderOffsets &MacWindowManager::getBorderOffsets(uint32 windowType) {
|
||||
int i = 0;
|
||||
while (borders[i].type != 0xFF) {
|
||||
if (borders[i].type == windowType)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
return borders[i].offsets;
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *MacWindowManager::getBorderFile(uint32 windowType, uint32 flags) {
|
||||
if (!_dataBundle)
|
||||
return NULL;
|
||||
|
||||
Common::String filename = windowTypeName(windowType);
|
||||
filename += (flags & kWindowBorderActive) ? "_act" : "_inac";
|
||||
filename += (flags & kWindowBorderTitle) ? "_title" : "";
|
||||
filename += ".bmp";
|
||||
Common::Path path(filename, Common::Path::kNoSeparator);
|
||||
if (!_dataBundle->hasFile(path)) {
|
||||
warning("Missing border file '%s' in data bundle", filename.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _dataBundle->createReadStreamForMember(path);
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *MacWindowManager::getFile(const Common::Path &filename) {
|
||||
if (!_dataBundle)
|
||||
return NULL;
|
||||
|
||||
if (!_dataBundle->hasFile(filename)) {
|
||||
warning("Missing file '%s' in data bundle", filename.toString().c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _dataBundle->createReadStreamForMember(filename);
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
245
graphics/macgui/macbutton.cpp
Normal file
245
graphics/macgui/macbutton.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/timer.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/primitives.h"
|
||||
#include "graphics/macgui/macwindowmanager.h"
|
||||
#include "graphics/macgui/macfontmanager.h"
|
||||
#include "graphics/macgui/macmenu.h"
|
||||
#include "graphics/macgui/macbutton.h"
|
||||
#include "graphics/macgui/macwidget.h"
|
||||
#include "graphics/macgui/macwindow.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
MacButton::MacButton(MacButtonType buttonType, TextAlign textAlignment, MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *macFont, int fgcolor, int bgcolor) :
|
||||
MacText(parent, x, y, w, h, wm, s, macFont, fgcolor, bgcolor, w, textAlignment), _pd(Graphics::MacPlotData(_composeSurface, nullptr, &_wm->getPatterns(), 1, 0, 0, 1, bgcolor, true)) {
|
||||
|
||||
_buttonType = buttonType;
|
||||
init();
|
||||
}
|
||||
|
||||
void MacButton::init() {
|
||||
_invertInner = false;
|
||||
_checkBoxType = 0;
|
||||
_checkBoxAccess = 0;
|
||||
|
||||
switch (_buttonType) {
|
||||
case kCheckBox:
|
||||
_dims.right += 16;
|
||||
break;
|
||||
case kRound:
|
||||
_dims.right += 4;
|
||||
_dims.bottom += 4;
|
||||
break;
|
||||
case kRadio:
|
||||
_dims.right += 16;
|
||||
break;
|
||||
}
|
||||
|
||||
_composeSurface->create(_dims.width(), _dims.height(), _wm->_pixelformat);
|
||||
_composeSurface->clear(_bgcolor);
|
||||
}
|
||||
|
||||
void MacButton::setActive(bool active) {
|
||||
if (active == _active)
|
||||
return;
|
||||
|
||||
MacWidget::setActive(active);
|
||||
if (_composeSurface)
|
||||
_contentIsDirty = true;
|
||||
}
|
||||
|
||||
// whether to use getDrawPrimitives or getDrawInvertPrimitives to draw invert pixel, maybe depends on the pattle we are using
|
||||
void MacButton::invertOuter() {
|
||||
Common::Rect r(_dims.width() - 1, _dims.height() - 1);
|
||||
|
||||
Primitives &primitives = _wm->getDrawPrimitives();
|
||||
|
||||
switch (_buttonType) {
|
||||
case kCheckBox: {
|
||||
Common::Rect c = Common::Rect(r.left + 1, r.top + 3, r.left + 9, r.top + 11);
|
||||
primitives.drawRect1(c, _wm->_colorWhite, &_pd);
|
||||
break;
|
||||
}
|
||||
case kRound:
|
||||
primitives.drawRoundRect1(r, 4, _wm->_colorWhite, true, &_pd);
|
||||
break;
|
||||
case kRadio:
|
||||
primitives.drawEllipse(r.left + 1, r.top + 3, r.left + 10, r.top + 12, _wm->_colorWhite, false, &_pd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MacButton::setCheckBoxType(int type) {
|
||||
if (_checkBoxType == type)
|
||||
return;
|
||||
_checkBoxType = type;
|
||||
_contentIsDirty = true;
|
||||
}
|
||||
|
||||
void MacButton::invertInner() {
|
||||
Common::Rect r(_dims.width() - 1, _dims.height() - 1);
|
||||
Common::Rect checkbox;
|
||||
|
||||
Primitives &primitives = _wm->getDrawPrimitives();
|
||||
|
||||
switch (_buttonType) {
|
||||
case kCheckBox:
|
||||
switch (_checkBoxType) {
|
||||
case kCBNormal:
|
||||
primitives.drawLine(r.left + 1, r.top + 3, r.left + 9, r.top + 11, _wm->_colorWhite, &_pd);
|
||||
primitives.drawLine(r.left + 1, r.top + 11, r.left + 9, r.top + 3, _wm->_colorWhite, &_pd);
|
||||
primitives.drawPoint(5, 7, _wm->_colorWhite, &_pd);
|
||||
break;
|
||||
case kCBInsetBlack:
|
||||
checkbox = Common::Rect(r.left + 2, r.top + 4, r.left + 2 + 6, r.top + 4 + 6);
|
||||
primitives.drawFilledRect1(checkbox, _wm->_colorWhite, &_pd);
|
||||
break;
|
||||
case kCBFilledBlack:
|
||||
checkbox = Common::Rect(r.left + 1, r.top + 3, r.left + 1 + 8, r.top + 3 + 8);
|
||||
primitives.drawFilledRect1(checkbox, _wm->_colorWhite, &_pd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case kRound:
|
||||
break;
|
||||
case kRadio:
|
||||
primitives.drawEllipse(r.left + 3, r.top + 5, r.left + 8, r.top + 10, 0, true, &_pd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MacButton::setHilite(bool hilite) {
|
||||
if (hilite == _invertInner)
|
||||
return;
|
||||
_invertInner = hilite;
|
||||
_contentIsDirty = true;
|
||||
}
|
||||
|
||||
bool MacButton::draw(bool forceRedraw) {
|
||||
if (!_contentIsDirty && !forceRedraw)
|
||||
return false;
|
||||
|
||||
MacText::draw();
|
||||
Common::Rect r(_dims.width() - 1, _dims.height() - 1);
|
||||
Graphics::MacPlotData pd(_composeSurface, nullptr, &_wm->getPatterns(), 1, 0, 0, 1, 0);
|
||||
|
||||
Primitives &primitives = _wm->getDrawPrimitives();
|
||||
|
||||
switch (_buttonType) {
|
||||
case kCheckBox: {
|
||||
Common::Rect c = Common::Rect(r.left, r.top + 2, r.left + 10, r.top + 2 + 10);
|
||||
primitives.drawRect1(c, _wm->_colorBlack, &pd);
|
||||
break;
|
||||
}
|
||||
case kRound:
|
||||
primitives.drawRoundRect1(r, 4, _wm->_colorBlack, false, &pd);
|
||||
break;
|
||||
case kRadio:
|
||||
primitives.drawEllipse(r.left, r.top + 2, r.left + 11, r.top + 13, _wm->_colorBlack, false, &pd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_active)
|
||||
invertOuter();
|
||||
if (_invertInner)
|
||||
invertInner();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacButton::draw(ManagedSurface *g, bool forceRedraw) {
|
||||
if (!MacButton::draw(forceRedraw))
|
||||
return false;
|
||||
|
||||
g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), Common::Point(_dims.left, _dims.top), _wm->_colorGreen2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacButton::processEvent(Common::Event &event) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
if (_wm->_mouseDown) {
|
||||
if (_wm->_mode & kWMModeButtonDialogStyle)
|
||||
return true;
|
||||
else if (!_wm->_hilitingWidget)
|
||||
return true;
|
||||
// hovered widget in macwindow will help us set the button status to non-active.
|
||||
// so we only care about setting active here is ok.
|
||||
|
||||
setActive(true);
|
||||
}
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
setActive(true);
|
||||
_wm->_hilitingWidget = true;
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
setActive(false);
|
||||
|
||||
switch (_checkBoxAccess) {
|
||||
case 0:
|
||||
_invertInner = !_invertInner;
|
||||
break;
|
||||
case 1:
|
||||
_invertInner = true;
|
||||
break;
|
||||
case 2:
|
||||
// no op, type 2 will prevent user from setting checkboxes
|
||||
break;
|
||||
default:
|
||||
warning("MacButton::processEvent can not handle checkBoxAccess with type %d", _checkBoxAccess);
|
||||
break;
|
||||
}
|
||||
|
||||
_wm->_hilitingWidget = false;
|
||||
break;
|
||||
default:
|
||||
warning("MacButton:: processEvent: Event not handled");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// we won't have the text with _border and _gutter in macbutton now.
|
||||
// so for the override of calculateOffset, we are passing the border and gutter which depends on buttonType
|
||||
// maybe we can cache this for optimization
|
||||
Common::Point MacButton::calculateOffset() {
|
||||
int x = 0, y = 0;
|
||||
switch (_buttonType) {
|
||||
case kCheckBox:
|
||||
x = 16;
|
||||
break;
|
||||
case kRound:
|
||||
x = 2;
|
||||
y = 2;
|
||||
break;
|
||||
case kRadio:
|
||||
x = 16;
|
||||
break;
|
||||
}
|
||||
return Common::Point(x, y);
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
78
graphics/macgui/macbutton.h
Normal file
78
graphics/macgui/macbutton.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACBUTTON_H
|
||||
#define GRAPHICS_MACGUI_MACBUTTON_H
|
||||
|
||||
#include "graphics/macgui/mactext.h"
|
||||
#include "graphics/macgui/macwidget.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class MacWidget;
|
||||
class MacText;
|
||||
struct MacPlotData;
|
||||
|
||||
enum MacButtonType {
|
||||
kRound,
|
||||
kCheckBox,
|
||||
kRadio
|
||||
};
|
||||
|
||||
// those name comes from Apartment
|
||||
enum CheckBoxType {
|
||||
kCBNormal,
|
||||
kCBInsetBlack,
|
||||
kCBFilledBlack
|
||||
};
|
||||
|
||||
class MacButton : public MacText {
|
||||
public:
|
||||
MacButton(MacButtonType buttonType, TextAlign textAlignment, MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *macFont, int fgcolor, int bgcolor);
|
||||
|
||||
void setActive(bool active) override;
|
||||
|
||||
void invertOuter();
|
||||
void invertInner();
|
||||
|
||||
void setHilite(bool hilite);
|
||||
void setCheckBoxType(int type);
|
||||
void setCheckBoxAccess(int type) { _checkBoxAccess = type; }
|
||||
|
||||
bool draw(ManagedSurface *g, bool forceRedraw = false) override;
|
||||
bool draw(bool forceRedraw = false) override;
|
||||
bool processEvent(Common::Event &event) override;
|
||||
Common::Point calculateOffset() override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
private:
|
||||
MacButtonType _buttonType;
|
||||
MacPlotData _pd;
|
||||
bool _invertInner;
|
||||
int _checkBoxType;
|
||||
int _checkBoxAccess;
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
294
graphics/macgui/macdialog.cpp
Normal file
294
graphics/macgui/macdialog.cpp
Normal file
@@ -0,0 +1,294 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "graphics/primitives.h"
|
||||
|
||||
#include "graphics/macgui/mactext.h"
|
||||
#include "graphics/macgui/macfontmanager.h"
|
||||
#include "graphics/macgui/macwindowmanager.h"
|
||||
#include "graphics/macgui/macdialog.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
enum {
|
||||
kDialogHeight = 113,
|
||||
kDialogBottomPadding = 15
|
||||
};
|
||||
|
||||
MacDialog::MacDialog(ManagedSurface *screen, MacWindowManager *wm, int width, MacText *mactext, int maxTextWidth, MacDialogButtonArray *buttons, uint defaultButton) :
|
||||
_screen(screen), _wm(wm), _mactext(mactext), _maxTextWidth(maxTextWidth), _buttons(buttons), _defaultButton(defaultButton) {
|
||||
// if we have buttons the height of the dialog box should resize accordingly
|
||||
int buttonBottomPos = 0;
|
||||
if (_buttons) {
|
||||
for (uint i = 0; i < _buttons->size(); i++) {
|
||||
if ((*_buttons)[i]->bounds.bottom > buttonBottomPos)
|
||||
buttonBottomPos = (*_buttons)[i]->bounds.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
int height;
|
||||
if (buttonBottomPos > 0)
|
||||
height = buttonBottomPos + kDialogBottomPadding;
|
||||
else
|
||||
height = kDialogHeight + _mactext->getTextHeight();
|
||||
|
||||
_font = getDialogFont();
|
||||
|
||||
_tempSurface = new ManagedSurface();
|
||||
_tempSurface->create(width + 1, height + 1, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
_bbox.left = (_screen->w - width) / 2;
|
||||
_bbox.top = (_screen->h - height) / 2;
|
||||
_bbox.right = (_screen->w + width) / 2;
|
||||
_bbox.bottom = (_screen->h + height) / 2;
|
||||
|
||||
_pressedButton = -1;
|
||||
_mouseOverButton = -1;
|
||||
|
||||
_mouseOverPressedButton = false;
|
||||
|
||||
// Adjust button positions
|
||||
for (uint i = 0; i < _buttons->size(); i++)
|
||||
_buttons->operator[](i)->bounds.translate(_bbox.left, _bbox.top);
|
||||
|
||||
_needsRedraw = true;
|
||||
}
|
||||
|
||||
MacDialog::~MacDialog() {
|
||||
for (uint i = 0; i < _buttons->size(); i++)
|
||||
delete _buttons->operator[](i);
|
||||
delete _tempSurface;
|
||||
}
|
||||
|
||||
const Graphics::Font *MacDialog::getDialogFont() {
|
||||
return _wm->_fontMan->getFont(Graphics::MacFont(Graphics::kMacFontSystem, 12));
|
||||
}
|
||||
|
||||
void MacDialog::paint() {
|
||||
if (!_needsRedraw)
|
||||
return;
|
||||
|
||||
Primitives &primitives = _wm->getDrawPrimitives();
|
||||
|
||||
MacPlotData pd(_screen, nullptr, &_wm->getPatterns(), 1, 0, 0, 1, _wm->_colorBlack, false);
|
||||
primitives.drawFilledRect1(_bbox, kColorWhite, &pd);
|
||||
_mactext->drawToPoint(_screen, Common::Point(_bbox.left + (_bbox.width() - _maxTextWidth)/2, _bbox.top + 16));
|
||||
static int boxOutline[] = {1, 0, 0, 1, 1};
|
||||
drawOutline(_bbox, boxOutline, ARRAYSIZE(boxOutline));
|
||||
|
||||
for (uint i = 0; i < _buttons->size(); i++) {
|
||||
MacDialogButton *button = _buttons->operator[](i);
|
||||
static int buttonOutline[] = {0, 0, 0, 0, 1};
|
||||
|
||||
if (i == _defaultButton) {
|
||||
buttonOutline[0] = buttonOutline[1] = 1;
|
||||
} else {
|
||||
buttonOutline[0] = buttonOutline[1] = 0;
|
||||
}
|
||||
|
||||
int color = kColorBlack;
|
||||
|
||||
if ((int)i == _pressedButton && _mouseOverPressedButton) {
|
||||
Common::Rect bb(button->bounds.left + 5, button->bounds.top + 5,
|
||||
button->bounds.right - 5, button->bounds.bottom - 5);
|
||||
|
||||
primitives.drawFilledRect1(bb, kColorBlack, &pd);
|
||||
|
||||
color = kColorWhite;
|
||||
}
|
||||
int w = _font->getStringWidth(button->text);
|
||||
int x = button->bounds.left + (button->bounds.width() - w) / 2;
|
||||
int y = button->bounds.top + 6;
|
||||
|
||||
_font->drawString(_screen, button->text, x, y, _bbox.width(), color);
|
||||
|
||||
drawOutline(button->bounds, buttonOutline, ARRAYSIZE(buttonOutline));
|
||||
}
|
||||
_needsRedraw = false;
|
||||
}
|
||||
|
||||
void MacDialog::blit() {
|
||||
paint();
|
||||
|
||||
g_system->copyRectToScreen(_screen->getBasePtr(_bbox.left, _bbox.top), _screen->pitch,
|
||||
_bbox.left, _bbox.top, _bbox.width() + 1, _bbox.height() + 1);
|
||||
}
|
||||
|
||||
void MacDialog::drawOutline(Common::Rect &bounds, int *spec, int speclen) {
|
||||
Primitives &primitives = _wm->getDrawPrimitives();
|
||||
|
||||
MacPlotData pd(_screen, nullptr, &_wm->getPatterns(), 1, 0, 0, 1, _wm->_colorBlack, false);
|
||||
for (int i = 0; i < speclen; i++)
|
||||
if (spec[i] != 0) {
|
||||
Common::Rect r(bounds.left + i, bounds.top + i, bounds.right - i, bounds.bottom - i);
|
||||
primitives.drawRect1(r, kColorBlack, &pd);
|
||||
}
|
||||
}
|
||||
|
||||
int MacDialog::run() {
|
||||
bool shouldQuitEngine = false;
|
||||
bool shouldQuit = false;
|
||||
Common::Rect r(_bbox);
|
||||
// we set _fullRefresh to true inside closeMenu() but it does not update the screen
|
||||
// to ensure we capture the background without the menu we must force a draw
|
||||
// draw() checks _fullRefresh flag which is set to true by closeMenu()
|
||||
// so draw() will draw the screen again without the menu pixels
|
||||
// if we don't call draw() then the background captured in the next line has the pixels of the menu.
|
||||
_wm->draw();
|
||||
|
||||
_tempSurface->copyRectToSurface(_screen->getBasePtr(_bbox.left, _bbox.top), _screen->pitch, 0, 0, _bbox.width() + 1, _bbox.height() + 1);
|
||||
_wm->pushCursor(kMacCursorArrow, nullptr);
|
||||
|
||||
while (!shouldQuit) {
|
||||
Common::Event event;
|
||||
|
||||
while (g_system->getEventManager()->pollEvent(event)) {
|
||||
if (processEvent(event))
|
||||
continue;
|
||||
|
||||
switch (event.type) {
|
||||
case Common::EVENT_QUIT:
|
||||
shouldQuitEngine = true;
|
||||
shouldQuit = true;
|
||||
break;
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
mouseMove(event.mouse.x, event.mouse.y);
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
mouseClick(event.mouse.x, event.mouse.y);
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
shouldQuit = mouseRaise(event.mouse.x, event.mouse.y);
|
||||
break;
|
||||
case Common::EVENT_KEYDOWN:
|
||||
switch (event.kbd.keycode) {
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
_pressedButton = -1;
|
||||
shouldQuit = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_needsRedraw)
|
||||
blit();
|
||||
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(50);
|
||||
}
|
||||
|
||||
_screen->copyRectToSurface(_tempSurface->getBasePtr(0, 0), _tempSurface->pitch, _bbox.left, _bbox.top, _bbox.width() + 1, _bbox.height() + 1);
|
||||
g_system->copyRectToScreen(_screen->getBasePtr(r.left, r.top), _screen->pitch, r.left, r.top, r.width() + 1, r.height() + 1);
|
||||
|
||||
_wm->popCursor();
|
||||
|
||||
if (shouldQuitEngine)
|
||||
return kMacDialogQuitRequested;
|
||||
|
||||
return _pressedButton;
|
||||
}
|
||||
|
||||
int MacDialog::matchButton(int x, int y) {
|
||||
for (uint i = 0; i < _buttons->size(); i++)
|
||||
if (_buttons->operator[](i)->bounds.contains(x, y))
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MacDialog::mouseMove(int x, int y) {
|
||||
int match = matchButton(x, y);
|
||||
|
||||
if (_pressedButton != -1) {
|
||||
if (_mouseOverPressedButton && match != _pressedButton) {
|
||||
_mouseOverPressedButton = false;
|
||||
_needsRedraw = true;
|
||||
} else if (!_mouseOverPressedButton && match == _pressedButton) {
|
||||
_mouseOverPressedButton = true;
|
||||
_needsRedraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_mouseOverButton != match) {
|
||||
_mouseOverButton = match;
|
||||
if (match != -1) {
|
||||
_wm->sayText(_buttons->operator[](match)->text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MacDialog::mouseClick(int x, int y) {
|
||||
int match = matchButton(x, y);
|
||||
|
||||
if (match != -1) {
|
||||
_pressedButton = match;
|
||||
_mouseOverPressedButton = true;
|
||||
|
||||
_needsRedraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
int MacDialog::mouseRaise(int x, int y) {
|
||||
bool res = false;
|
||||
|
||||
if (_pressedButton != -1) {
|
||||
if (matchButton(x, y) == _pressedButton)
|
||||
res = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
126
graphics/macgui/macdialog.h
Normal file
126
graphics/macgui/macdialog.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_MACDIALOG_H
|
||||
#define GRAPHICS_MACGUI_MACDIALOG_H
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Common {
|
||||
struct Event;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class Font;
|
||||
class ManagedSurface;
|
||||
|
||||
class MacText;
|
||||
class MacWindowManager;
|
||||
|
||||
enum {
|
||||
kMacDialogQuitRequested = -2
|
||||
};
|
||||
|
||||
struct MacDialogButton {
|
||||
Common::String text;
|
||||
Common::Rect bounds;
|
||||
|
||||
MacDialogButton(const char *t, int x1, int y1, int w, int h) {
|
||||
text = t;
|
||||
bounds.left = x1;
|
||||
bounds.top = y1;
|
||||
bounds.right = x1 + w - 1;
|
||||
bounds.bottom = y1 + h - 1;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Common::Array<MacDialogButton *> MacDialogButtonArray;
|
||||
|
||||
class MacDialog {
|
||||
public:
|
||||
MacDialog(ManagedSurface *screen, MacWindowManager *wm, int width, MacText *mactext, int maxTextWidth, MacDialogButtonArray *buttons, uint defaultButton);
|
||||
virtual ~MacDialog();
|
||||
|
||||
int run();
|
||||
virtual bool processEvent(const Common::Event &event) { return false; }
|
||||
|
||||
protected:
|
||||
ManagedSurface *_screen;
|
||||
MacWindowManager *_wm;
|
||||
ManagedSurface *_tempSurface;
|
||||
Common::Rect _bbox;
|
||||
Common::Rect _r;
|
||||
MacText *_mactext;
|
||||
int _maxTextWidth;
|
||||
|
||||
const Font *_font;
|
||||
MacDialogButtonArray *_buttons;
|
||||
uint _defaultButton;
|
||||
bool _mouseOverPressedButton;
|
||||
int _mouseOverButton;
|
||||
|
||||
public:
|
||||
int _pressedButton;
|
||||
bool _needsRedraw;
|
||||
|
||||
private:
|
||||
const Font *getDialogFont();
|
||||
void drawOutline(Common::Rect &bounds, int *spec, int speclen);
|
||||
|
||||
public:
|
||||
virtual void paint();
|
||||
void blit();
|
||||
void mouseMove(int x, int y);
|
||||
void mouseClick(int x, int y);
|
||||
int mouseRaise(int x, int y);
|
||||
int matchButton(int x, int y);
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
1010
graphics/macgui/macfontmanager.cpp
Normal file
1010
graphics/macgui/macfontmanager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
242
graphics/macgui/macfontmanager.h
Normal file
242
graphics/macgui/macfontmanager.h
Normal file
@@ -0,0 +1,242 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACFONTMANAGER_H
|
||||
#define GRAPHICS_MACGUI_MACFONTMANAGER_H
|
||||
|
||||
#include "common/language.h"
|
||||
#include "graphics/fonts/bdf.h"
|
||||
#include "graphics/fontman.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
class MacResManager;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
struct TTFMap {
|
||||
const char *ttfName;
|
||||
uint16 slant;
|
||||
};
|
||||
|
||||
class MacFONTFont;
|
||||
class MacFontFamily;
|
||||
|
||||
enum {
|
||||
kMacFontNonStandard = -1,
|
||||
kMacFontSystem = 0,
|
||||
kMacFontApplication = 1,
|
||||
|
||||
kMacFontNewYork = 2,
|
||||
kMacFontGeneva = 3,
|
||||
kMacFontMonaco = 4,
|
||||
kMacFontVenice = 5,
|
||||
kMacFontLondon = 6,
|
||||
kMacFontAthens = 7,
|
||||
kMacFontSanFrancisco = 8,
|
||||
kMacFontToronto = 9,
|
||||
kMacFontCairo = 11,
|
||||
kMacFontLosAngeles = 12,
|
||||
kMacFontZapfDingbats = 13,
|
||||
kMacFontBookman = 14,
|
||||
kMacFontHelveticaNarrow = 15,
|
||||
kMacFontPalatino = 16,
|
||||
kMacFontZapfChancery = 18,
|
||||
kMacFontTimes = 20,
|
||||
kMacFontHelvetica = 21,
|
||||
kMacFontCourier = 22,
|
||||
kMacFontSymbol = 23,
|
||||
kMacFontTaliesin = 24,
|
||||
kMacFontAvantGarde = 33,
|
||||
kMacFontNewCenturySchoolbook = 34,
|
||||
kMacFontChicago = 16383,
|
||||
|
||||
kMacFontOsaka = 16384,
|
||||
kMacFontBookMinchoM = 16396,
|
||||
kMacFontMonoGothic = 16433,
|
||||
kMacFontMonoMing = 16435,
|
||||
kMacFontOsakaMono = 16436,
|
||||
kMacFontMediumGothic = 16640,
|
||||
kMacFontMing = 16641,
|
||||
kMacFontHeiseiMincho = 16700,
|
||||
kMacFontHeiseiKakuGothic = 16701
|
||||
};
|
||||
|
||||
enum {
|
||||
kMacFontRegular,
|
||||
kMacFontBold = 1,
|
||||
kMacFontItalic = 2,
|
||||
kMacFontUnderline = 4,
|
||||
kMacFontOutline = 8,
|
||||
kMacFontShadow = 16,
|
||||
kMacFontCondense = 32,
|
||||
kMacFontExtend = 64
|
||||
};
|
||||
|
||||
class Font;
|
||||
|
||||
struct FontInfo {
|
||||
Common::Language lang;
|
||||
Common::CodePage encoding;
|
||||
int aliasForId;
|
||||
Common::String name;
|
||||
|
||||
FontInfo() : lang(Common::UNK_LANG), encoding(Common::kCodePageInvalid), aliasForId(-1) {}
|
||||
};
|
||||
|
||||
class MacFont {
|
||||
public:
|
||||
MacFont(int id = kMacFontSystem, int size = 12, int slant = kMacFontRegular) {
|
||||
_id = id;
|
||||
_size = size ? size : 12;
|
||||
_slant = slant;
|
||||
_fallback = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
|
||||
_fallbackName = Common::String(((const BdfFont *)_fallback)->getFamilyName());
|
||||
_generated = false;
|
||||
_truetype = false;
|
||||
_font = NULL;
|
||||
}
|
||||
|
||||
int getId() const { return _id; };
|
||||
void setId(int id) { _id = id; }
|
||||
int getSize() const { return _size; }
|
||||
int getSlant() const { return _slant; }
|
||||
Common::String getName() const { return _name; }
|
||||
void setName(Common::String &name) { setName(name.c_str()); }
|
||||
void setName(const char *name);
|
||||
const Graphics::Font *getFallback() const { return _fallback; }
|
||||
bool isGenerated() const { return _generated; }
|
||||
void setGenerated(bool gen) { _generated = gen; }
|
||||
bool isTrueType() const { return _truetype; }
|
||||
Font *getFont() const { return _font; }
|
||||
void setFont(Font *font, bool truetype) { _font = font; _truetype = truetype; }
|
||||
void setFallback(const Font *font, Common::String name = "");
|
||||
Common::String getFallbackName() const { return _fallbackName; }
|
||||
|
||||
private:
|
||||
int _id;
|
||||
int _size;
|
||||
int _slant;
|
||||
bool _truetype;
|
||||
Common::String _name;
|
||||
const Graphics::Font *_fallback;
|
||||
Common::String _fallbackName;
|
||||
|
||||
bool _generated;
|
||||
Font *_font;
|
||||
};
|
||||
|
||||
class MacFontManager {
|
||||
public:
|
||||
MacFontManager(uint32 mode, Common::Language language);
|
||||
~MacFontManager();
|
||||
|
||||
void setLocalizedFonts();
|
||||
|
||||
/**
|
||||
* 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(MacFont *macFont);
|
||||
const Font *getFont(MacFont macFont);
|
||||
|
||||
/**
|
||||
* Return font name from standard ID
|
||||
* @param id ID of the font
|
||||
* @param size size of the font
|
||||
* @return the font name or NULL if ID goes beyond the mapping
|
||||
*/
|
||||
const Common::String getFontName(uint16 id, int size, int slant = kMacFontRegular, bool tryGen = false);
|
||||
const Common::String getFontName(const MacFont &font);
|
||||
int getFontIdByName(Common::String name);
|
||||
|
||||
Common::Language getFontLanguage(uint16 id);
|
||||
Common::CodePage getFontEncoding(uint16 id);
|
||||
int getFontAliasForId(uint16 id);
|
||||
Common::String getFontName(uint16 id);
|
||||
|
||||
void loadFonts(Common::SeekableReadStream *stream);
|
||||
void loadFonts(const Common::Path &fileName);
|
||||
void loadFonts(Common::MacResManager *fontFile);
|
||||
void loadWindowsFont(const Common::Path &fileName);
|
||||
|
||||
/**
|
||||
* Register a font name if it doesn't already exist.
|
||||
* @param name name of the font
|
||||
* @return the font's ID
|
||||
*/
|
||||
int registerFontName(Common::String name, int preferredId = -1);
|
||||
|
||||
void forceBuiltinFonts() { _builtInFonts = true; }
|
||||
int parseSlantFromName(const Common::String &name);
|
||||
Common::String getNameFromSlant(int slantVal);
|
||||
|
||||
const Common::Array<MacFontFamily *> &getFontFamilies() { return _fontFamilies; }
|
||||
|
||||
void printFontRegistry(int debugLevel, uint32 channel);
|
||||
|
||||
int registerTTFFont(const Graphics::TTFMap ttfList[]);
|
||||
|
||||
int getFamilyId(int newId, int newSlant);
|
||||
|
||||
private:
|
||||
void loadFontsBDF();
|
||||
void loadFonts();
|
||||
void loadJapaneseFonts();
|
||||
|
||||
void generateFontSubstitute(MacFont &macFont);
|
||||
void generateFONTFont(MacFont &toFont, MacFont &fromFont);
|
||||
|
||||
#ifdef USE_FREETYPE2
|
||||
void generateTTFFont(MacFont &toFront, Common::SeekableReadStream *stream);
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool _builtInFonts;
|
||||
bool _japaneseFontsLoaded;
|
||||
uint32 _mode;
|
||||
Common::Language _language;
|
||||
Common::HashMap<Common::String, Graphics::Font *> _winFontRegistry;
|
||||
Common::HashMap<Common::String, MacFont *> _fontRegistry;
|
||||
Common::Array<MacFontFamily *> _fontFamilies;
|
||||
|
||||
Common::HashMap<int, FontInfo *> _fontInfo;
|
||||
Common::HashMap<Common::String, int> _fontIds;
|
||||
|
||||
int parseFontSlant(Common::String slant);
|
||||
|
||||
/* Unicode font */
|
||||
Common::HashMap<Common::String, const Graphics::Font *> _uniFontRegistry;
|
||||
|
||||
Common::HashMap<Common::String, Common::SeekableReadStream *> _ttfData;
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
1759
graphics/macgui/macmenu.cpp
Normal file
1759
graphics/macgui/macmenu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
246
graphics/macgui/macmenu.h
Normal file
246
graphics/macgui/macmenu.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACMENU_H
|
||||
#define GRAPHICS_MACGUI_MACMENU_H
|
||||
|
||||
#include "common/str-array.h"
|
||||
#include "graphics/macgui/macfontmanager.h"
|
||||
#include "graphics/macgui/macwindow.h"
|
||||
#include "graphics/font.h"
|
||||
|
||||
namespace Common {
|
||||
class U32String;
|
||||
class MacResManager;
|
||||
class PEResources;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
struct MacMenuItem;
|
||||
struct MacMenuSubMenu;
|
||||
typedef Common::Array<MacMenuItem *> ItemArray;
|
||||
|
||||
struct MacMenuSubMenu {
|
||||
ItemArray items;
|
||||
Common::Rect bbox;
|
||||
int highlight;
|
||||
int visStart; // Visible start
|
||||
int visEnd; // Visible end
|
||||
int scroll;
|
||||
|
||||
MacMenuSubMenu() : highlight(-1), visStart(0), visEnd(0), scroll(0) {}
|
||||
|
||||
~MacMenuSubMenu();
|
||||
|
||||
void enableAllItems();
|
||||
|
||||
int ytoItem(int y, int itemHeight) { return MIN<int>((y - bbox.top) / itemHeight, items.size() - 1); }
|
||||
};
|
||||
|
||||
struct MacMenuItem {
|
||||
Common::String text;
|
||||
Common::U32String unicodeText;
|
||||
bool unicode;
|
||||
int action;
|
||||
int style;
|
||||
char shortcut;
|
||||
int shortcutPos;
|
||||
bool enabled;
|
||||
bool checked;
|
||||
Common::Rect bbox;
|
||||
|
||||
MacMenuSubMenu *submenu;
|
||||
|
||||
MacMenuItem(const Common::String &t, int a = -1, int s = 0, char sh = 0, int sp = -1, bool e = true, bool c = false) :
|
||||
text(t), unicode(false), action(a), style(s), shortcut(sh),
|
||||
shortcutPos(sp), enabled(e), submenu(nullptr), checked(c) {}
|
||||
MacMenuItem(const Common::U32String &t, int a = -1, int s = 0, char sh = 0, int sp = -1, bool e = true, bool c = false) :
|
||||
unicodeText(t), unicode(true), action(a), style(s), shortcut(sh),
|
||||
shortcutPos(sp), enabled(e), submenu(nullptr), checked(c) {}
|
||||
|
||||
~MacMenuItem() {
|
||||
if (submenu)
|
||||
delete submenu;
|
||||
}
|
||||
};
|
||||
|
||||
struct MacMenuData {
|
||||
int menunum;
|
||||
const char *title;
|
||||
int action;
|
||||
byte shortcut;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
class MacMenu : public BaseMacWindow {
|
||||
public:
|
||||
MacMenu(int id, const Common::Rect &bounds, MacWindowManager *wm);
|
||||
~MacMenu();
|
||||
|
||||
ManagedSurface *getBorderSurface() override { return nullptr; }
|
||||
const Common::Rect &getInnerDimensions() override { return _dims; }
|
||||
bool isDirty() override { return _contentIsDirty || _dimensionsDirty; }
|
||||
|
||||
static Common::StringArray *readMenuFromResource(Common::SeekableReadStream *res);
|
||||
static MacMenu *createMenuFromPEexe(Common::PEResources *exe, MacWindowManager *wm);
|
||||
|
||||
void setAlignment(Graphics::TextAlign align);
|
||||
|
||||
void setCommandsCallback(void (*callback)(int, Common::String &, void *), void *data) { _ccallback = callback; _cdata = data; }
|
||||
void setCommandsCallback(void (*callback)(int, Common::U32String &, void *), void *data) { _unicodeccallback = callback; _cdata = data; }
|
||||
|
||||
void addStaticMenus(const MacMenuData *data);
|
||||
void calcDimensions();
|
||||
|
||||
int numberOfMenus();
|
||||
int numberOfMenuItems(MacMenuItem *menu);
|
||||
|
||||
MacMenuItem *getMenuItem(int menuId);
|
||||
MacMenuItem *getMenuItem(const Common::String &menuId);
|
||||
MacMenuItem *getSubMenuItem(MacMenuItem *menu, int itemId);
|
||||
MacMenuItem *getSubMenuItem(MacMenuItem *menu, const Common::String &itemId);
|
||||
|
||||
MacMenuSubMenu *addSubMenu(MacMenuSubMenu *submenu, int index = -1);
|
||||
int addMenuItem(MacMenuSubMenu *submenu, const Common::String &text, int action = -1, int style = 0, char shortcut = 0, bool enabled = true, bool checked = false);
|
||||
int addMenuItem(MacMenuSubMenu *submenu, const Common::U32String &text, int action = 0, int style = 0, char shortcut = 0, bool enabled = true, bool checked = false);
|
||||
void insertMenuItem(MacMenuSubMenu *submenu, const Common::String &text, uint pos, int action = -1, int style = 0, char shortcut = 0, bool enabled = true, bool checked = false);
|
||||
void insertMenuItem(MacMenuSubMenu *submenu, const Common::U32String &text, uint pos, int action = 0, int style = 0, char shortcut = 0, bool enabled = true, bool checked = false);
|
||||
void removeMenuItem(MacMenuSubMenu *submenu, uint pos);
|
||||
void loadMenuResource(Common::MacResManager *resFork, uint16 id);
|
||||
void loadMenuBarResource(Common::MacResManager *resFork, uint16 id);
|
||||
void createSubMenuFromString(int id, const char *string, int commandId);
|
||||
void clearSubMenu(int id);
|
||||
|
||||
MacMenuSubMenu *getSubmenu(MacMenuSubMenu *submenu, int index);
|
||||
|
||||
bool draw(ManagedSurface *g, bool forceRedraw = false) override;
|
||||
void eventLoop();
|
||||
bool mouseClick(int x, int y);
|
||||
bool draw(bool forceRedraw = false) override { return false; }
|
||||
void blit(ManagedSurface *g, Common::Rect &dest) override {}
|
||||
|
||||
bool processEvent(Common::Event &event) override;
|
||||
|
||||
void enableCommand(int menunum, int action, bool state);
|
||||
void enableCommand(const char *menuitem, const char *menuaction, bool state);
|
||||
void enableCommand(const Common::U32String &menuitem, const Common::U32String &menuaction, bool state);
|
||||
void enableAllMenus();
|
||||
void disableAllMenus();
|
||||
|
||||
bool isVisible() { return _isVisible; }
|
||||
void setVisible(bool visible, bool silent = false) override { _isVisible = visible; _contentIsDirty = true; }
|
||||
|
||||
void printMenu(int level = 0, MacMenuSubMenu *submenu = nullptr);
|
||||
|
||||
virtual void closeMenu();
|
||||
|
||||
bool checkIntersects(Common::Rect &rect);
|
||||
|
||||
// macmenuItem operations
|
||||
void setCheckMark(MacMenuItem *menuItem, bool checkMark);
|
||||
bool getCheckMark(MacMenuItem *menuItem);
|
||||
|
||||
void setEnabled(MacMenuItem *menuItem, bool enabled);
|
||||
bool getEnabled(MacMenuItem *menuItem);
|
||||
|
||||
void setName(MacMenuItem *menuItem, const Common::String &name);
|
||||
Common::String getName(MacMenuItem *menuItem);
|
||||
|
||||
void setAction(MacMenuItem *menuItem, int actionId);
|
||||
int getAction(MacMenuItem *menuItem);
|
||||
|
||||
int getLastSelectedMenuItem() { return _lastActiveItem; };
|
||||
int getLastSelectedSubmenuItem() { return _lastActiveSubItem; };
|
||||
|
||||
void renderSubmenu(MacMenuSubMenu *menu, bool recursive = true);
|
||||
|
||||
int getScrollDirection() { return _scrollDirection; }
|
||||
|
||||
int getDropdownItemHeight() { return _menuDropdownItemHeight; }
|
||||
|
||||
Common::Array<MacMenuSubMenu *> _menustack;
|
||||
|
||||
protected:
|
||||
Common::Rect _bbox;
|
||||
ManagedSurface _screen;
|
||||
ItemArray _items;
|
||||
bool _isVisible;
|
||||
bool _dimensionsDirty;
|
||||
int _menuDropdownItemHeight;
|
||||
|
||||
int _activeItem;
|
||||
int _activeSubItem;
|
||||
|
||||
bool _isModal;
|
||||
|
||||
void calcSubMenuBounds(MacMenuSubMenu *menu, int x, int y);
|
||||
|
||||
private:
|
||||
ManagedSurface _tempSurface;
|
||||
TextAlign _align;
|
||||
int _menuLeftDropdownPadding;
|
||||
int _menuRightDropdownPadding;
|
||||
|
||||
private:
|
||||
bool checkCallback(bool unicode = false);
|
||||
const Font *getMenuFont(int slant = kMacFontRegular);
|
||||
Common::CodePage getMenuEncoding() const;
|
||||
const Common::String getAcceleratorString(MacMenuItem *item, const char *prefix);
|
||||
void processTabs();
|
||||
void processSubmenuTabs(MacMenuSubMenu *submenu);
|
||||
|
||||
int calcSubMenuWidth(MacMenuSubMenu *menu);
|
||||
|
||||
bool keyEvent(Common::Event &event);
|
||||
bool mouseRelease(int x, int y);
|
||||
bool mouseMove(int x, int y);
|
||||
|
||||
bool processMenuShortCut(uint16 ascii);
|
||||
|
||||
void drawSubMenuArrow(ManagedSurface *dst, int x, int y, int color);
|
||||
bool contains(int x, int y);
|
||||
|
||||
void drawScrollArrow(int arrowX, int arrowY, int direction);
|
||||
|
||||
MacMenuItem *findMenuItem(const Common::String &menuId, const Common::String &itemId);
|
||||
MacMenuItem *findMenuItem(int menuId, int itemId);
|
||||
|
||||
|
||||
const Font *_font;
|
||||
Font *_loadedFont;
|
||||
|
||||
int _lastActiveItem;
|
||||
int _lastActiveSubItem;
|
||||
|
||||
int _selectedItem;
|
||||
|
||||
bool _scrollTimerActive;
|
||||
int _scrollDirection;
|
||||
|
||||
void (*_ccallback)(int action, Common::String &text, void *data);
|
||||
void (*_unicodeccallback)(int action, Common::U32String &text, void *data);
|
||||
void *_cdata;
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
168
graphics/macgui/macpopupmenu.cpp
Normal file
168
graphics/macgui/macpopupmenu.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "graphics/macgui/macpopupmenu.h"
|
||||
#include "graphics/macgui/macwindowmanager.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
MacPopUp::MacPopUp(int id, const Common::Rect &bounds, MacWindowManager *wm, const char *string) : MacMenu(id, bounds, wm) {
|
||||
_menuItemId = addMenuItem(nullptr, "");
|
||||
createSubMenuFromString(0, string, 0);
|
||||
wm->addMenu(id, this);
|
||||
_menuId = id;
|
||||
}
|
||||
|
||||
bool MacPopUp::draw(ManagedSurface *g, bool forceRedraw) {
|
||||
|
||||
if (!_isVisible)
|
||||
return false;
|
||||
|
||||
if (_dimensionsDirty)
|
||||
calcSubMenuBounds(_items[0]->submenu, _mouseX, _mouseY + _offsetY);
|
||||
|
||||
if (!_contentIsDirty && !forceRedraw)
|
||||
return false;
|
||||
_contentIsDirty = false;
|
||||
|
||||
_screen.clear(_wm->_colorGreen);
|
||||
renderSubmenu(_items[0]->submenu, false);
|
||||
|
||||
if (g)
|
||||
g->transBlitFrom(_screen, _wm->_colorGreen);
|
||||
|
||||
if (!(_wm->_mode & kWMModalMenuMode) && g)
|
||||
g_system->copyRectToScreen(g->getPixels(), g->pitch, 0, 0, g->w, g->h);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacPopUp::closeMenu() {
|
||||
// Special handling of popup closing (for example when displaying closing animation)
|
||||
int activeSubItem = getLastSelectedSubmenuItem(); // Find selected item
|
||||
|
||||
if (activeSubItem != -1) {
|
||||
// Do the blinking animation
|
||||
for (int i = 0; i < kNumBlinks; i++) {
|
||||
_items[0]->submenu->highlight = -1; // No selection
|
||||
draw(_wm->_screen, true);
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(kBlinkDelay);
|
||||
|
||||
_items[0]->submenu->highlight = activeSubItem; // Selection
|
||||
draw(_wm->_screen, true);
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(kBlinkDelay);
|
||||
}
|
||||
}
|
||||
|
||||
if (_isSmart && activeSubItem != -1) {
|
||||
// Smart menu, open menu at offset position (so selected item under cursor)
|
||||
int yDisplace = -activeSubItem * _menuDropdownItemHeight;
|
||||
_offsetY = _mouseY + yDisplace > 0 ? yDisplace : -_mouseY; // If offset sum gets out of window, then position menu to 0 (ie below top of window)
|
||||
|
||||
// Checkmark handling
|
||||
setCheckMark(_items[0]->submenu->items[activeSubItem], true);
|
||||
|
||||
// // Uncheck previous item if checked
|
||||
if (_prevCheckedItem != -1 && _prevCheckedItem != activeSubItem) {
|
||||
setCheckMark(_items[0]->submenu->items[_prevCheckedItem], false);
|
||||
}
|
||||
|
||||
_prevCheckedItem = activeSubItem;
|
||||
}
|
||||
|
||||
_isModal = false;
|
||||
|
||||
// Close now
|
||||
MacMenu::closeMenu();
|
||||
}
|
||||
|
||||
uint32 MacPopUp::drawAndSelectMenu(int x, int y, int item) {
|
||||
_mouseX = x;
|
||||
_mouseY = y;
|
||||
|
||||
// If menu is not active, then activate it!
|
||||
if (!_active)
|
||||
_wm->activateMenu();
|
||||
setActive(true);
|
||||
|
||||
_contentIsDirty = true; // Set true to force refresh menu open changes
|
||||
|
||||
_isModal = true;
|
||||
|
||||
// Push our submenu to stack
|
||||
_menustack.clear();
|
||||
_menustack.push_back(_items[0]->submenu);
|
||||
|
||||
_items[0]->submenu->visStart = 0;
|
||||
_items[0]->submenu->visEnd = 0;
|
||||
_items[0]->submenu->scroll = 0;
|
||||
_offsetY = 0;
|
||||
|
||||
if (_isSmart) {
|
||||
int activeSubItem = getLastSelectedSubmenuItem();
|
||||
|
||||
if (activeSubItem != -1)
|
||||
_offsetY = -activeSubItem * _menuDropdownItemHeight;
|
||||
else if (_prevCheckedItem != -1)
|
||||
_offsetY = -_prevCheckedItem * _menuDropdownItemHeight;
|
||||
|
||||
while (_offsetY + _mouseY < 0) {
|
||||
_offsetY += _menuDropdownItemHeight;
|
||||
|
||||
_items[0]->submenu->visStart++;
|
||||
}
|
||||
|
||||
int itemsLeft = _items[0]->submenu->items.size() - _items[0]->submenu->visStart;
|
||||
int spaceLeft = _screen.h - MIN(_mouseY + _offsetY, _mouseY);
|
||||
_items[0]->submenu->visEnd = MAX(0, itemsLeft - spaceLeft / _menuDropdownItemHeight);
|
||||
}
|
||||
|
||||
|
||||
// Highlight previous item if smart menu
|
||||
if (_isSmart && getLastSelectedSubmenuItem() != -1) {
|
||||
_activeItem = 0;
|
||||
_activeSubItem = getLastSelectedSubmenuItem();
|
||||
// Also select the item
|
||||
_items[0]->submenu->highlight = getLastSelectedSubmenuItem();
|
||||
}
|
||||
|
||||
// Display menu and update according to events
|
||||
this->draw(_wm->_screen);
|
||||
eventLoop();
|
||||
|
||||
int activeSubItem = getLastSelectedSubmenuItem();
|
||||
if (activeSubItem == -1)
|
||||
return item;
|
||||
|
||||
// Return one indexed item!
|
||||
return activeSubItem + 1;
|
||||
}
|
||||
|
||||
Common::String MacPopUp::getItemText(int item) {
|
||||
// Convert 1-indexed item to 0 indexed
|
||||
item = item - 1;
|
||||
MacMenuItem *menu = getMenuItem(_menuItemId);
|
||||
MacMenuItem *submenu = getSubMenuItem(menu, item);
|
||||
return getName(submenu);
|
||||
}
|
||||
} // end of namespace Graphics
|
||||
61
graphics/macgui/macpopupmenu.h
Normal file
61
graphics/macgui/macpopupmenu.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACPOPUPMENU_H
|
||||
#define GRAPHICS_MACGUI_MACPOPUPMENU_H
|
||||
|
||||
#include "graphics/macgui/macmenu.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class MacMenu;
|
||||
class MacWindowManager;
|
||||
|
||||
class MacPopUp : public MacMenu {
|
||||
public:
|
||||
MacPopUp(int id, const Common::Rect &bounds, MacWindowManager *wm, const char *string);
|
||||
uint32 drawAndSelectMenu(int x, int y, int item);
|
||||
Common::String getItemText(int item);
|
||||
|
||||
bool draw(ManagedSurface *g, bool forceRedraw = false) override;
|
||||
void closeMenu() override;
|
||||
|
||||
// Extra functions
|
||||
void setSmart(bool smart) {
|
||||
_isSmart = smart;
|
||||
}
|
||||
private:
|
||||
int kBlinkDelay = 15; // Blink delay for closing animation
|
||||
int kNumBlinks = 3; // Number of blinks
|
||||
|
||||
int _mouseX;
|
||||
int _mouseY;
|
||||
int _menuItemId;
|
||||
int _menuId;
|
||||
|
||||
bool _isSmart = false;
|
||||
int _offsetY = 0;
|
||||
int _prevCheckedItem = -1;
|
||||
|
||||
bool mouseClicked(int x, int y);
|
||||
};
|
||||
} // End of namespace Graphics
|
||||
#endif
|
||||
1520
graphics/macgui/mactext-canvas.cpp
Normal file
1520
graphics/macgui/mactext-canvas.cpp
Normal file
File diff suppressed because it is too large
Load Diff
211
graphics/macgui/mactext-canvas.h
Normal file
211
graphics/macgui/mactext-canvas.h
Normal file
@@ -0,0 +1,211 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACTEXTCANVAS_H
|
||||
#define GRAPHICS_MACGUI_MACTEXTCANVAS_H
|
||||
|
||||
#include "graphics/macgui/macwindowmanager.h"
|
||||
#include "graphics/image-archive.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class MacText;
|
||||
|
||||
struct MacFontRun {
|
||||
Common::U32String text;
|
||||
|
||||
uint16 fontId;
|
||||
byte textSlant;
|
||||
uint16 fontSize;
|
||||
uint16 palinfo1;
|
||||
uint16 palinfo2;
|
||||
uint16 palinfo3;
|
||||
uint32 fgcolor;
|
||||
const Font *font;
|
||||
MacWindowManager *wm;
|
||||
Common::String link; // Substitute to return when hover or click
|
||||
|
||||
MacFontRun() {
|
||||
wm = nullptr;
|
||||
fontId = textSlant = fontSize = 0;
|
||||
palinfo1 = palinfo2 = palinfo3 = 0;
|
||||
fgcolor = 0;
|
||||
font = nullptr;
|
||||
}
|
||||
|
||||
MacFontRun(MacWindowManager *wm_) {
|
||||
wm = wm_;
|
||||
fontId = textSlant = fontSize = 0;
|
||||
palinfo1 = palinfo2 = palinfo3 = 0;
|
||||
fgcolor = 0;
|
||||
font = nullptr;
|
||||
}
|
||||
|
||||
MacFontRun(MacWindowManager *wm_, uint16 fontId_, byte textSlant_, uint16 fontSize_,
|
||||
uint16 palinfo1_, uint16 palinfo2_, uint16 palinfo3_) {
|
||||
setValues(wm_, fontId_, textSlant_, fontSize_, palinfo1_, palinfo2_, palinfo3_);
|
||||
}
|
||||
|
||||
MacFontRun(MacWindowManager *wm_, const Font *font_, byte textSlant_, uint16 fontSize_,
|
||||
uint16 palinfo1_, uint16 palinfo2_, uint16 palinfo3_) {
|
||||
setValues(wm_, 0, textSlant_, fontSize_, palinfo1_, palinfo2_, palinfo3_);
|
||||
font = font_;
|
||||
}
|
||||
|
||||
void setValues(MacWindowManager *wm_, uint16 fontId_, byte textSlant_, uint16 fontSize_,
|
||||
uint16 palinfo1_, uint16 palinfo2_, uint16 palinfo3_) {
|
||||
wm = wm_;
|
||||
fontId = fontId_;
|
||||
textSlant = textSlant_;
|
||||
fontSize = fontSize_;
|
||||
palinfo1 = palinfo1_;
|
||||
palinfo2 = palinfo2_;
|
||||
palinfo3 = palinfo3_;
|
||||
fgcolor = wm_->findBestColor(palinfo1_ & 0xff, palinfo2_ & 0xff, palinfo3_ & 0xff);
|
||||
font = nullptr;
|
||||
}
|
||||
|
||||
const Font *getFont();
|
||||
|
||||
const Common::String toString();
|
||||
bool equals(MacFontRun &to);
|
||||
|
||||
Common::CodePage getEncoding();
|
||||
bool plainByteMode();
|
||||
Common::String getEncodedText();
|
||||
|
||||
bool equals(const MacFontRun *y) {
|
||||
return (fontId == y->fontId &&
|
||||
textSlant == y->textSlant &&
|
||||
fontSize == y->fontSize &&
|
||||
palinfo1 == y->palinfo1 &&
|
||||
palinfo2 == y->palinfo2 &&
|
||||
palinfo3 == y->palinfo3 &&
|
||||
fgcolor == y->fgcolor);
|
||||
}
|
||||
|
||||
void debugPrint();
|
||||
};
|
||||
|
||||
struct MacTextLine;
|
||||
|
||||
class MacTextCanvas {
|
||||
public:
|
||||
Common::Array<MacTextLine> _text;
|
||||
ManagedSurface *_surface = nullptr, *_shadowSurface = nullptr;
|
||||
int _maxWidth = 0;
|
||||
int _textMaxWidth = 0;
|
||||
int _textMaxHeight = 0;
|
||||
TextAlign _textAlignment = kTextAlignLeft;
|
||||
int _interLinear = 0;
|
||||
int _textShadow = 0;
|
||||
MacWindowManager *_wm = nullptr;
|
||||
uint32 _tfgcolor = 0;
|
||||
uint32 _tbgcolor = 0;
|
||||
bool _macFontMode = true;
|
||||
MacText *_macText;
|
||||
MacFontRun _defaultFormatting;
|
||||
ImageArchive _imageArchive;
|
||||
|
||||
public:
|
||||
~MacTextCanvas();
|
||||
|
||||
void recalcDims();
|
||||
void reallocSurface();
|
||||
void render(int from, int to);
|
||||
void render(int from, int to, int shadow);
|
||||
int getAlignOffset(int row);
|
||||
|
||||
/**
|
||||
* Returns line width in pixels. This takes into account chunks.
|
||||
* The result is cached for faster subsequent calls.
|
||||
*
|
||||
* @param line Line number
|
||||
* @param enforce Flag for indicating skipping the cache and computing the width,
|
||||
* must be called when text gets changed
|
||||
* @param col Compute line width up to specified column, including this column
|
||||
* @return line width in pixels, or 0 for non-existent lines
|
||||
*/
|
||||
int getLineWidth(int line, bool enforce = false, int col = -1);
|
||||
int getLineHeight(int line);
|
||||
int getLineCharWidth(int line, bool enforce = false);
|
||||
|
||||
void splitString(const Common::U32String &str, int curLine, MacFontRun &defaultFormatting);
|
||||
const Common::U32String::value_type *splitString(const Common::U32String::value_type *s, int curLine, MacFontRun &defaultFormatting);
|
||||
|
||||
void chopChunk(const Common::U32String &str, int *curLinePtr, int indent, int maxWidth);
|
||||
Common::U32String getTextChunk(int startRow, int startCol, int endRow, int endCol, bool formatted = false, bool newlines = true);
|
||||
|
||||
/**
|
||||
* Rewraps paragraph containing given text row.
|
||||
* When text is modified, we redo whole thing again without touching
|
||||
* other paragraphs. Also, cursor position is returned in the arguments
|
||||
*/
|
||||
void reshuffleParagraph(int *row, int *col, MacFontRun &defaultFormatting);
|
||||
void setMaxWidth(int maxWidth, MacFontRun &defaultFormatting);
|
||||
|
||||
void debugPrint(const char *prefix = nullptr);
|
||||
|
||||
private:
|
||||
void processTable(int line, int maxWidth);
|
||||
void parsePicExt(const Common::U32String &ext, uint16 &w, uint16 &h, int defpercent);
|
||||
};
|
||||
|
||||
struct MacTextTableRow {
|
||||
Common::Array<MacTextCanvas> cells;
|
||||
int heght = -1;
|
||||
};
|
||||
|
||||
struct MacTextLine {
|
||||
int width = -1;
|
||||
int height = -1;
|
||||
int minWidth = -1;
|
||||
int y = 0;
|
||||
int charwidth = -1;
|
||||
bool paragraphEnd = false;
|
||||
bool wordContinuation = false;
|
||||
int indent = 0; // in units
|
||||
int firstLineIndent = 0; // in pixels
|
||||
Common::Path picfname;
|
||||
Common::U32String picalt, pictitle, picext;
|
||||
uint16 picpercent = 50;
|
||||
Common::Array<MacTextTableRow> *table = nullptr;
|
||||
ManagedSurface *tableSurface = nullptr;
|
||||
|
||||
Common::Array<MacFontRun> chunks;
|
||||
|
||||
MacFontRun &firstChunk() { return chunks[0]; }
|
||||
MacFontRun &lastChunk() { return chunks[chunks.size() - 1]; }
|
||||
|
||||
/**
|
||||
* Search for a chunk at given char column.
|
||||
*
|
||||
* @param col Requested column, gets modified with in-chunk column
|
||||
* @returns Chunk number
|
||||
*
|
||||
* @note If requested column is too big, returns last character in the line
|
||||
*/
|
||||
uint getChunkNum(int *col);
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
382
graphics/macgui/mactext-md.cpp
Normal file
382
graphics/macgui/mactext-md.cpp
Normal file
@@ -0,0 +1,382 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/formats/markdown.h"
|
||||
|
||||
#include "graphics/macgui/mactext.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
#define PR(x) ((x && x->data) ? Common::toPrintable(Common::String((const char *)(x)->data , (x)->size)).c_str() : "(null)")
|
||||
|
||||
struct MDState {
|
||||
Common::List<int> listNum;
|
||||
uint32 linkr = 0, linkg = 0, linkb = 0;
|
||||
};
|
||||
|
||||
void render_blockcode(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, const Common::SDDataBuffer *lang, void *opaque) {
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
Common::String res = Common::String::format("\n\001\016+0001" "\001\016t%04x" "%s" "\001\016tffff" "\n\001\016-0001",
|
||||
kMacFontMonaco, Common::String((const char *)text->data , text->size).c_str());
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
|
||||
debug(1, "render_blockcode(%s, %s)", PR(text), PR(lang));
|
||||
}
|
||||
|
||||
void render_blockquote(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
warning("STUB: render_blockquote(%s)", PR(text));
|
||||
}
|
||||
|
||||
void render_blockhtml(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
warning("STUB: render_blockhtml(%s)", PR(text));
|
||||
}
|
||||
|
||||
void render_header(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, int level, void *opaque) {
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
debug(1, "render_header(%s)", PR(text));
|
||||
|
||||
Common::String res = Common::String::format("\001\016+00%01x0" "%s" "\001\016-00f0\n", level, Common::String((const char *)text->data , text->size).c_str());
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
}
|
||||
|
||||
void render_hrule(Common::SDDataBuffer *ob, void *opaque) {
|
||||
warning("STUB: render_hrule()");
|
||||
}
|
||||
|
||||
void render_list_start(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, int flags, void *opaque) {
|
||||
MDState *mdstate = (MDState *)opaque;
|
||||
|
||||
mdstate->listNum.push_back(flags & MKD_LIST_ORDERED ? 1 : -1);
|
||||
|
||||
sd_bufput(ob, "\001\016+0001", 7);
|
||||
|
||||
debug(1, "render_list_start(%s, %d)", PR(text), flags);
|
||||
}
|
||||
|
||||
void render_list(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, int flags, void *opaque) {
|
||||
MDState *mdstate = (MDState *)opaque;
|
||||
|
||||
mdstate->listNum.pop_back();
|
||||
|
||||
sd_bufput(ob, text->data, text->size);
|
||||
sd_bufput(ob, "\n\001\016-0001", 8);
|
||||
|
||||
debug(1, "render_list(%s, %d)", PR(text), flags);
|
||||
}
|
||||
|
||||
void render_listitem(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, int flags, void *opaque) {
|
||||
MDState *mdstate = (MDState *)opaque;
|
||||
|
||||
int listNum = mdstate->listNum.back();
|
||||
|
||||
Common::String prefix;
|
||||
if (flags & MKD_LIST_ORDERED) {
|
||||
prefix = Common::String::format("%d. ", listNum);
|
||||
|
||||
mdstate->listNum.back()++;
|
||||
} else {
|
||||
prefix = "* ";
|
||||
}
|
||||
|
||||
Common::String res = Common::String::format("\001\016*%02x%s", prefix.size(), prefix.c_str());
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
|
||||
sd_bufput(ob, prefix.c_str(), prefix.size());
|
||||
|
||||
sd_bufput(ob, text->data, text->size);
|
||||
|
||||
debug(1, "render_listitem(%s, %d)", PR(text), flags);
|
||||
}
|
||||
|
||||
void render_paragraph(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
debug(1, "render_paragraph(%s)", PR(text));
|
||||
|
||||
sd_bufput(ob, text->data, text->size);
|
||||
sd_bufput(ob, "\n\n", 2);
|
||||
}
|
||||
|
||||
void render_table(Common::SDDataBuffer *ob, const Common::SDDataBuffer *header, const Common::SDDataBuffer *body, void *opaque) {
|
||||
if (!body)
|
||||
return;
|
||||
|
||||
Common::String res = Common::String::format("\001\016Th" "%s" "\001\016Tb" "%s" "\001\016TB",
|
||||
Common::String((const char *)header->data , header->size).c_str(), Common::String((const char *)body->data , body->size).c_str());
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
|
||||
debug(1, "render_table(%s, %s)", PR(header), PR(body));
|
||||
}
|
||||
|
||||
void render_table_row(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
Common::String res = Common::String::format("\001\016Tr" "%s\n", Common::String((const char *)text->data , text->size).c_str());
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
|
||||
debug(1, "render_table_row(%s)", PR(text));
|
||||
}
|
||||
|
||||
void render_table_cell(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, int flags, void *opaque) {
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
TextAlign align;
|
||||
|
||||
switch (flags) {
|
||||
case Common::MKD_TABLE_ALIGN_R:
|
||||
align = kTextAlignRight;
|
||||
break;
|
||||
case Common::MKD_TABLE_ALIGN_CENTER:
|
||||
align = kTextAlignCenter;
|
||||
break;
|
||||
case Common::MKD_TABLE_ALIGN_L:
|
||||
default:
|
||||
align = kTextAlignLeft;
|
||||
}
|
||||
|
||||
Common::String res = Common::String((const char *)text->data, text->size);
|
||||
|
||||
if (flags & Common::MKD_TABLE_HEADER)
|
||||
res = Common::String::format("\001\016+%02x00" "%s" "\001\016-%02x00", kMacFontBold, res.c_str(), kMacFontBold);
|
||||
|
||||
res = Common::String::format("\001\016Tc%02x" "%s" "\001\016TC", align, res.c_str());
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
|
||||
debug(1, "render_table_cell(%s), flags: %d", PR(text), flags);
|
||||
}
|
||||
|
||||
int render_autolink(Common::SDDataBuffer *ob, const Common::SDDataBuffer *link, Common::MKDAutolink type, void *opaque) {
|
||||
if (!link)
|
||||
return 0;
|
||||
|
||||
warning("STUB: render_autolink(%s)", PR(link));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_codespan(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
Common::String res = Common::String::format("\001\016t%04x" "%s" "\001\016tffff",
|
||||
kMacFontMonaco, Common::String((const char *)text->data , text->size).c_str());
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
|
||||
debug(1, "render_codespan(%s)", PR(text));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_double_emphasis(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text || !text->size)
|
||||
return 0;
|
||||
|
||||
debug(1, "render_double_emphasis(%s)", PR(text));
|
||||
|
||||
Common::String res = Common::String::format("\001\016+%02x00" "%s" "\001\016-%02x00", kMacFontBold, Common::String((const char *)text->data , text->size).c_str(), kMacFontBold);
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_emphasis(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text || !text->size)
|
||||
return 0;
|
||||
|
||||
debug(1, "render_emphasis(%s)", PR(text));
|
||||
|
||||
Common::String res = Common::String::format("\001\016+%02x00" "%s" "\001\016-%02x00", kMacFontItalic, Common::String((const char *)text->data , text->size).c_str(), kMacFontItalic);
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_image(Common::SDDataBuffer *ob, const Common::SDDataBuffer *link, const Common::SDDataBuffer *title, const Common::SDDataBuffer *alt, const Common::SDDataBuffer *ext, void *opaque) {
|
||||
if (!link)
|
||||
return 0;
|
||||
|
||||
Common::String res = Common::String::format("\001" "\016i%02x" "%02x%s",
|
||||
80, (uint)link->size, Common::String((const char *)link->data, link->size).c_str());
|
||||
|
||||
if (alt) {
|
||||
uint32 len = Common::U32String((const char *)alt->data, alt->size).size();
|
||||
res += Common::String::format("%02x%s", len, Common::String((const char *)alt->data, alt->size).c_str());
|
||||
} else {
|
||||
res += "00";
|
||||
}
|
||||
|
||||
if (title) {
|
||||
uint32 len = Common::U32String((const char *)title->data, title->size).size();
|
||||
res += Common::String::format("%02x%s", len, Common::String((const char *)title->data, title->size).c_str());
|
||||
} else {
|
||||
res += "00";
|
||||
}
|
||||
|
||||
if (ext) {
|
||||
uint32 len = Common::U32String((const char *)ext->data, ext->size).size();
|
||||
res += Common::String::format("%02x%s", len, Common::String((const char *)ext->data, ext->size).c_str());
|
||||
} else {
|
||||
res += "00";
|
||||
}
|
||||
|
||||
res += "\n";
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
|
||||
debug(1, "render_image(%s, %s, %s, %s)", PR(link), PR(title), PR(alt), PR(ext));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_linebreak(Common::SDDataBuffer *ob, void *opaque) {
|
||||
debug(1, "render_linebreak()");
|
||||
|
||||
sd_bufput(ob, "\n", 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_link(Common::SDDataBuffer *ob, const Common::SDDataBuffer *link, const Common::SDDataBuffer *title, const Common::SDDataBuffer *content, void *opaque) {
|
||||
if (!link)
|
||||
return 0;
|
||||
|
||||
MDState *mdstate = (MDState *)opaque;
|
||||
const Common::SDDataBuffer *text = content ? content : link;
|
||||
|
||||
uint32 linklen = Common::U32String((const char *)link->data, link->size).size();
|
||||
|
||||
Common::String res = Common::String::format("\001" "\016+%02x00" "\001\016[%04x%04x%04x"
|
||||
"\001\016l%02x%s" "%s" "\001\016l00" "\001\016]" "\001\016-%02x00", kMacFontUnderline,
|
||||
mdstate->linkr, mdstate->linkg, mdstate->linkb,
|
||||
linklen, Common::String((const char *)link->data , link->size).c_str(),
|
||||
Common::String((const char *)text->data , text->size).c_str(), kMacFontUnderline);
|
||||
|
||||
sd_bufput(ob, res.c_str(), res.size());
|
||||
|
||||
debug(1, "render_link(%s, %s, %s)", PR(link), PR(title), PR(content));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_raw_html_tag(Common::SDDataBuffer *ob, const Common::SDDataBuffer *tag, void *opaque) {
|
||||
if (!tag)
|
||||
return 0;
|
||||
|
||||
sd_bufput(ob, tag->data, tag->size);
|
||||
|
||||
debug(1, "render_raw_html_tag(%s)", PR(tag));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_triple_emphasis(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
warning("STUB: render_triple_emphasis(%s)", PR(text));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_strikethrough(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
warning("STUB: render_strikethrough(%s)", PR(text));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int render_superscript(Common::SDDataBuffer *ob, const Common::SDDataBuffer *text, void *opaque) {
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
warning("STUB: render_superscript(%s)", PR(text));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MacText::setMarkdownText(const Common::U32String &str) {
|
||||
|
||||
const Common::SDCallbacks cb = {
|
||||
/* block level callbacks - NULL skips the block */
|
||||
render_blockcode,
|
||||
render_blockquote,
|
||||
render_blockhtml,
|
||||
render_header,
|
||||
render_hrule,
|
||||
render_list_start,
|
||||
render_list,
|
||||
render_listitem,
|
||||
render_paragraph,
|
||||
render_table,
|
||||
render_table_row,
|
||||
render_table_cell,
|
||||
|
||||
|
||||
/* span level callbacks - NULL or return 0 prints the span verbatim */
|
||||
render_autolink,
|
||||
render_codespan,
|
||||
render_double_emphasis,
|
||||
render_emphasis,
|
||||
render_image,
|
||||
render_linebreak,
|
||||
render_link,
|
||||
render_raw_html_tag,
|
||||
render_triple_emphasis,
|
||||
render_strikethrough,
|
||||
render_superscript,
|
||||
|
||||
/* low level callbacks - NULL copies input directly into the output */
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
/* header and footer */
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
Common::String input = str.encode(); // Encode to UTF8
|
||||
|
||||
MDState mdState;
|
||||
|
||||
// Set link color to blue
|
||||
mdState.linkr = 0;
|
||||
mdState.linkg = 0;
|
||||
mdState.linkb = 0xff;
|
||||
|
||||
Common::SDMarkdown md(Common::MKDEXT_TABLES, 16, &cb, &mdState);
|
||||
Common::String rendered = md.render((const byte *)input.c_str(), input.size());
|
||||
|
||||
setText(rendered);
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
2191
graphics/macgui/mactext.cpp
Normal file
2191
graphics/macgui/mactext.cpp
Normal file
File diff suppressed because it is too large
Load Diff
265
graphics/macgui/mactext.h
Normal file
265
graphics/macgui/mactext.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACTEXT_H
|
||||
#define GRAPHICS_MACGUI_MACTEXT_H
|
||||
|
||||
#include "graphics/macgui/mactext-canvas.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
struct SelectedText {
|
||||
int startX, startY;
|
||||
int endX, endY;
|
||||
int startRow, startCol;
|
||||
int endRow, endCol;
|
||||
|
||||
SelectedText() {
|
||||
startX = startY = -1;
|
||||
endX = endY = -1;
|
||||
startRow = startCol = -1;
|
||||
endRow = endCol = -1;
|
||||
}
|
||||
|
||||
bool needsRender() {
|
||||
return startX != endX || startY != endY;
|
||||
}
|
||||
};
|
||||
|
||||
class MacText : public MacWidget {
|
||||
public:
|
||||
MacText(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, const Common::U32String &s, const MacFont *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment = kTextAlignLeft, int interlinear = 0, uint16 border = 0, uint16 gutter = 0, uint16 boxShadow = 0, uint16 textShadow = 0, bool fixedDims = true, bool scrollBar = false);
|
||||
// 0 pixels between the lines by default
|
||||
|
||||
MacText(const Common::U32String &s, MacWindowManager *wm, const MacFont *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear = 0, bool fixedDims = true, bool scrollBar = false);
|
||||
|
||||
MacText(const Common::U32String &s, MacWindowManager *wm, const Font *font, uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear = 0, bool fixedDims = true, bool scrollBar = false);
|
||||
|
||||
virtual ~MacText();
|
||||
|
||||
virtual void resize(int w, int h);
|
||||
bool processEvent(Common::Event &event) override;
|
||||
|
||||
bool needsRedraw() override { return _contentIsDirty || _cursorDirty; }
|
||||
|
||||
WindowClick isInScrollBar(int x, int y) const;
|
||||
void setScrollBar(bool enable);
|
||||
void resizeScrollBar(int w, int h);
|
||||
|
||||
void setAutoSelect(bool enable) { _autoSelect = enable; }
|
||||
|
||||
void render();
|
||||
void undrawCursor();
|
||||
void draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int yoff);
|
||||
bool draw(ManagedSurface *g, bool forceRedraw = false) override;
|
||||
bool draw(bool forceRedraw = false) override;
|
||||
void drawToPoint(ManagedSurface *g, Common::Rect srcRect, Common::Point dstPoint);
|
||||
void drawToPoint(ManagedSurface *g, Common::Point dstPoint);
|
||||
|
||||
ManagedSurface *getSurface() { return _canvas._surface; }
|
||||
int getInterLinear() { return _canvas._interLinear; }
|
||||
void setInterLinear(int interLinear);
|
||||
void setMaxWidth(int maxWidth);
|
||||
void setDefaultFormatting(uint16 fontId, byte textSlant, uint16 fontSize,
|
||||
uint16 palinfo1, uint16 palinfo2, uint16 palinfo3);
|
||||
const MacFontRun &getDefaultFormatting() { return _defaultFormatting; }
|
||||
|
||||
void setAlignOffset(TextAlign align);
|
||||
TextAlign getAlign() { return _canvas._textAlignment; }
|
||||
virtual Common::Point calculateOffset();
|
||||
void setActive(bool active) override;
|
||||
void setEditable(bool editable);
|
||||
void setInputPadding(bool enable){ _addInputPadding = enable; }
|
||||
|
||||
void setColors(uint32 fg, uint32 bg) override;
|
||||
// set fgcolor for line x
|
||||
void setTextColor(uint32 color, uint32 line);
|
||||
void setTextColor(uint32 color, uint32 start, uint32 end);
|
||||
|
||||
void appendText(const Common::U32String &str, int fontId = kMacFontSystem, int fontSize = 12, int fontSlant = kMacFontRegular, bool skipAdd = false);
|
||||
void appendText(const Common::U32String &str, int fontId = kMacFontSystem, int fontSize = 12, int fontSlant = kMacFontRegular, uint16 r = 0, uint16 g = 0, uint16 b = 0, bool skipAdd = false);
|
||||
void appendText(const Common::U32String &str, const Font *font, uint16 r = 0, uint16 g = 0, uint16 b = 0, bool skipAdd = false);
|
||||
|
||||
int getTextFont() { return _defaultFormatting.fontId; }
|
||||
void enforceTextFont(uint16 fontId);
|
||||
|
||||
int getRowCount();
|
||||
|
||||
// because currently, we are counting linespacing as font height
|
||||
int getTextSize() { return _defaultFormatting.fontSize; }
|
||||
void setTextSize(int textSize);
|
||||
|
||||
int getTextSize(int start, int end);
|
||||
void setTextSize(int textSize, int start, int end);
|
||||
|
||||
uint32 getTextColor() { return _defaultFormatting.fgcolor; }
|
||||
uint32 getTextColor(int start, int end);
|
||||
|
||||
int getTextFont(int start, int end);
|
||||
void setTextFont(int fontId, int start, int end);
|
||||
|
||||
int getTextSlant() { return _defaultFormatting.textSlant; }
|
||||
int getTextSlant(int start, int end);
|
||||
void setTextSlant(int textSlant, int start, int end);
|
||||
void enforceTextSlant(int textSlant);
|
||||
|
||||
// director text related-functions
|
||||
int getMouseChar(int x, int y);
|
||||
int getMouseWord(int x, int y);
|
||||
int getMouseItem(int x, int y);
|
||||
int getMouseLine(int x, int y);
|
||||
Common::U32String getMouseLink(int x, int y);
|
||||
|
||||
bool setImageArchive(const Common::Path &name) { return _canvas._imageArchive.setImageArchive(name); }
|
||||
|
||||
private:
|
||||
MacFontRun getTextChunks(int start, int end);
|
||||
void setTextChunks(int start, int end, int param, void (*callback)(MacFontRun &, int));
|
||||
|
||||
void appendText_(const Common::U32String &strWithFont, uint oldLen);
|
||||
void deletePreviousCharInternal(int *row, int *col);
|
||||
void insertTextFromClipboard();
|
||||
MacFontRun getFgColor();
|
||||
|
||||
public:
|
||||
void appendTextDefault(const Common::U32String &str, bool skipAdd = false);
|
||||
void appendTextDefault(const Common::String &str, bool skipAdd = false);
|
||||
void clearText();
|
||||
void removeLastLine();
|
||||
int getLineCount() { return _canvas._text.size(); }
|
||||
int getLastLineWidth();
|
||||
int getTextHeight() { return _canvas._textMaxHeight; }
|
||||
int getLineHeight(int line);
|
||||
int getTextMaxWidth() { return _canvas._textMaxWidth; }
|
||||
|
||||
void setText(const Common::U32String &str);
|
||||
|
||||
void setFixDims(bool fixed) { _fixedDims = fixed; }
|
||||
bool getFixDims() { return _fixedDims; }
|
||||
|
||||
void deleteSelection();
|
||||
void deletePreviousChar(int *row, int *col);
|
||||
void addNewLine(int *row, int *col);
|
||||
void insertChar(byte c, int *row, int *col);
|
||||
|
||||
void getChunkPosFromIndex(int index, uint &lineNum, uint &chunkNum, uint &offset);
|
||||
void getRowCol(int x, int y, int *sx, int *sy, int *row, int *col, int *chunk_ = nullptr);
|
||||
void getLineCharacter(int x, int y, int *sx, int *sy, int *line, int *character, int *chunk_ = nullptr);
|
||||
Common::U32String getTextChunk(int startRow, int startCol, int endRow, int endCol, bool formatted = false, bool newlines = true);
|
||||
|
||||
Common::U32String getSelection(bool formatted = false, bool newlines = true);
|
||||
uint getSelectionIndex(bool start);
|
||||
void clearSelection();
|
||||
Common::U32String cutSelection();
|
||||
const SelectedText *getSelectedText() { return &_selectedText; }
|
||||
bool hasSelection() { return _selectedText.endY != -1; }
|
||||
|
||||
int getLineSpacing() { return _canvas._interLinear; }
|
||||
|
||||
/**
|
||||
* set the selection of mactext
|
||||
* @param pos pos of selection, 0 represent first, -1 represent the end of text
|
||||
* @param start selection start or selection end
|
||||
*/
|
||||
void setSelection(int pos, bool start);
|
||||
|
||||
Common::U32String getEditedString();
|
||||
Common::U32String getText() { return _str; }
|
||||
Common::U32String getPlainText();
|
||||
|
||||
void setSelRange(int selStart, int selEnd);
|
||||
|
||||
void scroll(int delta);
|
||||
|
||||
// Markdown
|
||||
public:
|
||||
void setMarkdownText(const Common::U32String &str);
|
||||
|
||||
private:
|
||||
void init(uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, uint16 textShadow, bool macFontMode);
|
||||
bool isCutAllowed();
|
||||
|
||||
void recalcDims();
|
||||
|
||||
void drawSelection(int xoff, int yoff);
|
||||
void updateCursorPos();
|
||||
|
||||
void startMarking(int x, int y);
|
||||
void updateTextSelection(int x, int y);
|
||||
|
||||
/**
|
||||
* Clears the text of the last chunk.
|
||||
*/
|
||||
void clearChunkInput();
|
||||
|
||||
public:
|
||||
int _cursorX, _cursorY;
|
||||
bool _cursorState;
|
||||
int _cursorRow, _cursorCol;
|
||||
|
||||
bool _cursorDirty;
|
||||
Common::Rect *_cursorRect;
|
||||
bool _cursorOff;
|
||||
bool _selectable;
|
||||
|
||||
int _scrollPos;
|
||||
|
||||
bool _fullRefresh;
|
||||
|
||||
protected:
|
||||
Common::U32String _str;
|
||||
const MacFont *_macFont;
|
||||
|
||||
bool _fixedDims;
|
||||
bool _scrollBar;
|
||||
MacWindowBorder _scrollBorder;
|
||||
ManagedSurface _borderSurface;
|
||||
|
||||
int _selEnd;
|
||||
int _selStart;
|
||||
|
||||
MacTextCanvas _canvas;
|
||||
|
||||
MacFontRun _defaultFormatting;
|
||||
MacFontRun _currentFormatting;
|
||||
|
||||
private:
|
||||
ManagedSurface *_cursorSurface;
|
||||
ManagedSurface *_cursorSurface2;
|
||||
|
||||
int _editableRow;
|
||||
|
||||
bool _addInputPadding;
|
||||
|
||||
bool _inTextSelection;
|
||||
SelectedText _selectedText;
|
||||
bool _selectionIsDirty;
|
||||
|
||||
MacMenu *_menu;
|
||||
|
||||
bool _autoSelect;
|
||||
};
|
||||
|
||||
int getStringWidth(MacFontRun &format, const Common::U32String &str);
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
618
graphics/macgui/mactextwindow.cpp
Normal file
618
graphics/macgui/mactextwindow.cpp
Normal file
@@ -0,0 +1,618 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/timer.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/macgui/macwindowmanager.h"
|
||||
#include "graphics/macgui/macfontmanager.h"
|
||||
#include "graphics/macgui/mactextwindow.h"
|
||||
#include "graphics/macgui/macmenu.h"
|
||||
|
||||
#define SCROLLBAR_DELAY 300
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
enum {
|
||||
kConWOverlap = 20,
|
||||
kConHOverlap = 20,
|
||||
kConWPadding = 3,
|
||||
kConHPadding = 4,
|
||||
kConOverscan = 3,
|
||||
kConScrollStep = 12,
|
||||
};
|
||||
|
||||
MacTextWindow::MacTextWindow(MacWindowManager *wm, const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, MacMenu *menu, int padding) :
|
||||
MacWindow(wm->getLastId(), true, true, true, wm), _bgcolor(bgcolor), _maxWidth(maxWidth), _menu(menu) {
|
||||
|
||||
_font = font;
|
||||
_mactext = new MacText(this, 0, 0, 0, 0, _wm, Common::U32String(""), font, fgcolor, bgcolor, maxWidth, textAlignment, 0, padding);
|
||||
|
||||
_fontRef = wm->_fontMan->getFont(*font);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
MacTextWindow::MacTextWindow(MacWindowManager *wm, const Font *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, MacMenu *menu, int padding) :
|
||||
MacWindow(wm->getLastId(), true, true, true, wm), _bgcolor(bgcolor), _maxWidth(maxWidth), _menu(menu) {
|
||||
|
||||
_font = nullptr;
|
||||
_mactext = new MacText(Common::U32String(""), _wm, font, fgcolor, bgcolor, maxWidth, textAlignment, 0, true);
|
||||
_fontRef = font;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
void MacTextWindow::init() {
|
||||
_inputTextHeight = 0;
|
||||
|
||||
_inputIsDirty = true;
|
||||
|
||||
_editable = true;
|
||||
_selectable = true;
|
||||
|
||||
_textColorRGB = 0;
|
||||
|
||||
_scrollDirection = kBorderNone;
|
||||
_clickedScrollPart = kBorderNone;
|
||||
_nextScrollTime = 0;
|
||||
_nextWheelEventTime = 0;
|
||||
_scrollDelay = 50;
|
||||
|
||||
_isDragging = false;
|
||||
_dragStartY = 0;
|
||||
_dragStartScrollPos = 0;
|
||||
|
||||
// Disable autoselect on activation
|
||||
_mactext->setAutoSelect(false);
|
||||
|
||||
if (_wm->_mode & kWMModeWin95) {
|
||||
// in win95 mode, we set scrollbar as default
|
||||
_hasScrollBar = true;
|
||||
setBorderType(kWinBorderWin95Scrollbar);
|
||||
loadInternalBorder(kWindowBorderScrollbar | kWindowBorderActive);
|
||||
}
|
||||
}
|
||||
|
||||
void MacTextWindow::resize(int w, int h) {
|
||||
if (_composeSurface->w == w && _composeSurface->h == h)
|
||||
return;
|
||||
|
||||
undrawInput();
|
||||
|
||||
MacWindow::resize(w, h);
|
||||
|
||||
_maxWidth = getInnerDimensions().width();
|
||||
_mactext->resize(_maxWidth, getInnerDimensions().height());
|
||||
}
|
||||
|
||||
void MacTextWindow::setDimensions(const Common::Rect &r) {
|
||||
resize(r.width(), r.height());
|
||||
_dims.moveTo(r.left, r.top);
|
||||
updateInnerDims();
|
||||
|
||||
_contentIsDirty = true;
|
||||
_wm->setFullRefresh(true);
|
||||
|
||||
_mactext->setDimensions(Common::Rect(_innerDims.width(), _innerDims.height()));
|
||||
}
|
||||
|
||||
void MacTextWindow::appendText(const Common::U32String &str, const MacFont *macFont, bool skipAdd) {
|
||||
// the reason we put undrawInput here before appendText, is we don't want the appended text affect our input
|
||||
// thus, we first delete all of out input, and we append new text, and we redraw the input
|
||||
undrawInput();
|
||||
// we calc the rgb though fgcolor
|
||||
uint16 red = (_textColorRGB >> 16) & 0xFF;
|
||||
uint16 green = (_textColorRGB >> 8) & 0xFF;
|
||||
uint16 blue = (_textColorRGB) & 0xFF;
|
||||
|
||||
// Adding empty line at the bottom of the input text area if needed
|
||||
_mactext->setInputPadding(true);
|
||||
|
||||
if (macFont)
|
||||
_mactext->appendText(str, macFont->getId(), macFont->getSize(), macFont->getSlant(), red, green, blue, skipAdd);
|
||||
else {
|
||||
_mactext->appendText(str, _fontRef, red, green, blue, skipAdd);
|
||||
}
|
||||
|
||||
_contentIsDirty = true;
|
||||
_inputIsDirty = true; //force it to redraw input
|
||||
|
||||
if (_editable) {
|
||||
// Add one line of bottom padding to ensure the last line is not covered
|
||||
int padding = _mactext->getLineHeight(_mactext->getLineCount() - 1);
|
||||
padding = MIN<int>(padding, getInnerDimensions().height());
|
||||
|
||||
int oldScroll = _mactext->_scrollPos;
|
||||
|
||||
_mactext->_scrollPos = MAX<int>(0, _mactext->getTextHeight() - getInnerDimensions().height() + padding);
|
||||
|
||||
if (_mactext->_scrollPos != oldScroll) {
|
||||
_mactext->undrawCursor();
|
||||
_mactext->_cursorY -= (_mactext->_scrollPos - oldScroll);
|
||||
_mactext->_cursorDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_wm->_mode & kWMModeWin95)
|
||||
calcScrollBar();
|
||||
// if we enable the dynamic scrollbar, and the text height is smaller than window height, then we disable the border
|
||||
// if the window is editable, then we don't disable the border, because in editable window, the area you scroll is always bigger
|
||||
// than the window
|
||||
if (!_editable && (_mode & kWindowModeDynamicScrollbar) && _mactext->getTextHeight() < getInnerDimensions().height()) {
|
||||
int w = getDimensions().width();
|
||||
int h = getDimensions().height();
|
||||
enableScrollbar(false);
|
||||
disableBorder();
|
||||
resize(w, h);
|
||||
_mactext->_fullRefresh = true;
|
||||
}
|
||||
// if the text height is bigger than the window, then we enable the scrollbar again
|
||||
if (!_editable && (_mode & kWindowModeDynamicScrollbar) && _mactext->getTextHeight() > getInnerDimensions().height()) {
|
||||
enableScrollbar(true);
|
||||
int w = getDimensions().width();
|
||||
int h = getDimensions().height();
|
||||
resize(w, h);
|
||||
_mactext->_fullRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MacTextWindow::appendText(const Common::String &str, const MacFont *macFont, bool skipAdd) {
|
||||
appendText(Common::U32String(str), macFont, skipAdd);
|
||||
}
|
||||
|
||||
void MacTextWindow::setMarkdownText(const Common::U32String &str) {
|
||||
_mactext->setMarkdownText(str);
|
||||
|
||||
_contentIsDirty = true;
|
||||
}
|
||||
|
||||
void MacTextWindow::clearText() {
|
||||
_mactext->clearText();
|
||||
|
||||
_contentIsDirty = true;
|
||||
_borderIsDirty = true;
|
||||
}
|
||||
|
||||
MacTextWindow::~MacTextWindow() {
|
||||
delete _mactext;
|
||||
}
|
||||
|
||||
void MacTextWindow::setTextWindowFont(const MacFont *font) {
|
||||
_font = font;
|
||||
|
||||
_fontRef = _wm->_fontMan->getFont(*font);
|
||||
|
||||
_mactext->setDefaultFormatting(font->getId(), font->getSlant(), font->getSize(), 0, 0, 0);
|
||||
}
|
||||
|
||||
const MacFont *MacTextWindow::getTextWindowFont() {
|
||||
return _font;
|
||||
}
|
||||
|
||||
bool MacTextWindow::draw(bool forceRedraw) {
|
||||
|
||||
uint32 now = g_system->getMillis();
|
||||
// check if we need to hide the scroll bar
|
||||
if (!(_wm->_mode & kWMModeWin95)) {
|
||||
if (_nextWheelEventTime != 0 && now >= _nextWheelEventTime) {
|
||||
if (_scrollDirection == kBorderNone && _clickedScrollPart == kBorderNone) {
|
||||
setScroll(0, 0); // hide the scrollbar
|
||||
_nextWheelEventTime = 0; // reset timer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handle mouse button scrolling
|
||||
if (_scrollDirection != kBorderNone) {
|
||||
Common::Point mousePos = g_system->getEventManager()->getMousePos();
|
||||
if (isInBorder(mousePos.x, mousePos.y) != _clickedScrollPart) {
|
||||
_scrollDirection = kBorderNone;
|
||||
setHighlight(kBorderNone);
|
||||
calcScrollBar();
|
||||
if (!(_wm->_mode & kWMModeWin95)) {
|
||||
setScroll(0, 0);
|
||||
}
|
||||
}
|
||||
if (_scrollDirection != kBorderNone && now >= _nextScrollTime) {
|
||||
if (_scrollDirection == kBorderScrollUp) {
|
||||
_mactext->scroll(-1);
|
||||
} else if (_scrollDirection == kBorderScrollDown) {
|
||||
_mactext->scroll(1);
|
||||
}
|
||||
calcScrollBar();
|
||||
_nextScrollTime = now + _scrollDelay;
|
||||
}
|
||||
}
|
||||
|
||||
bool needsContentRedraw = _contentIsDirty || _inputIsDirty || _mactext->needsRedraw() || forceRedraw;
|
||||
|
||||
if (!_borderIsDirty && !needsContentRedraw)
|
||||
return false;
|
||||
|
||||
if (_borderIsDirty || forceRedraw)
|
||||
drawBorder();
|
||||
|
||||
if (_inputIsDirty || forceRedraw) {
|
||||
drawInput();
|
||||
_inputIsDirty = false;
|
||||
needsContentRedraw = true; // input update needs a redraw
|
||||
}
|
||||
|
||||
if (needsContentRedraw) {
|
||||
// only clear the surface if we are actually going to redraw the text
|
||||
if (_wm->_mode & kWMModeWin95) {
|
||||
_composeSurface->clear(_bgcolor);
|
||||
} else {
|
||||
_composeSurface->clear(_wm->_colorWhite);
|
||||
}
|
||||
|
||||
_contentIsDirty = false;
|
||||
_mactext->draw(_composeSurface, forceRedraw);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacTextWindow::draw(ManagedSurface *g, bool forceRedraw) {
|
||||
if (!draw(forceRedraw))
|
||||
return false;
|
||||
|
||||
g->blitFrom(*_composeSurface, Common::Rect(0, 0, _composeSurface->w, _composeSurface->h), Common::Point(_innerDims.left, _innerDims.top));
|
||||
uint32 transcolor = (_wm->_pixelformat.bytesPerPixel == 1) ? _wm->_colorGreen : 0;
|
||||
g->transBlitFrom(_borderSurface, Common::Rect(0, 0, _borderSurface.w, _borderSurface.h), Common::Point(_dims.left, _dims.top), transcolor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacTextWindow::blit(ManagedSurface *g, Common::Rect &dest) {
|
||||
g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), dest, _wm->_colorGreen2);
|
||||
}
|
||||
|
||||
Common::U32String MacTextWindow::getSelection(bool formatted, bool newlines) {
|
||||
return _mactext->getSelection(formatted, newlines);
|
||||
}
|
||||
|
||||
int MacTextWindow::getMouseLine(int x, int y) {
|
||||
// TODO: Improve the algorithm here, since after long scrolling there is
|
||||
// sometimes error of +2 rows
|
||||
x -= getInnerDimensions().left;
|
||||
y -= getInnerDimensions().top + kConScrollStep;
|
||||
return _mactext->getMouseLine(x, y);
|
||||
}
|
||||
|
||||
void MacTextWindow::calcScrollBar() {
|
||||
// since this function only able for the window which has scroll bar
|
||||
// thus, if it doesn't has scrollbar, then we don't have to calc it
|
||||
if (!_hasScrollBar)
|
||||
return;
|
||||
|
||||
int maxText = 0, maxScrollbar = 0, displayHeight = 0;
|
||||
|
||||
displayHeight = getInnerDimensions().height();
|
||||
maxScrollbar = getDimensions().height() - getBorderOffsets().upperScrollHeight - getBorderOffsets().lowerScrollHeight;
|
||||
maxText = _mactext->getTextHeight();
|
||||
|
||||
// if we enable the win95 mode but the text height is smaller than window height, then we don't draw the scrollbar
|
||||
if (_wm->_mode & kWMModeWin95 && displayHeight > maxText && !_editable)
|
||||
return;
|
||||
|
||||
int maxScroll = 0;
|
||||
// identical to MacText scroll() logic
|
||||
if (_editable)
|
||||
maxScroll = maxText - kConScrollStep;
|
||||
else
|
||||
maxScroll = maxText - displayHeight;
|
||||
|
||||
float contentHeight = (float)(maxText + displayHeight);
|
||||
float scrollSize = (float)(maxScrollbar * displayHeight) / contentHeight;
|
||||
int range = maxScrollbar - (int)scrollSize - 1;
|
||||
|
||||
float ratio = CLIP<float>((float)_mactext->_scrollPos / (float)maxScroll, 0.0f, 1.0f);
|
||||
float scrollPos = ratio * (float)range;
|
||||
setScroll(scrollPos, scrollSize);
|
||||
}
|
||||
|
||||
void MacTextWindow::calcWin95Scroll(int &scrollAreaTop, int &scrollAreaHeight, int &barY, int &barHeight) {
|
||||
const BorderOffsets &offsets = getBorderOffsets();
|
||||
|
||||
scrollAreaTop = offsets.upperScrollHeight;
|
||||
scrollAreaHeight = _dims.height() - offsets.upperScrollHeight - offsets.lowerScrollHeight;
|
||||
|
||||
int contentHeight = _mactext->getTextHeight();
|
||||
int winHeight = getInnerDimensions().height();
|
||||
|
||||
// if content fits in the current window
|
||||
if (contentHeight <= winHeight || contentHeight == 0) {
|
||||
barHeight = scrollAreaHeight;
|
||||
barY = scrollAreaTop;
|
||||
return;
|
||||
}
|
||||
|
||||
float winRatio = (float)winHeight / (float)contentHeight;
|
||||
barHeight = MAX<int>(8, (int)(scrollAreaHeight * winRatio)); // 8 the min height of scrollBar
|
||||
|
||||
int maxTextScroll = contentHeight - winHeight;
|
||||
int maxBarScroll = scrollAreaHeight - barHeight;
|
||||
|
||||
float scrollAmount = (float)_mactext->_scrollPos / (float)maxTextScroll;
|
||||
|
||||
barY = scrollAreaTop + (int)(maxBarScroll * scrollAmount);
|
||||
}
|
||||
|
||||
bool MacTextWindow::processEvent(Common::Event &event) {
|
||||
WindowClick click = isInBorder(event.mouse.x, event.mouse.y);
|
||||
|
||||
if (!(g_system->getEventManager()->getButtonState() & Common::EventManager::LBUTTON)) {
|
||||
if (_isDragging) {
|
||||
_isDragging = false;
|
||||
}
|
||||
if (_clickedScrollPart != kBorderNone || _scrollDirection != kBorderNone) {
|
||||
_scrollDirection = kBorderNone;
|
||||
_clickedScrollPart = kBorderNone;
|
||||
setHighlight(kBorderNone);
|
||||
|
||||
if (!(_wm->_mode & kWMModeWin95)) {
|
||||
setScroll(0, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type == Common::EVENT_MOUSEMOVE) {
|
||||
if (!(_wm->_mode & kWMModeWin95)) {
|
||||
if (_clickedScrollPart == kBorderScrollUp || _clickedScrollPart == kBorderScrollDown) {
|
||||
if (click == kBorderScrollUp) {
|
||||
if (_scrollDirection != kBorderScrollUp) {
|
||||
_scrollDirection = kBorderScrollUp;
|
||||
_clickedScrollPart = kBorderScrollUp;
|
||||
setHighlight(kBorderScrollUp);
|
||||
calcScrollBar();
|
||||
}
|
||||
} else if (click == kBorderScrollDown) {
|
||||
if (_scrollDirection != kBorderScrollDown) {
|
||||
_scrollDirection = kBorderScrollDown;
|
||||
_clickedScrollPart = kBorderScrollDown;
|
||||
setHighlight(kBorderScrollDown);
|
||||
calcScrollBar();
|
||||
}
|
||||
} else {
|
||||
if (_scrollDirection != kBorderNone) {
|
||||
_scrollDirection = kBorderNone;
|
||||
setHighlight(kBorderNone);
|
||||
calcScrollBar();
|
||||
setScroll(0, 0);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if ((_wm->_mode & kWMModeWin95) && _isDragging) {
|
||||
int scrollAreaTop, scrollAreaHeight, barY, barHeight;
|
||||
calcWin95Scroll(scrollAreaTop, scrollAreaHeight, barY, barHeight);
|
||||
|
||||
int relMouseY = event.mouse.y - _dims.top;
|
||||
int diffY = relMouseY - _dragStartY;
|
||||
|
||||
if (diffY != 0) {
|
||||
int maxTextScroll = _mactext->getTextHeight() - getInnerDimensions().height();
|
||||
int maxBarScroll = scrollAreaHeight - barHeight;
|
||||
|
||||
if (maxBarScroll > 0) {
|
||||
float pixelsPerUnit = (float)maxTextScroll / (float)maxBarScroll;
|
||||
int newScrollPos = _dragStartScrollPos + (int)(diffY * pixelsPerUnit);
|
||||
|
||||
newScrollPos = CLIP<int>(newScrollPos, 0, maxTextScroll);
|
||||
|
||||
if (newScrollPos != _mactext->_scrollPos) {
|
||||
_mactext->_scrollPos = newScrollPos;
|
||||
_mactext->setDirty(true);
|
||||
_contentIsDirty = true;
|
||||
_borderIsDirty = true;
|
||||
calcScrollBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type == Common::EVENT_LBUTTONDOWN) {
|
||||
if ((_wm->_mode & kWMModeWin95) && (click == kBorderScrollUp || click == kBorderScrollDown)) {
|
||||
const BorderOffsets &offsets = getBorderOffsets();
|
||||
int scrollBarWidth = offsets.right;
|
||||
|
||||
if (event.mouse.x >= _dims.right - scrollBarWidth && event.mouse.x < _dims.right) {
|
||||
int scrollAreaTop, scrollAreaHeight, barY, barHeight;
|
||||
calcWin95Scroll(scrollAreaTop, scrollAreaHeight, barY, barHeight);
|
||||
|
||||
int relMouseY = event.mouse.y - _dims.top;
|
||||
|
||||
if (relMouseY >= barY && relMouseY < barY + barHeight) {
|
||||
_isDragging = true;
|
||||
_dragStartY = relMouseY; // store window relative Y
|
||||
_dragStartScrollPos = _mactext->_scrollPos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type == Common::EVENT_LBUTTONUP) {
|
||||
if (_isDragging) {
|
||||
_isDragging = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type == Common::EVENT_KEYDOWN) {
|
||||
if (!_editable)
|
||||
return false;
|
||||
|
||||
_wm->setActiveWindow(getId());
|
||||
|
||||
if (event.kbd.flags & (Common::KBD_ALT | Common::KBD_CTRL | Common::KBD_META)) {
|
||||
if (_mactext->processEvent(event))
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (event.kbd.keycode) {
|
||||
case Common::KEYCODE_BACKSPACE:
|
||||
if (!_inputText.empty()) {
|
||||
if (_mactext->hasSelection()) {
|
||||
_mactext->cutSelection();
|
||||
} else {
|
||||
_inputText.deleteLastChar();
|
||||
}
|
||||
_inputIsDirty = true;
|
||||
}
|
||||
return true;
|
||||
|
||||
case Common::KEYCODE_RETURN:
|
||||
undrawInput();
|
||||
_inputIsDirty = true; // we force it to redraw input
|
||||
return false; // Pass it to the higher level for processing
|
||||
|
||||
default:
|
||||
if (event.kbd.ascii == '~')
|
||||
return false;
|
||||
|
||||
if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) {
|
||||
if (_mactext->hasSelection())
|
||||
_mactext->cutSelection();
|
||||
_inputText += (char)event.kbd.ascii;
|
||||
_inputIsDirty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAllFocus()) // We are being dragged or resized
|
||||
return MacWindow::processEvent(event); // Pass it to upstream
|
||||
|
||||
if (event.type == Common::EVENT_WHEELUP) {
|
||||
//setHighlight(kBorderScrollUp);
|
||||
_mactext->scroll(-2);
|
||||
_contentIsDirty = true;
|
||||
calcScrollBar();
|
||||
|
||||
_nextWheelEventTime = g_system->getMillis() + SCROLLBAR_DELAY; // hide the bar after 300ms from now
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.type == Common::EVENT_WHEELDOWN) {
|
||||
//setHighlight(kBorderScrollDown);
|
||||
_mactext->scroll(2);
|
||||
_contentIsDirty = true;
|
||||
calcScrollBar();
|
||||
|
||||
_nextWheelEventTime = g_system->getMillis() + SCROLLBAR_DELAY; // hide the bar after 300ms from now
|
||||
return true;
|
||||
}
|
||||
|
||||
if (click == kBorderScrollUp || click == kBorderScrollDown) {
|
||||
if (event.type == Common::EVENT_LBUTTONDOWN) {
|
||||
setHighlight(click);
|
||||
_scrollDirection = click;
|
||||
_clickedScrollPart = click;
|
||||
calcScrollBar();
|
||||
return true;
|
||||
} else if (event.type == Common::EVENT_LBUTTONUP) {
|
||||
// reset scrolling state
|
||||
_scrollDirection = kBorderNone;
|
||||
_clickedScrollPart = kBorderNone;
|
||||
setHighlight(kBorderNone);
|
||||
// hide the scroll bar
|
||||
if (!(_wm->_mode & kWMModeWin95)) {
|
||||
setScroll(0, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.type == Common::EVENT_LBUTTONUP && _clickedScrollPart != kBorderNone) {
|
||||
_scrollDirection = kBorderNone;
|
||||
_clickedScrollPart = kBorderNone;
|
||||
setHighlight(kBorderNone);
|
||||
if (!(_wm->_mode & kWMModeWin95)) {
|
||||
setScroll(0, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (click == kBorderInner) {
|
||||
// Call callback for processing any events
|
||||
if (_callback)
|
||||
(*_callback)(click, event, _dataPtr);
|
||||
|
||||
if (!_selectable)
|
||||
return false;
|
||||
|
||||
event.mouse.x -= _innerDims.left;
|
||||
event.mouse.y -= _innerDims.top;
|
||||
return _mactext->processEvent(event);
|
||||
}
|
||||
|
||||
return MacWindow::processEvent(event);
|
||||
}
|
||||
|
||||
void MacTextWindow::undrawInput() {
|
||||
for (uint i = 0; i < _inputTextHeight; i++)
|
||||
_mactext->removeLastLine();
|
||||
|
||||
_inputTextHeight = 0;
|
||||
}
|
||||
|
||||
void MacTextWindow::drawInput() {
|
||||
if (!_editable)
|
||||
return;
|
||||
|
||||
int oldLen = _mactext->getLineCount() - _inputTextHeight;
|
||||
|
||||
// add new input line to the text
|
||||
appendText(_inputText, _font, true);
|
||||
|
||||
// Now recalc new text height
|
||||
int newLen = _mactext->getLineCount();
|
||||
_inputTextHeight = newLen - oldLen;
|
||||
|
||||
_contentIsDirty = true;
|
||||
}
|
||||
|
||||
void MacTextWindow::clearInput() {
|
||||
_inputText.clear();
|
||||
}
|
||||
|
||||
void MacTextWindow::appendInput(const Common::U32String &str) {
|
||||
_inputText += str;
|
||||
|
||||
drawInput();
|
||||
}
|
||||
|
||||
void MacTextWindow::appendInput(const Common::String &str) {
|
||||
appendInput(Common::U32String(str));
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
142
graphics/macgui/mactextwindow.h
Normal file
142
graphics/macgui/mactextwindow.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACTEXTWINDOW_H
|
||||
#define GRAPHICS_MACGUI_MACTEXTWINDOW_H
|
||||
|
||||
#include "graphics/macgui/macfontmanager.h"
|
||||
#include "graphics/macgui/mactext.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class MacTextWindow : public MacWindow {
|
||||
public:
|
||||
MacTextWindow(MacWindowManager *wm, const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, MacMenu *menu, int padding = 0);
|
||||
MacTextWindow(MacWindowManager *wm, const Font *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, MacMenu *menu, int padding = 0);
|
||||
virtual ~MacTextWindow();
|
||||
|
||||
virtual void resize(int w, int h) override;
|
||||
void setDimensions(const Common::Rect &r) override;
|
||||
|
||||
virtual bool processEvent(Common::Event &event) override;
|
||||
|
||||
virtual bool draw(ManagedSurface *g, bool forceRedraw = false) override;
|
||||
virtual bool draw(bool forceRedraw = false) override;
|
||||
virtual void blit(ManagedSurface *g, Common::Rect &dest) override;
|
||||
|
||||
void setTextWindowFont(const MacFont *macFont);
|
||||
const MacFont *getTextWindowFont();
|
||||
|
||||
void appendText(const Common::U32String &str, const MacFont *macFont = nullptr, bool skipAdd = false);
|
||||
void appendText(const Common::String &str, const MacFont *macFont = nullptr, bool skipAdd = false);
|
||||
void clearText();
|
||||
void setMarkdownText(const Common::U32String &str);
|
||||
|
||||
void setEditable(bool editable) { _editable = editable; _mactext->setEditable(editable); }
|
||||
void setActive(bool active) override { MacWindow::setActive(active); if (_editable) _mactext->setActive(active); }
|
||||
void setSelectable(bool selectable) { _selectable = selectable; }
|
||||
|
||||
const Common::U32String &getInput() { return _inputText; }
|
||||
void clearInput();
|
||||
void appendInput(const Common::U32String &str);
|
||||
void appendInput(const Common::String &str);
|
||||
|
||||
Common::U32String getSelection(bool formatted = false, bool newlines = true);
|
||||
void clearSelection() { _mactext->clearSelection(); }
|
||||
Common::U32String cutSelection() { return _mactext->cutSelection(); }
|
||||
const SelectedText *getSelectedText() { return _mactext->getSelectedText(); }
|
||||
uint32 getTextColor() { return _mactext->getTextColor(); }
|
||||
uint32 getTextColor(int start, int end) { return _mactext->getTextColor(start, end); }
|
||||
void setTextColor(uint32 color, int start, int end) { return _mactext->setTextColor(color, start, end); }
|
||||
int getTextFont() { return _mactext->getTextFont(); }
|
||||
int getTextFont(int start, int end) { return _mactext->getTextFont(start, end); }
|
||||
int getTextSlant() { return _mactext->getTextSlant(); }
|
||||
int getTextSlant(int start, int end) { return _mactext->getTextSlant(start, end); }
|
||||
int getTextHeight() { return _mactext->getTextHeight(); }
|
||||
int getLineHeight(int line) { return _mactext->getLineHeight(line); }
|
||||
Common::U32String getTextChunk(int startRow, int startCol, int endRow, int endCol, bool formatted = false, bool newlines = true) { return _mactext->getTextChunk(startRow, startCol, endRow, endCol, formatted, newlines); }
|
||||
Common::U32String getPlainText() { return _mactext->getPlainText(); }
|
||||
Common::U32String getEditedString() { return _mactext->getEditedString(); };
|
||||
void enforceTextFont(uint16 fontId) { return _mactext->enforceTextFont(fontId); }
|
||||
void setTextFont(uint16 fontId, int start, int end) { return _mactext->setTextFont(fontId, start, end); }
|
||||
void enforceTextSlant(int textSlant) { return _mactext->enforceTextSlant(textSlant); }
|
||||
void setTextSlant(int textSlant, int start, int end) { return _mactext->setTextSlant(textSlant, start, end); }
|
||||
int getRowCount() { return _mactext->getRowCount(); }
|
||||
int getLineSpacing() { return _mactext->getLineSpacing(); }
|
||||
int getTextSize() { return _mactext->getTextSize(); }
|
||||
int getTextSize(int start, int end) { return _mactext->getTextSize(start, end); }
|
||||
void setTextSize(int textSize) { return _mactext->setTextSize(textSize); }
|
||||
void setTextSize(int textSize, int start, int end) { return _mactext->setTextSize(textSize, start, end); }
|
||||
|
||||
int getMouseLine(int x, int y);
|
||||
|
||||
virtual void setBorderColor(uint32 color) override { _mactext->setBorderColor(color); }
|
||||
/**
|
||||
* if we want to draw the text which color is not black, then we need to set _textColorRGB
|
||||
* @param rgb text color you want to draw
|
||||
*/
|
||||
void setTextColorRGB (uint32 rgb) { _textColorRGB = rgb; }
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
void calcScrollBar();
|
||||
|
||||
void undrawInput();
|
||||
void drawInput();
|
||||
void drawSelection();
|
||||
|
||||
void calcWin95Scroll(int &scrollAreaTop, int &scrollAreaHeight, int &barY, int &barHeight);
|
||||
|
||||
public:
|
||||
bool _editable;
|
||||
bool _selectable;
|
||||
|
||||
private:
|
||||
MacText *_mactext;
|
||||
const MacFont *_font;
|
||||
const Font *_fontRef;
|
||||
|
||||
int _maxWidth;
|
||||
Common::U32String _inputText;
|
||||
uint _inputTextHeight;
|
||||
bool _inputIsDirty;
|
||||
|
||||
WindowClick _scrollDirection;
|
||||
uint32 _nextScrollTime;
|
||||
uint32 _scrollDelay;
|
||||
uint32 _nextWheelEventTime;
|
||||
WindowClick _clickedScrollPart;
|
||||
|
||||
// dragging bar for win95
|
||||
bool _isDragging;
|
||||
int _dragStartY;
|
||||
int _dragStartScrollPos;
|
||||
|
||||
MacMenu *_menu;
|
||||
|
||||
int _bgcolor;
|
||||
int _textColorRGB;
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
176
graphics/macgui/macwidget.cpp
Normal file
176
graphics/macgui/macwidget.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/macgui/macwindowmanager.h"
|
||||
#include "graphics/macgui/macwidget.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
MacWidget::MacWidget(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, bool focusable, uint16 border, uint16 gutter, uint16 shadow, uint32 fgcolor, uint32 bgcolor) :
|
||||
_focusable(focusable), _parent(parent), _border(border), _gutter(gutter), _shadow(shadow), _wm(wm) {
|
||||
_contentIsDirty = true;
|
||||
_priority = 0;
|
||||
|
||||
_dims.left = x;
|
||||
_dims.right = x + w + (2 * border) + (2 * gutter) + shadow;
|
||||
_dims.top = y;
|
||||
_dims.bottom = y + h + (2 * border) + gutter + shadow;
|
||||
|
||||
_fgcolor = fgcolor;
|
||||
_bgcolor = bgcolor;
|
||||
|
||||
if (parent)
|
||||
parent->_children.push_back(this);
|
||||
|
||||
_composeSurface = new ManagedSurface(_dims.width(), _dims.height(), _wm->_pixelformat);
|
||||
_composeSurface->clear(_bgcolor);
|
||||
|
||||
_active = false;
|
||||
_editable = false;
|
||||
|
||||
_borderColor = 0xff;
|
||||
}
|
||||
|
||||
MacWidget::~MacWidget() {
|
||||
if (_parent)
|
||||
_parent->removeWidget(this, false);
|
||||
|
||||
if (_wm)
|
||||
_wm->clearWidgetRefs(this);
|
||||
|
||||
if (_composeSurface) {
|
||||
_composeSurface->free();
|
||||
delete _composeSurface;
|
||||
}
|
||||
}
|
||||
|
||||
void MacWidget::setActive(bool active) {
|
||||
if (!_focusable)
|
||||
return;
|
||||
|
||||
if (active == _active)
|
||||
return;
|
||||
|
||||
_active = active;
|
||||
}
|
||||
|
||||
bool MacWidget::draw(bool forceRedraw) {
|
||||
_contentIsDirty = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacWidget::draw(ManagedSurface *g, bool forceRedraw) {
|
||||
_contentIsDirty = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacWidget::blit(ManagedSurface *g, Common::Rect &dest) {
|
||||
g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), dest, _wm->_colorGreen2);
|
||||
}
|
||||
|
||||
void MacWidget::setColors(uint32 fg, uint32 bg) {
|
||||
_fgcolor = fg;
|
||||
_bgcolor = bg;
|
||||
|
||||
_contentIsDirty = true;
|
||||
}
|
||||
|
||||
bool MacWidget::processEvent(Common::Event &event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacWidget::removeWidget(MacWidget *child, bool del) {
|
||||
if (_children.size() == 0)
|
||||
return;
|
||||
|
||||
for (uint i = 0; i < _children.size(); i++) {
|
||||
if (_children[i] == child) {
|
||||
if (del)
|
||||
delete _children[i];
|
||||
|
||||
_children.remove_at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MacWidget *MacWidget::findEventHandler(Common::Event &event, int dx, int dy) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
{
|
||||
Common::Point pos;
|
||||
|
||||
pos = g_system->getEventManager()->getMousePos();
|
||||
|
||||
if (_dims.contains(pos.x - dx, pos.y - dy)) {
|
||||
uint priority = 0;
|
||||
MacWidget *widget = nullptr;
|
||||
|
||||
for (uint i = 0; i < _children.size(); i++) {
|
||||
MacWidget *res = _children[i]->findEventHandler(event, dx + _dims.left, dy + _dims.top);
|
||||
if (res && res->_priority > priority) {
|
||||
priority = res->_priority;
|
||||
widget = res;
|
||||
}
|
||||
}
|
||||
return widget ? widget : this;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Common::EVENT_KEYDOWN:
|
||||
break;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Common::Point MacWidget::getAbsolutePos() {
|
||||
Common::Point absPoint = Common::Point(0, 0);
|
||||
MacWidget *currentParent = _parent;
|
||||
while (currentParent != nullptr) {
|
||||
absPoint = Common::Point(currentParent->_dims.left, currentParent->_dims.top) + absPoint;
|
||||
currentParent = currentParent->_parent;
|
||||
}
|
||||
|
||||
return absPoint;
|
||||
}
|
||||
|
||||
Common::Rect MacWidget::getAbsoluteDimensions() {
|
||||
Common::Point absPos = getAbsolutePos();
|
||||
Common::Rect dims = getDimensions();
|
||||
|
||||
dims.translate(absPos.x, absPos.y);
|
||||
|
||||
return dims;
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
118
graphics/macgui/macwidget.h
Normal file
118
graphics/macgui/macwidget.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACWIDGET_H
|
||||
#define GRAPHICS_MACGUI_MACWIDGET_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/events.h"
|
||||
#include "common/rect.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Common {
|
||||
struct Event;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class ManagedSurface;
|
||||
class MacWindowManager;
|
||||
|
||||
class MacWidget {
|
||||
|
||||
public:
|
||||
MacWidget(MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, bool focusable, uint16 border = 0, uint16 gutter = 0, uint16 shadow = 0, uint32 fgcolor = 0, uint32 bgcolor= 0xff);
|
||||
virtual ~MacWidget();
|
||||
|
||||
/**
|
||||
* Accessor method for the complete dimensions of the widget.
|
||||
* @return Dimensions of the widget relative to the parent's position.
|
||||
*/
|
||||
const Common::Rect &getDimensions() { return _dims; }
|
||||
|
||||
/**
|
||||
* Method for indicating whether the widget is active or inactive.
|
||||
* Used by the WM to handle focus on windows, etc.
|
||||
* @param active Desired state of the widget.
|
||||
*/
|
||||
virtual void setActive(bool active);
|
||||
|
||||
/**
|
||||
* Method for marking the widget for redraw.
|
||||
* @param dirty True if the widget needs to be redrawn.
|
||||
*/
|
||||
void setDirty(bool dirty) { _contentIsDirty = dirty; }
|
||||
|
||||
virtual bool needsRedraw() { return _contentIsDirty; }
|
||||
|
||||
virtual bool draw(ManagedSurface *g, bool forceRedraw = false);
|
||||
virtual bool draw(bool forceRedraw = false);
|
||||
virtual void blit(ManagedSurface *g, Common::Rect &dest);
|
||||
virtual bool processEvent(Common::Event &event);
|
||||
virtual bool hasAllFocus() { return _active; }
|
||||
virtual bool isEditable() { return _editable; }
|
||||
|
||||
virtual void setColors(uint32 fg, uint32 bg);
|
||||
virtual void setBorderColor(uint32 color) {
|
||||
_borderColor = color;
|
||||
_contentIsDirty = true;
|
||||
}
|
||||
|
||||
virtual void setDimensions(const Common::Rect &r) {
|
||||
_dims = r;
|
||||
}
|
||||
|
||||
Common::Point getAbsolutePos();
|
||||
Common::Rect getAbsoluteDimensions();
|
||||
MacWidget *findEventHandler(Common::Event &event, int dx, int dy);
|
||||
|
||||
void removeWidget(MacWidget *child, bool del = true);
|
||||
|
||||
Graphics::ManagedSurface *getSurface() { return _composeSurface; }
|
||||
|
||||
protected:
|
||||
uint16 _border;
|
||||
uint16 _gutter;
|
||||
uint16 _shadow;
|
||||
uint32 _borderColor;
|
||||
|
||||
uint32 _fgcolor, _bgcolor;
|
||||
|
||||
Graphics::ManagedSurface *_composeSurface;
|
||||
|
||||
bool _contentIsDirty;
|
||||
|
||||
public:
|
||||
bool _focusable;
|
||||
bool _active;
|
||||
bool _editable;
|
||||
uint _priority;
|
||||
|
||||
Common::Rect _dims;
|
||||
|
||||
MacWindowManager *_wm;
|
||||
MacWidget *_parent;
|
||||
Common::Array<MacWidget *> _children;
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
728
graphics/macgui/macwindow.cpp
Normal file
728
graphics/macgui/macwindow.cpp
Normal file
@@ -0,0 +1,728 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/primitives.h"
|
||||
#include "common/events.h"
|
||||
#include "graphics/macgui/macfontmanager.h"
|
||||
#include "graphics/macgui/macwindowmanager.h"
|
||||
#include "graphics/macgui/macwindow.h"
|
||||
#include "graphics/macgui/macwidget.h"
|
||||
#include "image/bmp.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
BaseMacWindow::BaseMacWindow(int id, bool editable, MacWindowManager *wm) :
|
||||
MacWidget(nullptr, 0, 0, 0, 0, wm, true), _id(id), _editable(editable) {
|
||||
_callback = 0;
|
||||
_dataPtr = 0;
|
||||
|
||||
_contentIsDirty = true;
|
||||
|
||||
_type = kWindowUnknown;
|
||||
|
||||
_visible = true;
|
||||
|
||||
_draggable = true;
|
||||
}
|
||||
|
||||
void BaseMacWindow::setVisible(bool visible, bool silent) { _visible = visible; _wm->setFullRefresh(true); }
|
||||
|
||||
bool BaseMacWindow::isVisible() { return _visible; }
|
||||
|
||||
MacWindow::MacWindow(int id, bool scrollable, bool resizable, bool editable, MacWindowManager *wm) :
|
||||
BaseMacWindow(id, editable, wm), _scrollable(scrollable), _resizable(resizable) {
|
||||
_borderIsDirty = true;
|
||||
|
||||
_pattern = 0;
|
||||
_hasPattern = false;
|
||||
|
||||
_highlightedPart = kBorderNone;
|
||||
|
||||
_beingDragged = false;
|
||||
_beingResized = false;
|
||||
|
||||
_draggedX = _draggedY = 0;
|
||||
|
||||
_type = kWindowWindow;
|
||||
|
||||
_closeable = false;
|
||||
_isTitleVisible = true;
|
||||
|
||||
_borderType = -1;
|
||||
_borderWidth = kBorderWidth;
|
||||
|
||||
_macBorder.setWindow(this);
|
||||
_macBorder.setWindowManager(wm);
|
||||
|
||||
_hasScrollBar = false;
|
||||
|
||||
_mode = 0;
|
||||
}
|
||||
|
||||
MacWindow::MacWindow(const MacWindow &source) :
|
||||
BaseMacWindow(source),
|
||||
|
||||
_borderIsDirty(source._borderIsDirty),
|
||||
_innerDims(source._innerDims),
|
||||
_dirtyRects(source._dirtyRects),
|
||||
_hasScrollBar(source._hasScrollBar),
|
||||
_mode(source._mode),
|
||||
|
||||
_macBorder(source._macBorder),
|
||||
_pattern(source._pattern),
|
||||
_hasPattern(source._hasPattern),
|
||||
_scrollable(source._scrollable),
|
||||
_resizable(source._resizable),
|
||||
_closeable(source._closeable),
|
||||
_isTitleVisible(source._isTitleVisible),
|
||||
_borderWidth(source._borderWidth),
|
||||
|
||||
_beingDragged(source._beingDragged),
|
||||
_beingResized(source._beingResized),
|
||||
_draggedX(source._draggedX),
|
||||
_draggedY(source._draggedY),
|
||||
_highlightedPart(source._highlightedPart),
|
||||
|
||||
_title(source._title),
|
||||
_shadowedTitle(source._shadowedTitle),
|
||||
_borderType(source._borderType) {
|
||||
|
||||
// The copy constructor of ManagedSurface is deprecated
|
||||
// Need to use copyFrom
|
||||
_borderSurface.copyFrom(source._borderSurface);
|
||||
|
||||
}
|
||||
|
||||
void MacWindow::disableBorder() {
|
||||
_macBorder.disableBorder();
|
||||
}
|
||||
|
||||
const Font *MacWindow::getTitleFont() {
|
||||
return _wm->_fontMan->getFont(Graphics::MacFont(kMacFontSystem, 12));
|
||||
}
|
||||
|
||||
void MacWindow::setActive(bool active) {
|
||||
bool changed = (active != _active);
|
||||
|
||||
MacWidget::setActive(active);
|
||||
|
||||
_borderIsDirty = true;
|
||||
|
||||
if (changed) {
|
||||
WindowClick click = active ? kBorderActivate : kBorderDeactivate;
|
||||
Common::Event event;
|
||||
if (_callback)
|
||||
_callback(click, event, _dataPtr);
|
||||
}
|
||||
}
|
||||
|
||||
bool MacWindow::isActive() const { return _active; }
|
||||
|
||||
void MacWindow::resize(int w, int h) {
|
||||
w = MAX(w, (int)kWindowMinWidth);
|
||||
h = MAX(h, (int)kWindowMinHeight);
|
||||
if (_composeSurface->w == w && _composeSurface->h == h)
|
||||
return;
|
||||
|
||||
_dims.setWidth(w);
|
||||
_dims.setHeight(h);
|
||||
updateInnerDims();
|
||||
|
||||
rebuildSurface();
|
||||
}
|
||||
|
||||
void MacWindow::resizeInner(int w, int h) {
|
||||
if (_composeSurface->w == w && _composeSurface->h == h)
|
||||
return;
|
||||
|
||||
_innerDims.setWidth(w);
|
||||
_innerDims.setHeight(h);
|
||||
updateOuterDims();
|
||||
|
||||
rebuildSurface();
|
||||
}
|
||||
|
||||
void MacWindow::rebuildSurface() {
|
||||
_composeSurface->free();
|
||||
_composeSurface->create(_innerDims.width(), _innerDims.height(), _wm->_pixelformat);
|
||||
|
||||
if (_hasPattern)
|
||||
drawPattern();
|
||||
|
||||
_borderSurface.free();
|
||||
_borderSurface.create(_dims.width(), _dims.height(), _wm->_pixelformat);
|
||||
|
||||
_contentIsDirty = true;
|
||||
_borderIsDirty = true;
|
||||
_wm->setFullRefresh(true);
|
||||
}
|
||||
|
||||
void MacWindow::move(int x, int y) {
|
||||
if (_dims.left == x && _dims.top == y)
|
||||
return;
|
||||
|
||||
_dims.moveTo(x, y);
|
||||
updateInnerDims();
|
||||
|
||||
_contentIsDirty = true;
|
||||
_wm->setFullRefresh(true);
|
||||
}
|
||||
|
||||
void MacWindow::setDimensions(const Common::Rect &r) {
|
||||
resize(r.width(), r.height());
|
||||
_dims.moveTo(r.left, r.top);
|
||||
updateInnerDims();
|
||||
|
||||
_contentIsDirty = true;
|
||||
_wm->setFullRefresh(true);
|
||||
}
|
||||
|
||||
void MacWindow::setInnerDimensions(const Common::Rect &r) {
|
||||
resizeInner(r.width(), r.height());
|
||||
_innerDims.moveTo(r.left, r.top);
|
||||
updateOuterDims();
|
||||
|
||||
_contentIsDirty = true;
|
||||
_wm->setFullRefresh(true);
|
||||
}
|
||||
|
||||
void MacWindow::setBackgroundPattern(int pattern) {
|
||||
_pattern = pattern;
|
||||
_hasPattern = true;
|
||||
drawPattern();
|
||||
_contentIsDirty = true;
|
||||
}
|
||||
|
||||
bool MacWindow::draw(bool forceRedraw) {
|
||||
if (!_borderIsDirty && !_contentIsDirty && !forceRedraw)
|
||||
return false;
|
||||
|
||||
if (_borderIsDirty || forceRedraw)
|
||||
drawBorder();
|
||||
|
||||
_contentIsDirty = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacWindow::draw(ManagedSurface *g, bool forceRedraw) {
|
||||
if (!draw(forceRedraw))
|
||||
return false;
|
||||
|
||||
g->blitFrom(*_composeSurface, Common::Rect(0, 0, _composeSurface->w, _composeSurface->h), Common::Point(_innerDims.left, _innerDims.top));
|
||||
|
||||
uint32 transcolor = (_wm->_pixelformat.bytesPerPixel == 1) ? _wm->_colorGreen : 0;
|
||||
|
||||
g->transBlitFrom(_borderSurface, Common::Rect(0, 0, _borderSurface.w, _borderSurface.h), Common::Point(_dims.left, _dims.top), transcolor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacWindow::blit(ManagedSurface *g, Common::Rect &dest) {
|
||||
// Only the inner surface is blitted here
|
||||
uint32 transcolor = (_wm->_pixelformat.bytesPerPixel == 1) ? _wm->_colorGreen2 : 0;
|
||||
|
||||
g->transBlitFrom(*_composeSurface, _composeSurface->getBounds(), dest, transcolor);
|
||||
}
|
||||
|
||||
uint32 MacWindow::getBorderFlags() const {
|
||||
uint32 flags = 0;
|
||||
if (_active)
|
||||
flags |= kWindowBorderActive;
|
||||
if (!_title.empty() && _borderType != 0x02 && _borderType != 0x03 && _borderType != 0x0a && _borderType != 0x0b)
|
||||
flags |= kWindowBorderTitle;
|
||||
if (_hasScrollBar)
|
||||
flags |= kWindowBorderScrollbar;
|
||||
return flags;
|
||||
}
|
||||
|
||||
void MacWindow::center(bool toCenter) {
|
||||
if (!_wm)
|
||||
return;
|
||||
|
||||
Common::Rect screen = _wm->getScreenBounds();
|
||||
|
||||
uint32 flags = getBorderFlags();
|
||||
if (toCenter) {
|
||||
move((screen.width() - _dims.width()) / 2, (screen.height() - _dims.height()) / 2);
|
||||
} else if (_macBorder.hasBorder(flags) && _macBorder.hasOffsets()) {
|
||||
move(_macBorder.getOffset().left, _macBorder.getOffset().top);
|
||||
} else {
|
||||
move(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindow::updateInnerDims() {
|
||||
if (_dims.isEmpty())
|
||||
return;
|
||||
|
||||
uint32 flags = getBorderFlags();
|
||||
|
||||
if (_macBorder.hasBorder(flags) && _macBorder.hasOffsets()) {
|
||||
_innerDims = Common::Rect(
|
||||
_dims.left + _macBorder.getOffset().left,
|
||||
_dims.top + _macBorder.getOffset().top,
|
||||
_dims.right - _macBorder.getOffset().right,
|
||||
_dims.bottom - _macBorder.getOffset().bottom);
|
||||
} else {
|
||||
_innerDims = _dims;
|
||||
_innerDims.grow(-kBorderWidth);
|
||||
}
|
||||
// Prevent negative dimensions
|
||||
_innerDims.right = MAX(_innerDims.left, _innerDims.right);
|
||||
_innerDims.bottom = MAX(_innerDims.top, _innerDims.bottom);
|
||||
}
|
||||
|
||||
void MacWindow::updateOuterDims() {
|
||||
if (_innerDims.isEmpty())
|
||||
return;
|
||||
|
||||
uint32 flags = getBorderFlags();
|
||||
|
||||
if (_macBorder.hasBorder(flags) && _macBorder.hasOffsets()) {
|
||||
_dims = Common::Rect(
|
||||
_innerDims.left - _macBorder.getOffset().left,
|
||||
_innerDims.top - _macBorder.getOffset().top,
|
||||
_innerDims.right + _macBorder.getOffset().right,
|
||||
_innerDims.bottom + _macBorder.getOffset().bottom);
|
||||
} else {
|
||||
_dims = _innerDims;
|
||||
_dims.grow(kBorderWidth);
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindow::drawBorder() {
|
||||
resizeBorderSurface();
|
||||
|
||||
_borderIsDirty = false;
|
||||
|
||||
ManagedSurface *g = &_borderSurface;
|
||||
|
||||
uint32 flags = getBorderFlags();
|
||||
|
||||
if (_macBorder.hasBorder(flags)) {
|
||||
drawBorderFromSurface(g, flags);
|
||||
} else {
|
||||
warning("MacWindow: No Border Loaded");
|
||||
setBorderType(0xff);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_highlightedPart == kBorderScrollUp || _highlightedPart == kBorderScrollDown) {
|
||||
_macBorder.drawScrollBar(g);
|
||||
|
||||
_highlightedPart = kBorderNone;
|
||||
|
||||
setHighlight(kBorderNone);
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindow::drawBorderFromSurface(ManagedSurface *g, uint32 flags) {
|
||||
if (_wm->_pixelformat.bytesPerPixel == 1) {
|
||||
g->clear(_wm->_colorGreen);
|
||||
}
|
||||
|
||||
_macBorder.blitBorderInto(*g, flags);
|
||||
}
|
||||
|
||||
void MacWindow::setTitle(const Common::String &title) {
|
||||
if (!_isTitleVisible) {
|
||||
// Title hidden right now, so don't propagate the change but just cache it up for later
|
||||
_shadowedTitle = title;
|
||||
return;
|
||||
}
|
||||
|
||||
_title = title;
|
||||
_borderIsDirty = true;
|
||||
_macBorder.setTitle(title, _borderSurface.w);
|
||||
}
|
||||
|
||||
void MacWindow::setTitleVisible(bool visible) {
|
||||
if (_isTitleVisible && !visible) {
|
||||
_shadowedTitle = _title;
|
||||
setTitle("");
|
||||
_isTitleVisible = visible;
|
||||
} else if (!_isTitleVisible && visible) {
|
||||
_title = _shadowedTitle;
|
||||
_isTitleVisible = visible;
|
||||
setTitle(_title);
|
||||
}
|
||||
}
|
||||
|
||||
bool MacWindow::isTitleVisible() {
|
||||
return _isTitleVisible;
|
||||
}
|
||||
|
||||
void MacWindow::drawPattern() {
|
||||
const byte *pat = _wm->getPatterns()[_pattern - 1];
|
||||
for (int y = 0; y < _composeSurface->h; y++) {
|
||||
for (int x = 0; x < _composeSurface->w; x++) {
|
||||
if (_wm->_pixelformat.bytesPerPixel == 1) {
|
||||
byte *dst = (byte *)_composeSurface->getBasePtr(x, y);
|
||||
if (pat[y % 8] & (1 << (7 - (x % 8))))
|
||||
*dst = _wm->_colorBlack;
|
||||
else
|
||||
*dst = _wm->_colorWhite;
|
||||
} else {
|
||||
uint32 *dst = (uint32 *)_composeSurface->getBasePtr(x, y);
|
||||
if (pat[y % 8] & (1 << (7 - (x % 8))))
|
||||
*dst = _wm->_colorBlack;
|
||||
else
|
||||
*dst = _wm->_colorWhite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindow::setHighlight(WindowClick highlightedPart) {
|
||||
if (_highlightedPart == highlightedPart)
|
||||
return;
|
||||
|
||||
_highlightedPart = highlightedPart;
|
||||
_borderIsDirty = true;
|
||||
}
|
||||
|
||||
void MacWindow::setScroll(float scrollPos, float scrollSize) {
|
||||
_macBorder.setScroll(scrollPos, scrollSize);
|
||||
_borderIsDirty = true;
|
||||
}
|
||||
|
||||
void MacWindow::loadBorder(Common::SeekableReadStream &file, uint32 flags, int lo, int ro, int to, int bo) {
|
||||
_macBorder.loadBorder(file, flags, lo, ro, to, bo);
|
||||
}
|
||||
|
||||
void MacWindow::loadBorder(Common::SeekableReadStream &file, uint32 flags, const BorderOffsets &offsets) {
|
||||
_macBorder.loadBorder(file, flags, offsets);
|
||||
}
|
||||
|
||||
void MacWindow::setBorder(Graphics::ManagedSurface *surface, uint32 flags, const BorderOffsets &offsets) {
|
||||
_macBorder.setBorder(surface, flags, offsets);
|
||||
}
|
||||
|
||||
void MacWindow::resizeBorderSurface() {
|
||||
updateOuterDims();
|
||||
|
||||
if (_borderSurface.w != _dims.width() || _borderSurface.h != _dims.height()) {
|
||||
_borderSurface.free();
|
||||
_borderSurface.create(_dims.width(), _dims.height(), _wm->_pixelformat);
|
||||
}
|
||||
}
|
||||
|
||||
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, _wm->_colorWhite);
|
||||
g->frameRect(r, _wm->_colorBlack);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
WindowClick MacWindow::isInBorder(int x, int y) const {
|
||||
if (_innerDims.contains(x, y))
|
||||
return kBorderInner;
|
||||
|
||||
if (isInCloseButton(x, y))
|
||||
return kBorderCloseButton;
|
||||
|
||||
if (_resizable)
|
||||
if (isInResizeButton(x, y))
|
||||
return kBorderResizeButton;
|
||||
|
||||
if (_scrollable)
|
||||
return isInScroll(x, y);
|
||||
|
||||
return kBorderBorder;
|
||||
}
|
||||
|
||||
bool MacWindow::isInCloseButton(int x, int y) const {
|
||||
int bLeft = kBorderWidth;
|
||||
int bTop = kBorderWidth;
|
||||
if (_macBorder.hasOffsets()) {
|
||||
bLeft = _macBorder.getOffset().left;
|
||||
bTop = _macBorder.getOffset().top;
|
||||
}
|
||||
if (_macBorder.getOffset().closeButtonTop > -1 && _macBorder.getOffset().closeButtonLeft > -1 &&
|
||||
_macBorder.getOffset().closeButtonWidth > 0) {
|
||||
int closeButtonTop = _macBorder.getOffset().closeButtonTop;
|
||||
int closeButtonLeft = _macBorder.getOffset().closeButtonLeft;
|
||||
int closeWidth = _macBorder.getOffset().closeButtonWidth;
|
||||
return (x >= _innerDims.left + closeButtonLeft && x < _innerDims.left + closeButtonLeft + closeWidth && y >= _innerDims.top - closeButtonTop && y < _innerDims.top - closeButtonTop + closeWidth);
|
||||
}
|
||||
return (x >= _innerDims.left - bLeft && x < _innerDims.left && y >= _innerDims.top - bTop && y < _innerDims.top);
|
||||
}
|
||||
|
||||
bool MacWindow::isInResizeButton(int x, int y) const {
|
||||
int bRight = kBorderWidth;
|
||||
int bBottom = kBorderWidth;
|
||||
if (_macBorder.hasOffsets()) {
|
||||
bRight = _macBorder.getOffset().right;
|
||||
bBottom = _macBorder.getOffset().bottom;
|
||||
}
|
||||
if (_macBorder.getOffset().resizeButtonTop > -1 && _macBorder.getOffset().resizeButtonHeight > 0) {
|
||||
int resizeButtonTop = _macBorder.getOffset().resizeButtonTop;
|
||||
int resizeHeight = _macBorder.getOffset().resizeButtonHeight;
|
||||
|
||||
if (bBottom != resizeButtonTop) {
|
||||
return (x >= _innerDims.right && x < _innerDims.right + bRight && y >= _innerDims.bottom - resizeHeight && y < _innerDims.bottom);
|
||||
}
|
||||
}
|
||||
return (x >= _innerDims.right && x < _innerDims.right + bRight && y >= _innerDims.bottom && y < _innerDims.bottom + bBottom);
|
||||
}
|
||||
|
||||
WindowClick MacWindow::isInScroll(int x, int y) const {
|
||||
int bTop = kBorderWidth;
|
||||
int bRight = kBorderWidth;
|
||||
int bBottom = kBorderWidth;
|
||||
if (_macBorder.hasOffsets()) {
|
||||
bTop = _macBorder.getOffset().top;
|
||||
bRight = _macBorder.getOffset().right;
|
||||
bBottom = _macBorder.getOffset().bottom;
|
||||
}
|
||||
|
||||
if (x >= _innerDims.right && x < _innerDims.right + bRight) {
|
||||
if (y < _innerDims.top - bTop)
|
||||
return kBorderBorder;
|
||||
|
||||
if (y >= _innerDims.bottom + bBottom)
|
||||
return kBorderBorder;
|
||||
|
||||
if (y >= _innerDims.top + _innerDims.height() / 2)
|
||||
return kBorderScrollDown;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool MacWindow::processEvent(Common::Event &event) {
|
||||
WindowClick click = isInBorder(event.mouse.x, event.mouse.y);
|
||||
|
||||
bool result = false;
|
||||
|
||||
switch (event.type) {
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
if (_wm->_mouseDown && _wm->_hoveredWidget && !_wm->_hoveredWidget->_dims.contains(event.mouse.x - _dims.left, event.mouse.y - _dims.top)) {
|
||||
_wm->_hoveredWidget->setActive(false);
|
||||
// since we de-active the hoveredWidget, so we need to check whether it's the activeWidget of wm
|
||||
if (_wm->getActiveWidget() == _wm->_hoveredWidget)
|
||||
_wm->setActiveWidget(nullptr);
|
||||
_wm->_hoveredWidget = nullptr;
|
||||
}
|
||||
|
||||
if (_beingDragged && _draggable) {
|
||||
_dims.translate(event.mouse.x - _draggedX, event.mouse.y - _draggedY);
|
||||
updateInnerDims();
|
||||
|
||||
_draggedX = event.mouse.x;
|
||||
_draggedY = event.mouse.y;
|
||||
|
||||
_wm->setFullRefresh(true);
|
||||
}
|
||||
|
||||
if (_beingResized) {
|
||||
int minWidth = _borderWidth * 4;
|
||||
int minHeight = minWidth;
|
||||
|
||||
uint32 flags = getBorderFlags();
|
||||
if (_macBorder.hasBorder(flags) && _macBorder.hasOffsets()) {
|
||||
minWidth = MAX(minWidth, _macBorder.getMinWidth(flags));
|
||||
minHeight = MAX(minHeight, _macBorder.getMinHeight(flags));
|
||||
}
|
||||
|
||||
resize(MAX(minWidth, _dims.width() + event.mouse.x - _draggedX),
|
||||
MAX(minHeight, _dims.height() + event.mouse.y - _draggedY));
|
||||
|
||||
setTitle(_title);
|
||||
|
||||
_draggedX = event.mouse.x;
|
||||
_draggedY = event.mouse.y;
|
||||
|
||||
_wm->setFullRefresh(true);
|
||||
|
||||
if (_callback)
|
||||
(*_callback)(click, event, _dataPtr);
|
||||
}
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
setHighlight(click);
|
||||
|
||||
if (click == kBorderBorder) {
|
||||
_beingDragged = true;
|
||||
|
||||
_draggedX = event.mouse.x;
|
||||
_draggedY = event.mouse.y;
|
||||
}
|
||||
|
||||
if (click == kBorderResizeButton) {
|
||||
_beingResized = true;
|
||||
|
||||
_draggedX = event.mouse.x;
|
||||
_draggedY = event.mouse.y;
|
||||
}
|
||||
|
||||
if (click == kBorderCloseButton && _closeable) {
|
||||
_wm->removeWindow(this);
|
||||
}
|
||||
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
if (_beingDragged || _beingResized) {
|
||||
WindowClick click1 = _beingDragged ? kBorderDragged : kBorderResized;
|
||||
if (_callback)
|
||||
_callback(click1, event, _dataPtr);
|
||||
}
|
||||
|
||||
_beingDragged = false;
|
||||
_beingResized = false;
|
||||
|
||||
setHighlight(kBorderNone);
|
||||
break;
|
||||
|
||||
case Common::EVENT_KEYDOWN:
|
||||
if (_callback)
|
||||
result = _callback(kBorderNone, event, _dataPtr);
|
||||
|
||||
if (!_editable && !(_wm->getActiveWidget() && _wm->getActiveWidget()->isEditable()))
|
||||
return result;
|
||||
|
||||
if (_wm->getActiveWidget())
|
||||
return _wm->getActiveWidget()->processEvent(event) || result;
|
||||
|
||||
return result;
|
||||
|
||||
case Common::EVENT_WHEELUP:
|
||||
case Common::EVENT_WHEELDOWN:
|
||||
if (_callback)
|
||||
result = _callback(kBorderNone, event, _dataPtr);
|
||||
|
||||
if (_wm->getActiveWidget() && _wm->getActiveWidget()->processEvent(event))
|
||||
return true;
|
||||
return result;
|
||||
|
||||
default:
|
||||
if (_callback)
|
||||
return _callback(kBorderNone, event, _dataPtr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
event.mouse.x -= _dims.left;
|
||||
event.mouse.y -= _dims.top;
|
||||
|
||||
MacWidget *w = findEventHandler(event, -_dims.left + _innerDims.left, -_dims.top + _innerDims.top);
|
||||
if (w && w != this) {
|
||||
_wm->_hoveredWidget = w;
|
||||
|
||||
if (w->processEvent(event))
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (_callback)
|
||||
result = (*_callback)(click, event, _dataPtr) || result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void MacWindow::setBorderType(int borderType) {
|
||||
_borderType = borderType;
|
||||
if (borderType < 0) {
|
||||
_macBorder.disableBorder();
|
||||
} else {
|
||||
_macBorder.setBorderType(borderType);
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindow::loadInternalBorder(uint32 flags) {
|
||||
_macBorder.loadInternalBorder(flags);
|
||||
}
|
||||
|
||||
void MacWindow::addDirtyRect(const Common::Rect &r) {
|
||||
if (!r.isValidRect())
|
||||
return;
|
||||
|
||||
Common::Rect bounds = r;
|
||||
bounds.clip(Common::Rect(_innerDims.width(), _innerDims.height()));
|
||||
|
||||
if (bounds.width() > 0 && bounds.height() > 0)
|
||||
_dirtyRects.push_back(bounds);
|
||||
}
|
||||
|
||||
void MacWindow::markAllDirty() {
|
||||
_dirtyRects.clear();
|
||||
_dirtyRects.push_back(Common::Rect(_composeSurface->w, _composeSurface->h));
|
||||
}
|
||||
|
||||
void MacWindow::mergeDirtyRects() {
|
||||
Common::List<Common::Rect>::iterator rOuter, rInner;
|
||||
|
||||
// Process the dirty rect list to find any rects to merge
|
||||
for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
|
||||
rInner = rOuter;
|
||||
while (++rInner != _dirtyRects.end()) {
|
||||
|
||||
if ((*rOuter).intersects(*rInner)) {
|
||||
// These two rectangles overlap, so merge them
|
||||
rOuter->extend(*rInner);
|
||||
|
||||
// remove the inner rect from the list
|
||||
_dirtyRects.erase(rInner);
|
||||
|
||||
// move back to beginning of list
|
||||
rInner = rOuter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common::Rect MacWindow::getDirtyRectBounds() {
|
||||
Common::Rect result;
|
||||
if (_dirtyRects.size() == 0)
|
||||
return result;
|
||||
result = Common::Rect(_dirtyRects.front());
|
||||
for (auto &r : _dirtyRects) {
|
||||
result.extend(r);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
461
graphics/macgui/macwindow.h
Normal file
461
graphics/macgui/macwindow.h
Normal file
@@ -0,0 +1,461 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACWINDOW_H
|
||||
#define GRAPHICS_MACGUI_MACWINDOW_H
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "graphics/nine_patch.h"
|
||||
#include "graphics/font.h"
|
||||
|
||||
#include "graphics/macgui/macwidget.h"
|
||||
#include "graphics/macgui/macwindowborder.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class MacWindowManager;
|
||||
class MacWindowBorder;
|
||||
class MacWidget;
|
||||
|
||||
namespace MacWindowConstants {
|
||||
enum WindowType {
|
||||
kWindowUnknown,
|
||||
kWindowWindow,
|
||||
kWindowMenu
|
||||
};
|
||||
|
||||
enum {
|
||||
kBorderWidth = 17,
|
||||
kWindowMinWidth = 70,
|
||||
kWindowMinHeight = 70
|
||||
};
|
||||
|
||||
enum WindowClick {
|
||||
kBorderNone = 0,
|
||||
kBorderScrollUp,
|
||||
kBorderScrollDown,
|
||||
kBorderScrollLeft,
|
||||
kBorderScrollRight,
|
||||
kBorderCloseButton,
|
||||
kBorderInner,
|
||||
kBorderBorder,
|
||||
kBorderResizeButton,
|
||||
kBorderActivate,
|
||||
kBorderDeactivate,
|
||||
kBorderDragged,
|
||||
kBorderResized,
|
||||
kBorderMaximizeButton,
|
||||
};
|
||||
|
||||
enum {
|
||||
kWindowModeDynamicScrollbar = 1 << 0
|
||||
};
|
||||
}
|
||||
using namespace MacWindowConstants;
|
||||
|
||||
/**
|
||||
* Abstract class that defines common functionality for all window classes.
|
||||
* It supports event callbacks and drawing.
|
||||
*/
|
||||
class BaseMacWindow : public MacWidget {
|
||||
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 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; }
|
||||
|
||||
/**
|
||||
* Mutator to change the visible state of the window.
|
||||
* @param visible Target state.
|
||||
*/
|
||||
virtual void setVisible(bool visible, bool silent = false);
|
||||
/**
|
||||
* Accessor to determine whether a window is active.
|
||||
* @return True if the window is active.
|
||||
*/
|
||||
bool isVisible();
|
||||
|
||||
/**
|
||||
* Method to access the entire interior surface of the window (e.g. to draw an image).
|
||||
* @return A pointer to the entire interior surface of the window.
|
||||
*/
|
||||
ManagedSurface *getWindowSurface() { return _composeSurface; }
|
||||
|
||||
/**
|
||||
* Method to access the border surface of the window.
|
||||
* @return A pointer to the border surface of the window.
|
||||
*/
|
||||
virtual ManagedSurface *getBorderSurface() = 0;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
virtual const Common::Rect &getInnerDimensions() = 0;
|
||||
|
||||
/**
|
||||
* Method called to internally draw the window. This relies on the window
|
||||
* being marked as dirty unless otherwise specified.
|
||||
* @param forceRedraw Its behavior depends on the subclass.
|
||||
*/
|
||||
virtual bool draw(bool forceRedraw = false) = 0;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Method that checks if the window is needs redrawing.
|
||||
*/
|
||||
virtual bool isDirty() = 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; }
|
||||
|
||||
/**
|
||||
* Mutator to change the draggable state of the window.
|
||||
* @param draggable Target state.
|
||||
*/
|
||||
void setDraggable(bool draggable) { _draggable = draggable; }
|
||||
|
||||
protected:
|
||||
int _id;
|
||||
WindowType _type;
|
||||
|
||||
bool _editable;
|
||||
|
||||
bool (*_callback)(WindowClick, Common::Event &, void *);
|
||||
void *_dataPtr;
|
||||
|
||||
bool _visible;
|
||||
|
||||
bool _draggable;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Copy constructor for MacWindow
|
||||
* Needs defining because ManagedSurface has a deprecated default copy constructor
|
||||
* @param source Source window to copy from
|
||||
*/
|
||||
MacWindow(const MacWindow &source);
|
||||
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 (outer dimensions).
|
||||
* @param w New width of the window.
|
||||
* @param h New height of the window.
|
||||
*/
|
||||
virtual void resize(int w, int h);
|
||||
|
||||
/*
|
||||
* Change the width and the height of the inner window.
|
||||
* @param w New width of the window.
|
||||
* @param h New height of the window.
|
||||
*/
|
||||
virtual void resizeInner(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) override;
|
||||
|
||||
/**
|
||||
* Change the inner dimension of the window.
|
||||
* Note that this changes the window inner dimension and calculates
|
||||
* outer dimension (ie with border, etc)
|
||||
* @param r The desired dimensions of the window.
|
||||
*/
|
||||
void setInnerDimensions(const Common::Rect &r);
|
||||
|
||||
/**
|
||||
* Set a background pattern for the window.
|
||||
* @param pattern
|
||||
*/
|
||||
void setBackgroundPattern(int pattern);
|
||||
|
||||
/**
|
||||
* 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) override;
|
||||
|
||||
bool draw(bool forceRedraw = false) override;
|
||||
void blit(ManagedSurface *g, Common::Rect &dest) override;
|
||||
|
||||
const Common::Rect &getInnerDimensions() override { return _innerDims; }
|
||||
ManagedSurface *getBorderSurface() override { return &_borderSurface; }
|
||||
|
||||
/**
|
||||
* Centers the window using the dimensions of the parent window manager, or undoes this; does
|
||||
* nothing if WM is null.
|
||||
*/
|
||||
void center(bool toCenter = true);
|
||||
|
||||
/**
|
||||
* Mutator to change the active state of the window.
|
||||
* Most often called from the WM.
|
||||
* @param active Target state.
|
||||
*/
|
||||
void setActive(bool active) override;
|
||||
/**
|
||||
* Accessor to determine whether a window is active.
|
||||
* @return True if the window is active.
|
||||
*/
|
||||
bool isActive() const;
|
||||
|
||||
/**
|
||||
* Mutator to change the title of the window.
|
||||
* @param title Target title.
|
||||
*/
|
||||
void setTitle(const Common::String &title);
|
||||
|
||||
/**
|
||||
* Set visibility of window title.
|
||||
* @param visible visibility of window.
|
||||
*/
|
||||
virtual void setTitleVisible(bool visible);
|
||||
|
||||
/**
|
||||
* Get visibility of window title.
|
||||
*/
|
||||
bool isTitleVisible();
|
||||
|
||||
/**
|
||||
* Accessor to get the title of the window.
|
||||
* @return Title.
|
||||
*/
|
||||
const Common::String &getTitle() const { return _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) override;
|
||||
bool hasAllFocus() override { 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, uint32 flags, int lo = -1, int ro = -1, int to = -1, int bo = -1);
|
||||
void loadBorder(Common::SeekableReadStream &file, uint32 flags, const BorderOffsets &offsets);
|
||||
void setBorder(Graphics::ManagedSurface *surface, uint32 flags, const BorderOffsets &offsets);
|
||||
void disableBorder();
|
||||
void loadInternalBorder(uint32 flags);
|
||||
/**
|
||||
* we better set this before we load the border
|
||||
* @param scrollbar state
|
||||
*/
|
||||
void enableScrollbar(bool active) { _hasScrollBar = active; }
|
||||
|
||||
/**
|
||||
* Indicate whether the window can be closed (false by default).
|
||||
* @param closeable True if the window can be closed.
|
||||
*/
|
||||
void setCloseable(bool closeable);
|
||||
|
||||
/**
|
||||
* Mutator to change the border type.
|
||||
* @param borderType Border type.
|
||||
*/
|
||||
void setBorderType(int borderType);
|
||||
/**
|
||||
* Accessor to get the border type.
|
||||
* @return Border type.
|
||||
*/
|
||||
int getBorderType() const { return _borderType; };
|
||||
|
||||
/**
|
||||
* We should call this method whenever we need border flags
|
||||
* don't calc border flags yourself
|
||||
* @return Border flags
|
||||
*/
|
||||
uint32 getBorderFlags() const;
|
||||
|
||||
void addDirtyRect(const Common::Rect &r);
|
||||
void markAllDirty();
|
||||
void mergeDirtyRects();
|
||||
Common::Rect getDirtyRectBounds();
|
||||
void clearDirtyRects() { _dirtyRects.clear(); }
|
||||
Common::List<Common::Rect> &getDirtyRectList() { return _dirtyRects; }
|
||||
|
||||
bool isDirty() override { return _borderIsDirty || _contentIsDirty; }
|
||||
|
||||
void setBorderDirty(bool dirty) { _borderIsDirty = true; }
|
||||
void setContentDirty(bool dirty) { _contentIsDirty = true; }
|
||||
void resizeBorderSurface();
|
||||
|
||||
void setMode(uint32 mode) { _mode = mode; }
|
||||
void setBorderOffsets(BorderOffsets &offsets) { _macBorder.setOffsets(offsets); }
|
||||
const BorderOffsets &getBorderOffsets() const { return _macBorder.getOffset(); }
|
||||
|
||||
void updateInnerDims();
|
||||
|
||||
private:
|
||||
void rebuildSurface(); // Propagate dimensions change and recreate patter/borders, etc.
|
||||
void drawBorderFromSurface(ManagedSurface *g, uint32 flags);
|
||||
void drawPattern();
|
||||
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 updateOuterDims();
|
||||
|
||||
bool isInCloseButton(int x, int y) const;
|
||||
bool isInResizeButton(int x, int y) const;
|
||||
WindowClick isInScroll(int x, int y) const;
|
||||
|
||||
protected:
|
||||
void drawBorder();
|
||||
WindowClick isInBorder(int x, int y) const;
|
||||
|
||||
protected:
|
||||
ManagedSurface _borderSurface;
|
||||
|
||||
bool _borderIsDirty;
|
||||
Common::Rect _innerDims;
|
||||
|
||||
Common::List<Common::Rect> _dirtyRects;
|
||||
bool _hasScrollBar;
|
||||
|
||||
uint32 _mode;
|
||||
private:
|
||||
MacWindowBorder _macBorder;
|
||||
|
||||
int _pattern;
|
||||
bool _hasPattern;
|
||||
|
||||
bool _scrollable;
|
||||
bool _resizable;
|
||||
|
||||
bool _closeable;
|
||||
bool _isTitleVisible;
|
||||
|
||||
int _borderWidth;
|
||||
|
||||
bool _beingDragged, _beingResized;
|
||||
int _draggedX, _draggedY;
|
||||
|
||||
WindowClick _highlightedPart;
|
||||
|
||||
Common::String _title;
|
||||
Common::String _shadowedTitle;
|
||||
|
||||
int _borderType;
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
349
graphics/macgui/macwindowborder.cpp
Normal file
349
graphics/macgui/macwindowborder.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/macgui/macwindowborder.h"
|
||||
#include "graphics/macgui/macwindowmanager.h"
|
||||
#include "graphics/macgui/macfontmanager.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
using namespace Graphics::MacGUIConstants;
|
||||
|
||||
static const byte noborderData[3][3] = {
|
||||
{ 0, 1, 0 },
|
||||
{ 1, 0, 1 },
|
||||
{ 0, 1, 0 },
|
||||
};
|
||||
|
||||
MacWindowBorder::MacWindowBorder() {
|
||||
|
||||
_border = Common::Array<NinePatchBitmap *>(kWindowBorderMaxFlag);
|
||||
_window = nullptr;
|
||||
_wm = nullptr;
|
||||
_useInternalBorder = false;
|
||||
|
||||
for (uint32 i = 0; i < kWindowBorderMaxFlag; i++)
|
||||
_border[i] = nullptr;
|
||||
|
||||
_borderOffsets.left = -1;
|
||||
_borderOffsets.right = -1;
|
||||
_borderOffsets.top = -1;
|
||||
_borderOffsets.bottom = -1;
|
||||
_borderOffsets.titleTop = -1;
|
||||
_borderOffsets.titleBottom = -1;
|
||||
_borderOffsets.dark = false;
|
||||
_borderOffsets.titlePos = 0;
|
||||
_borderOffsets.closeButtonTop = -1;
|
||||
_borderOffsets.closeButtonLeft = -1;
|
||||
_borderOffsets.closeButtonWidth = 0;
|
||||
_borderOffsets.resizeButtonTop = -1;
|
||||
_borderOffsets.resizeButtonHeight = 0;
|
||||
_borderOffsets.upperScrollHeight = 0;
|
||||
_borderOffsets.lowerScrollHeight = 0;
|
||||
|
||||
_borderType = 0;
|
||||
|
||||
_scrollSize = -1;
|
||||
_scrollPos = 0;
|
||||
}
|
||||
|
||||
MacWindowBorder::~MacWindowBorder() {
|
||||
for (uint32 i = 0; i < kWindowBorderMaxFlag; i++) {
|
||||
if (_border[i])
|
||||
delete _border[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool MacWindowBorder::hasBorder(uint32 flags) {
|
||||
if (flags >= kWindowBorderMaxFlag) {
|
||||
warning("Accessing non-existed border type, %d", flags);
|
||||
return false;
|
||||
}
|
||||
if (_useInternalBorder && !_border[flags]) {
|
||||
loadInternalBorder(flags);
|
||||
}
|
||||
return _border[flags] != nullptr;
|
||||
}
|
||||
|
||||
void MacWindowBorder::disableBorder() {
|
||||
const byte palette[] = {
|
||||
255, 0, 255,
|
||||
0, 0, 0,
|
||||
255, 255, 255,
|
||||
};
|
||||
|
||||
Graphics::ManagedSurface *noborder = new Graphics::ManagedSurface();
|
||||
noborder->create(3, 3, Graphics::PixelFormat::createFormatCLUT8());
|
||||
noborder->setPalette(palette, 0, 3);
|
||||
noborder->setTransparentColor(0);
|
||||
|
||||
for (int y = 0; y < 3; y++)
|
||||
for (int x = 0; x < 3; x++)
|
||||
*((byte *)noborder->getBasePtr(x, y)) = noborderData[y][x];
|
||||
|
||||
setBorder(noborder, kWindowBorderActive);
|
||||
|
||||
Graphics::ManagedSurface *noborder2 = new Graphics::ManagedSurface();
|
||||
noborder2->copyFrom(*noborder);
|
||||
setBorder(noborder2, 0);
|
||||
}
|
||||
|
||||
void MacWindowBorder::addBorder(ManagedSurface *source, uint32 flags, int titlePos) {
|
||||
if (flags >= kWindowBorderMaxFlag) {
|
||||
warning("Accessing non-existed border type");
|
||||
return;
|
||||
}
|
||||
if (_border[flags])
|
||||
delete _border[flags];
|
||||
|
||||
_border[flags] = new NinePatchBitmap(source, true, titlePos);
|
||||
|
||||
if (_border[flags]->getPadding().isValidRect() && _border[flags]->getPadding().left > -1 && _border[flags]->getPadding().top > -1)
|
||||
setOffsets(_border[flags]->getPadding());
|
||||
}
|
||||
|
||||
bool MacWindowBorder::hasOffsets() const {
|
||||
return _borderOffsets.left > -1 && _borderOffsets.right > -1
|
||||
&& _borderOffsets.top > -1 && _borderOffsets.bottom > -1;
|
||||
}
|
||||
|
||||
void MacWindowBorder::setOffsets(int left, int right, int top, int bottom) {
|
||||
_borderOffsets.left = left;
|
||||
_borderOffsets.right = right;
|
||||
_borderOffsets.top = top;
|
||||
_borderOffsets.bottom = bottom;
|
||||
}
|
||||
|
||||
void MacWindowBorder::setOffsets(Common::Rect &rect) {
|
||||
_borderOffsets.left = rect.left;
|
||||
_borderOffsets.right = rect.right;
|
||||
_borderOffsets.top = rect.top;
|
||||
_borderOffsets.bottom = rect.bottom;
|
||||
}
|
||||
|
||||
void MacWindowBorder::setOffsets(const BorderOffsets &offsets) {
|
||||
_borderOffsets = offsets;
|
||||
}
|
||||
|
||||
BorderOffsets &MacWindowBorder::getOffset() {
|
||||
return _borderOffsets;
|
||||
}
|
||||
|
||||
const BorderOffsets &MacWindowBorder::getOffset() const {
|
||||
return _borderOffsets;
|
||||
}
|
||||
|
||||
int MacWindowBorder::getMinWidth(uint32 flags) const {
|
||||
return _border[flags]->getMinWidth();
|
||||
}
|
||||
|
||||
int MacWindowBorder::getMinHeight(uint32 flags) const {
|
||||
return _border[flags]->getMinHeight();
|
||||
}
|
||||
|
||||
void MacWindowBorder::setTitle(const Common::String& title, int width) {
|
||||
_title = title;
|
||||
const Graphics::Font *font = _wm->_fontMan->getFont(Graphics::MacFont(kMacFontSystem, 12));
|
||||
int titleWidth = font->getStringWidth(_title) + getOffset().titlePadding;
|
||||
|
||||
// if titleWidth is changed, then we modify it
|
||||
// here, we change all the border that has title
|
||||
for (uint32 i = 0; i < kWindowBorderMaxFlag; i++) {
|
||||
if ((_border[i] != nullptr) && (i & kWindowBorderTitle)) {
|
||||
int maxWidth = MAX<int>(width - _border[i]->getMinWidth() + getOffset().titlePadding, 0);
|
||||
if (titleWidth > maxWidth)
|
||||
titleWidth = maxWidth;
|
||||
_border[i]->modifyTitleWidth(titleWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindowBorder::drawScrollBar(ManagedSurface *g) {
|
||||
// here, we first check the _scrollSize, and if it is negative, then we don't draw the scrollBar
|
||||
if (_scrollSize < 0)
|
||||
return;
|
||||
int width = _borderOffsets.right;
|
||||
int height = _borderOffsets.upperScrollHeight;
|
||||
int rx1 = g->w - width + 2;
|
||||
int ry1 = height + _scrollPos;
|
||||
int rx2 = rx1 + width - 5;
|
||||
int ry2 = ry1 + _scrollSize ;
|
||||
Common::Rect rr(rx1, ry1, rx2, ry2);
|
||||
|
||||
MacPlotData pd(g, nullptr, &_wm->getPatterns(), 1, 0, 0, 1, _wm->_colorWhite, true);
|
||||
Primitives &primitives = _wm->getDrawInvertPrimitives();
|
||||
primitives.drawFilledRect1(rr, _wm->_colorWhite, &pd);
|
||||
|
||||
// after drawing, we set the _scrollSize negative, to indicate no more drawing is needed
|
||||
// if win95 mode is enabled, then we keep on drawing the scrollbar
|
||||
if (!(_wm->_mode & kWMModeWin95))
|
||||
_scrollSize = -1;
|
||||
}
|
||||
|
||||
void MacWindowBorder::drawTitle(ManagedSurface *g, int titleOffset, int minWidth) {
|
||||
const Graphics::Font *font = _wm->_fontMan->getFont(Graphics::MacFont(kMacFontSystem, 12));
|
||||
int width = g->w;
|
||||
int titleColor = getOffset().dark ? _wm->_colorWhite: _wm->_colorBlack;
|
||||
int titleY = getOffset().titleTop;
|
||||
int titleWidth = font->getStringWidth(_title) + 8;
|
||||
int yOff = _wm->_fontMan->hasBuiltInFonts() ? 3 : 1;
|
||||
int maxWidth = MAX<int>(width - minWidth - 7 - 4, 0);
|
||||
if (titleWidth > maxWidth)
|
||||
titleWidth = maxWidth;
|
||||
|
||||
font->drawString(g, _title, titleOffset + 4, titleY + yOff, titleWidth, titleColor);
|
||||
}
|
||||
|
||||
void MacWindowBorder::setBorderType(int type) {
|
||||
if (_window)
|
||||
setOffsets(_window->_wm->getBorderOffsets(type));
|
||||
|
||||
_useInternalBorder = true;
|
||||
_borderType = type;
|
||||
}
|
||||
|
||||
void MacWindowBorder::loadBorder(Common::SeekableReadStream &file, uint32 flags, int lo, int ro, int to, int bo) {
|
||||
BorderOffsets offsets;
|
||||
offsets.left = lo;
|
||||
offsets.right = ro;
|
||||
offsets.top = to;
|
||||
offsets.bottom = bo;
|
||||
offsets.titleTop = -1;
|
||||
offsets.titleBottom = -1;
|
||||
offsets.titlePos = 0;
|
||||
offsets.dark = false;
|
||||
offsets.closeButtonTop = -1;
|
||||
offsets.closeButtonLeft = -1;
|
||||
offsets.closeButtonWidth = 0;
|
||||
offsets.resizeButtonTop = -1;
|
||||
offsets.resizeButtonHeight = 0;
|
||||
offsets.upperScrollHeight = 0;
|
||||
offsets.lowerScrollHeight = 0;
|
||||
|
||||
loadBorder(file, flags, offsets);
|
||||
}
|
||||
|
||||
void MacWindowBorder::loadBorder(Common::SeekableReadStream &file, uint32 flags, const BorderOffsets &offsets) {
|
||||
Image::BitmapDecoder bmpDecoder;
|
||||
bmpDecoder.loadStream(file);
|
||||
|
||||
Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
|
||||
surface->copyFrom(*bmpDecoder.getSurface());
|
||||
surface->setPalette(bmpDecoder.getPalette().data(), 0,
|
||||
bmpDecoder.getPalette().size());
|
||||
|
||||
if (surface->format.isCLUT8()) {
|
||||
const Graphics::Palette &palette = bmpDecoder.getPalette();
|
||||
uint i = palette.find(255, 0, 255);
|
||||
if (i < palette.size())
|
||||
surface->setTransparentColor(i);
|
||||
} else {
|
||||
const Graphics::PixelFormat requiredFormat_4byte(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
||||
surface->convertToInPlace(requiredFormat_4byte);
|
||||
surface->setTransparentColor(surface->format.RGBToColor(255, 0, 255));
|
||||
}
|
||||
|
||||
setBorder(surface, flags, offsets);
|
||||
}
|
||||
|
||||
void MacWindowBorder::setBorder(Graphics::ManagedSurface *surface, uint32 flags, int lo, int ro, int to, int bo) {
|
||||
BorderOffsets offsets;
|
||||
offsets.left = lo;
|
||||
offsets.right = ro;
|
||||
offsets.top = to;
|
||||
offsets.bottom = bo;
|
||||
offsets.titleTop = -1;
|
||||
offsets.titleBottom = -1;
|
||||
offsets.titlePos = 0;
|
||||
offsets.dark = false;
|
||||
offsets.closeButtonTop = -1;
|
||||
offsets.closeButtonLeft = -1;
|
||||
offsets.closeButtonWidth = 0;
|
||||
offsets.resizeButtonTop = -1;
|
||||
offsets.resizeButtonHeight = 0;
|
||||
offsets.upperScrollHeight = 0;
|
||||
offsets.lowerScrollHeight = 0;
|
||||
setBorder(surface, flags, offsets);
|
||||
}
|
||||
|
||||
void MacWindowBorder::setBorder(Graphics::ManagedSurface *surface, uint32 flags, const BorderOffsets &offsets) {
|
||||
addBorder(surface, flags, offsets.titlePos);
|
||||
|
||||
if ((flags & kWindowBorderActive) && offsets.left + offsets.right + offsets.top + offsets.bottom > -4) { // Checking against default -1
|
||||
setOffsets(offsets);
|
||||
if (_window)
|
||||
_window->resizeBorderSurface();
|
||||
}
|
||||
|
||||
if (_window) {
|
||||
_window->setBorderDirty(true);
|
||||
_window->_wm->setFullRefresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindowBorder::loadInternalBorder(uint32 flags) {
|
||||
if (_borderType < 0) {
|
||||
warning("trying to load non-existing internal border type");
|
||||
return;
|
||||
}
|
||||
const BorderOffsets &offsets = _wm->getBorderOffsets(_borderType);
|
||||
Common::SeekableReadStream *file = _wm->getBorderFile(_borderType, flags);
|
||||
if (file) {
|
||||
loadBorder(*file, flags, offsets);
|
||||
delete file;
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindowBorder::blitBorderInto(ManagedSurface &destination, uint32 flags) {
|
||||
if (flags >= kWindowBorderMaxFlag) {
|
||||
warning("Accessing non-existed border type");
|
||||
return;
|
||||
}
|
||||
|
||||
NinePatchBitmap *src = _border[flags];
|
||||
|
||||
if (!src) {
|
||||
warning("Attempt to blit uninitialized border");
|
||||
return;
|
||||
}
|
||||
|
||||
if (destination.w == 0 || destination.h == 0) {
|
||||
warning("Attempt to draw %d x %d window", destination.w, destination.h);
|
||||
return;
|
||||
}
|
||||
|
||||
// we add a special check here, if we have title but the titleWidth is zero, then we try to recalc it
|
||||
if ((flags & kWindowBorderTitle) && _border[flags]->getTitleWidth() == 0) {
|
||||
setTitle(_title, destination.w);
|
||||
}
|
||||
|
||||
src->blit(destination, 0, 0, destination.w, destination.h, _wm);
|
||||
|
||||
if (flags & kWindowBorderTitle)
|
||||
drawTitle(&destination, src->getTitleOffset(), _border[flags]->getMinWidth());
|
||||
|
||||
if (flags & kWindowBorderScrollbar)
|
||||
drawScrollBar(&destination);
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
184
graphics/macgui/macwindowborder.h
Normal file
184
graphics/macgui/macwindowborder.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACWINDOWBORDER_H
|
||||
#define GRAPHICS_MACGUI_MACWINDOWBORDER_H
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/list.h"
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "graphics/primitives.h"
|
||||
|
||||
#include "image/bmp.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class MacWindow;
|
||||
class MacWindowManager;
|
||||
class NinePatchBitmap;
|
||||
|
||||
enum {
|
||||
kWindowBorderActive = 1 << 0,
|
||||
kWindowBorderTitle = 1 << 1,
|
||||
kWindowBorderScrollbar = 1 << 2,
|
||||
|
||||
kWindowBorderMaxFlag = 1 << 3
|
||||
};
|
||||
|
||||
enum {
|
||||
kBorderScroll = 1000
|
||||
};
|
||||
|
||||
enum {
|
||||
kWinBorderWin95Scrollbar = kBorderScroll + 0x00,
|
||||
kWindowBorderWin95NoBorderScrollbar,
|
||||
kWindowBorderMacOSNoBorderScrollbar
|
||||
};
|
||||
|
||||
struct BorderOffsets {
|
||||
int left;
|
||||
int right;
|
||||
int top;
|
||||
int bottom;
|
||||
int titleTop;
|
||||
int titleBottom;
|
||||
bool dark;
|
||||
int titlePos;
|
||||
int closeButtonTop;
|
||||
int closeButtonLeft;
|
||||
int closeButtonWidth;
|
||||
int resizeButtonTop;
|
||||
int resizeButtonHeight;
|
||||
int upperScrollHeight;
|
||||
int lowerScrollHeight;
|
||||
int titlePadding;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 check whether the border type we want has been initialized.
|
||||
* @return True if the checked state has a border loaded, false otherwise.
|
||||
*/
|
||||
bool hasBorder(uint32 flags);
|
||||
|
||||
/**
|
||||
* Add the given surface as the display of the border in the state that is instructed by flag.
|
||||
* Will fail if there is already a border.
|
||||
* @param The surface that will be displayed.
|
||||
* @param The border type indicated by flag
|
||||
* @param The title position of bmp image
|
||||
*/
|
||||
void addBorder(ManagedSurface *source, uint32 flags, int titlePos = 0);
|
||||
|
||||
/**
|
||||
* Accessor function for the custom offsets.
|
||||
* @return True if custom offsets have been indicated (setOffsets has been called previously).
|
||||
*/
|
||||
bool hasOffsets() const;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
void setOffsets(Common::Rect &rect);
|
||||
void setOffsets(const BorderOffsets &offsets);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
BorderOffsets &getOffset();
|
||||
const BorderOffsets &getOffset() const;
|
||||
|
||||
int getMinWidth(uint32 flags) const;
|
||||
int getMinHeight(uint32 flags) const;
|
||||
|
||||
/**
|
||||
* 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 border type that you want to draw
|
||||
* @param wm The window manager.
|
||||
*/
|
||||
void blitBorderInto(ManagedSurface &destination, uint32 flags);
|
||||
|
||||
void setTitle(const Common::String& title, int width);
|
||||
|
||||
void setScroll(int scrollPos, int scrollSize) { _scrollPos = scrollPos, _scrollSize = scrollSize; }
|
||||
|
||||
void drawTitle(ManagedSurface *g, int titleOffset, int minWidth);
|
||||
|
||||
void drawScrollBar(ManagedSurface *g);
|
||||
|
||||
// we should call this method as soon as the macwindowborder is constructed
|
||||
void setWindow(MacWindow *window) { _window = window; }
|
||||
void setWindowManager(MacWindowManager *wm) { _wm = wm; }
|
||||
|
||||
void setBorderType(int type);
|
||||
|
||||
void disableBorder();
|
||||
|
||||
void loadBorder(Common::SeekableReadStream &file, uint32 flags, int lo = -1, int ro = -1, int to = -1, int bo = -1);
|
||||
void loadBorder(Common::SeekableReadStream &file, uint32 flags, const BorderOffsets &offsets);
|
||||
void loadInternalBorder(uint32 flags);
|
||||
|
||||
void setBorder(Graphics::ManagedSurface *surface, uint32 flags, int lo = -1, int ro = -1, int to = -1, int bo = -1);
|
||||
void setBorder(Graphics::ManagedSurface *surface, uint32 flags, const BorderOffsets &offsets);
|
||||
private:
|
||||
int _scrollPos, _scrollSize;
|
||||
Common::String _title;
|
||||
|
||||
Common::Array<NinePatchBitmap *> _border;
|
||||
|
||||
MacWindow *_window;
|
||||
MacWindowManager *_wm;
|
||||
BorderOffsets _borderOffsets;
|
||||
|
||||
bool _useInternalBorder;
|
||||
|
||||
int _borderType;
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
#endif
|
||||
1581
graphics/macgui/macwindowmanager.cpp
Normal file
1581
graphics/macgui/macwindowmanager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
504
graphics/macgui/macwindowmanager.h
Normal file
504
graphics/macgui/macwindowmanager.h
Normal file
@@ -0,0 +1,504 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_MACGUI_MACWINDOWMANAGER_H
|
||||
#define GRAPHICS_MACGUI_MACWINDOWMANAGER_H
|
||||
|
||||
#include "common/hashmap.h"
|
||||
#include "common/list.h"
|
||||
#include "common/mutex.h"
|
||||
#include "common/stack.h"
|
||||
#include "common/events.h"
|
||||
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/fontman.h"
|
||||
#include "graphics/palette.h"
|
||||
#include "graphics/macgui/macwindow.h"
|
||||
#include "graphics/macgui/macmenu.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Common {
|
||||
class Archive;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
namespace MacGUIConstants {
|
||||
enum {
|
||||
kDesktopArc = 7
|
||||
};
|
||||
|
||||
enum {
|
||||
kColorBlack = 0,
|
||||
kColorGray80 = 1,
|
||||
kColorGray88 = 2,
|
||||
kColorGrayEE = 3,
|
||||
kColorWhite = 4,
|
||||
kColorGreen = 5,
|
||||
kColorGreen2 = 6,
|
||||
kColorCount
|
||||
};
|
||||
|
||||
enum {
|
||||
kPatternSolid = 1,
|
||||
kPatternStripes = 2,
|
||||
kPatternCheckers = 3,
|
||||
kPatternCheckers2 = 4,
|
||||
kPatternLightGray = 5,
|
||||
kPatternDarkGray = 6
|
||||
};
|
||||
|
||||
enum MacCursorType {
|
||||
kMacCursorArrow,
|
||||
kMacCursorBeam,
|
||||
kMacCursorCrossHair,
|
||||
kMacCursorCrossBar,
|
||||
kMacCursorWatch,
|
||||
kMacCursorCustom,
|
||||
kMacCursorOff
|
||||
};
|
||||
|
||||
enum {
|
||||
kWMModeNone = 0,
|
||||
kWMModeNoDesktop = (1 << 0),
|
||||
kWMModeAutohideMenu = (1 << 1),
|
||||
kWMModalMenuMode = (1 << 2),
|
||||
kWMModeForceBuiltinFonts = (1 << 3),
|
||||
kWMModeUnicode = (1 << 4),
|
||||
kWMModeManualDrawWidgets = (1 << 5),
|
||||
kWMModeFullscreen = (1 << 6),
|
||||
kWMModeButtonDialogStyle = (1 << 7),
|
||||
kWMMode32bpp = (1 << 8),
|
||||
kWMNoScummVMWallpaper = (1 << 9),
|
||||
kWMModeWin95 = (1 << 10),
|
||||
kWMModeForceMacFontsInWin95 = (1 << 11), // Enforce Mac font for languages which don't have glyphs in ms_sans_serif.ttf
|
||||
kWMModeNoCursorOverride = (1 << 12),
|
||||
kWMModeForceMacBorder = (1 << 13),
|
||||
kWMModeForceMacFonts = (1 << 14), // Enforce Mac fonts even when there are viable TTF substitutions
|
||||
};
|
||||
|
||||
}
|
||||
using namespace MacGUIConstants;
|
||||
|
||||
class Cursor;
|
||||
|
||||
class ManagedSurface;
|
||||
|
||||
class MacCursor;
|
||||
class MacMenu;
|
||||
class MacTextWindow;
|
||||
class MacWidget;
|
||||
|
||||
class MacFont;
|
||||
|
||||
class MacFontManager;
|
||||
|
||||
typedef Common::Array<const byte *> MacPatterns;
|
||||
|
||||
struct MacPlotData {
|
||||
Graphics::ManagedSurface *surface;
|
||||
Graphics::ManagedSurface *mask;
|
||||
MacPatterns *patterns;
|
||||
uint fillType;
|
||||
int fillOriginX;
|
||||
int fillOriginY;
|
||||
int thickness;
|
||||
uint bgColor;
|
||||
bool invert;
|
||||
|
||||
MacPlotData(Graphics::ManagedSurface *s, Graphics::ManagedSurface *m, MacPatterns *p, uint f, int fx, int fy, int t, uint bg, bool inv = false) :
|
||||
surface(s), mask(m), patterns(p), fillType(f), fillOriginX(fx), fillOriginY(fy), thickness(t), bgColor(bg), invert(inv) {
|
||||
}
|
||||
};
|
||||
|
||||
struct ZoomBox {
|
||||
Common::Rect start;
|
||||
Common::Rect end;
|
||||
Common::Array<Common::Rect> last;
|
||||
int delay;
|
||||
int step;
|
||||
uint32 startTime;
|
||||
uint32 nextTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* A manager class to handle window creation, destruction,
|
||||
* drawing, moving and event handling.
|
||||
*/
|
||||
class MacWindowManager {
|
||||
public:
|
||||
MacWindowManager(uint32 mode = 0, MacPatterns *patterns = nullptr, Common::Language language = Common::UNK_LANG);
|
||||
~MacWindowManager();
|
||||
|
||||
Primitives &getDrawPrimitives() const { return *_macDrawPrimitives; }
|
||||
Primitives &getDrawInvertPrimitives() const;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Mutator to indicate the dimensions of the desktop, when a backing surface is not used.
|
||||
* 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(int w, int h);
|
||||
|
||||
int getWidth();
|
||||
|
||||
int getHeight();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
MacTextWindow *addTextWindow(const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, MacMenu *menu, int padding = 0);
|
||||
MacTextWindow *addTextWindow(const Font *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, MacMenu *menu, int padding = 0);
|
||||
void resizeScreen(int w, int h);
|
||||
|
||||
/**
|
||||
* Adds a window that has already been initialized to the registry.
|
||||
* Like addWindow, but this doesn't create/allocate the Window.
|
||||
* @param macWindow the window to be added to the registry
|
||||
*/
|
||||
void addWindowInitialized(MacWindow *macwindow);
|
||||
/**
|
||||
* Returns the last allocated id
|
||||
* @return last allocated window id
|
||||
*/
|
||||
int getLastId() { return _lastId; }
|
||||
/**
|
||||
* Returns the next available id and the increments the internal counter.
|
||||
* @return next (new) window id that can be used
|
||||
*/
|
||||
int getNextId() { return _lastId++; }
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
MacMenu *addMenu();
|
||||
void addMenu(int id, MacMenu *menu);
|
||||
|
||||
void removeMenu();
|
||||
void activateMenu();
|
||||
|
||||
void activateScreenCopy();
|
||||
void disableScreenCopy();
|
||||
|
||||
bool isMenuActive();
|
||||
void setDesktopMode(uint32 mode);
|
||||
|
||||
/**
|
||||
* Set hot zone where menu appears (works only with autohide menu)
|
||||
*/
|
||||
void setMenuHotzone(const Common::Rect &rect) { _menuHotzone = rect; }
|
||||
|
||||
/**
|
||||
* Set delay in milliseconds when menu appears (works only with autohide menu)
|
||||
*/
|
||||
void setMenuDelay(int delay) { _menuDelay = delay; }
|
||||
|
||||
/**
|
||||
* Set the desired window state to active.
|
||||
* @param id ID of the window that has to be set to active.
|
||||
*/
|
||||
void setActiveWindow(int id);
|
||||
|
||||
int getActiveWindow() { return _activeWindow; }
|
||||
|
||||
/**
|
||||
* Return Top Window containing a point
|
||||
* @param x x coordinate of point
|
||||
* @param y y coordiante of point
|
||||
*/
|
||||
MacWindow *findWindowAtPoint(int16 x, int16 y);
|
||||
/**
|
||||
* Return Top Window containing a point
|
||||
* @param point Point
|
||||
*/
|
||||
MacWindow *findWindowAtPoint(Common::Point point);
|
||||
|
||||
/**
|
||||
* 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 = redraw; }
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (id >= 0 && id < (int)_windows.size())
|
||||
return _windows[id];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the patterns used to fill surfaces.
|
||||
* @return A MacPatterns object reference with the patterns.
|
||||
*/
|
||||
MacPatterns &getPatterns() { return _patterns; }
|
||||
|
||||
/**
|
||||
* Sets an active widget, typically the one which steals the input
|
||||
* It also sends deactivation message to the previous one
|
||||
* @param widget Pointer to the widget to activate, nullptr for no widget
|
||||
*/
|
||||
void setActiveWidget(MacWidget *widget);
|
||||
|
||||
/**
|
||||
* Similar to setActiveWidget but in this case no action including animation
|
||||
* hover, etc can work until a window is locked.
|
||||
* Anything outside this window will not respond to user.
|
||||
* @param widget Pointer to the widget to lock, nullptr for no widget
|
||||
*/
|
||||
void setLockedWidget(MacWidget *widget);
|
||||
|
||||
/**
|
||||
* Sets a background window, which is always active, this window cannot be
|
||||
* deactivated by clicking outside it, ie it is always in background.
|
||||
* @param window Pointer to the widget to background, nullptr for no widget
|
||||
*/
|
||||
void setBackgroundWindow(MacWindow *window);
|
||||
|
||||
MacPatterns &getBuiltinPatterns() { return _builtinPatterns; }
|
||||
|
||||
MacWidget *getActiveWidget() { return _activeWidget; }
|
||||
MacWidget *getLockedWidget() { return _lockedWidget; }
|
||||
|
||||
Common::Rect getScreenBounds() { return _screen ? _screen->getBounds() : _screenDims; }
|
||||
|
||||
void clearWidgetRefs(MacWidget *widget);
|
||||
|
||||
void printWMMode(int debuglevel = 0);
|
||||
|
||||
private:
|
||||
void replaceCursorType(MacCursorType type);
|
||||
|
||||
public:
|
||||
MacCursorType getCursorType() const;
|
||||
|
||||
void pushCursor(MacCursorType type, Cursor *cursor = nullptr);
|
||||
void replaceCursor(MacCursorType type, Cursor *cursor = nullptr);
|
||||
|
||||
void pushCustomCursor(const byte *data, int w, int h, int hx, int hy, int transcolor);
|
||||
void replaceCustomCursor(const byte *data, int w, int h, int hx, int hy, int transcolor);
|
||||
void pushCustomCursor(const Graphics::Cursor *cursor);
|
||||
void popCursor();
|
||||
|
||||
PauseToken pauseEngine();
|
||||
|
||||
void setMode(uint32 mode);
|
||||
|
||||
void setEngine(Engine *engine);
|
||||
void setEngineRedrawCallback(void *engine, void (*redrawCallback)(void *engine));
|
||||
void setEngineActivateMenuCallback(void *engine, void (*redrawCallback)(void *engine));
|
||||
|
||||
void passPalette(const byte *palette, uint size);
|
||||
template <typename T> void decomposeColor(uint32 color, byte &r, byte &g, byte &b);
|
||||
uint32 findBestColor(byte cr, byte cg, byte cb);
|
||||
uint32 findBestColor(uint32 color);
|
||||
void setDesktopColor(byte, byte, byte);
|
||||
|
||||
byte inverter(byte src);
|
||||
|
||||
const byte *getPalette() { return _palette; }
|
||||
uint getPaletteSize() { return _paletteSize; }
|
||||
|
||||
void renderZoomBox(bool redraw = false);
|
||||
void addZoomBox(ZoomBox *box);
|
||||
|
||||
void removeMarked();
|
||||
|
||||
void loadDataBundle();
|
||||
void cleanupDataBundle();
|
||||
void cleanupDesktopBmp();
|
||||
|
||||
const BorderOffsets &getBorderOffsets(uint32 windowType);
|
||||
Common::SeekableReadStream *getBorderFile(uint32 windowType, uint32 flags);
|
||||
Common::SeekableReadStream *getFile(const Common::Path &filename);
|
||||
|
||||
void setTextInClipboard(const Common::U32String &str);
|
||||
/**
|
||||
* get text from WM clipboard or the global clipboard
|
||||
* @param size will change to the length of real text in clipboard
|
||||
* @return the text in clipboard, which may contained the format
|
||||
*/
|
||||
Common::U32String getTextFromClipboard(const Common::U32String &format = Common::U32String(), int *size = nullptr);
|
||||
|
||||
/**
|
||||
* reset events for current widgets. i.e. we reset those variables which are used for handling events for macwidgets.
|
||||
* e.g. we clear the active widget, set mouse down false, clear the hoveredWidget
|
||||
* this function should be called when we are going to other level to handling events. thus wm may not handle events correctly.
|
||||
*/
|
||||
void clearHandlingWidgets();
|
||||
|
||||
void setMenuItemCheckMark(MacMenuItem *menuItem, bool checkMark);
|
||||
void setMenuItemEnabled(MacMenuItem *menuItem, bool enabled);
|
||||
void setMenuItemName(MacMenuItem *menuItem, const Common::String &name);
|
||||
void setMenuItemAction(MacMenuItem *menuItem, int actionId);
|
||||
|
||||
bool getMenuItemCheckMark(MacMenuItem *menuItem);
|
||||
bool getMenuItemEnabled(MacMenuItem *menuItem);
|
||||
Common::String getMenuItemName(MacMenuItem *menuItem);
|
||||
int getMenuItemAction(MacMenuItem *menuItem);
|
||||
MacMenu *getMenu();
|
||||
MacMenu *getMenu(int id);
|
||||
|
||||
void sayText(const Common::U32String &text) const;
|
||||
void setTTSEnabled(bool enabled);
|
||||
|
||||
public:
|
||||
MacFontManager *_fontMan;
|
||||
uint32 _mode;
|
||||
Common::Language _language;
|
||||
|
||||
Common::Point _lastClickPos;
|
||||
Common::Point _lastMousePos;
|
||||
Common::Rect _menuHotzone;
|
||||
|
||||
uint32 _menuTimer;
|
||||
bool _mouseDown;
|
||||
|
||||
uint32 _colorBlack, _colorGray80, _colorGray88, _colorGrayEE, _colorWhite, _colorGreen, _colorGreen2;
|
||||
|
||||
MacWidget *_hoveredWidget;
|
||||
|
||||
// we use it to indicate whether we are clicking the hilite-able widget.
|
||||
// In list style button mode, we will highlight the subsequent buttons only when we've clicked the hilite-able button initially
|
||||
bool _hilitingWidget;
|
||||
|
||||
private:
|
||||
void loadDesktop();
|
||||
void drawDesktop();
|
||||
|
||||
void removeFromStack(BaseMacWindow *target);
|
||||
void removeFromWindowList(BaseMacWindow *target);
|
||||
|
||||
void zoomBoxInner(Common::Rect &r, Graphics::MacPlotData &pd);
|
||||
bool haveZoomBox() { return !_zoomBoxes.empty(); }
|
||||
|
||||
void adjustDimensions(const Common::Rect &clip, const Common::Rect &dims, int &adjWidth, int &adjHeight);
|
||||
|
||||
public:
|
||||
Surface *_desktopBmp;
|
||||
ManagedSurface *_desktop;
|
||||
PixelFormat _pixelformat;
|
||||
|
||||
ManagedSurface *_screen;
|
||||
ManagedSurface *_screenCopy;
|
||||
Common::Rect _screenDims;
|
||||
|
||||
private:
|
||||
Common::Mutex _mutex;
|
||||
Common::List<BaseMacWindow *> _windowStack;
|
||||
Common::HashMap<uint, BaseMacWindow *> _windows;
|
||||
|
||||
Common::List<BaseMacWindow *> _windowsToRemove;
|
||||
bool _needsRemoval;
|
||||
|
||||
int _lastId;
|
||||
int _activeWindow;
|
||||
|
||||
bool _fullRefresh;
|
||||
|
||||
bool _inEditableArea;
|
||||
|
||||
Primitives *_macDrawPrimitives;
|
||||
Primitives *_macDrawInvertPrimitives;
|
||||
|
||||
MacPatterns _patterns;
|
||||
MacPatterns _builtinPatterns;
|
||||
byte *_palette;
|
||||
uint _paletteSize;
|
||||
|
||||
MacMenu *_menu;
|
||||
uint32 _menuDelay;
|
||||
|
||||
Engine *_engineP;
|
||||
void *_engineR;
|
||||
void (*_redrawEngineCallback)(void *engine);
|
||||
void *_engineAM;
|
||||
void (*_activateMenuCallback)(void *engine);
|
||||
|
||||
MacCursorType _tempType = kMacCursorArrow;
|
||||
Common::Stack<MacCursorType> _cursorTypeStack;
|
||||
Cursor *_cursor = nullptr;
|
||||
|
||||
MacWidget *_activeWidget;
|
||||
MacWidget *_lockedWidget;
|
||||
MacWindow *_backgroundWindow;
|
||||
|
||||
PauseToken *_screenCopyPauseToken;
|
||||
|
||||
Common::Array<ZoomBox *> _zoomBoxes;
|
||||
Graphics::PaletteLookup _paletteLookup;
|
||||
Common::HashMap<uint, uint> _invertColorHash;
|
||||
|
||||
Common::Archive *_dataBundle;
|
||||
|
||||
Common::U32String _clipboard;
|
||||
|
||||
bool _ttsEnabled;
|
||||
};
|
||||
|
||||
const Common::U32String::value_type *readHex(uint16 *res, const Common::U32String::value_type *s, int len);
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user