Permalink
Browse files

GLK: FROTZ: Add support for pair windows to have more than 2 children

This is primarily for the V6 games, which have up to 8 windows
on-screen at the same time in arbitray positions
ext
  • Loading branch information...
dreammaster committed Jan 3, 2019
1 parent 3ed48e3 commit f1d9722f3bd58f7883f3e76c19d4a0133da73489
@@ -22,6 +22,7 @@

#include "glk/frotz/windows.h"
#include "glk/frotz/frotz.h"
#include "glk/window_pair.h"

namespace Glk {
namespace Frotz {
@@ -51,14 +52,16 @@ winid_t Window::getWindow() {
// TODO: For now I'm assuming all the extra created windows will be graphics, since Glk requires
// us to specify it at creation time. Not sure if it's true or not for all V6 games
winid_t parent = _windows->_lower;
_win = g_vm->glk_window_open(parent, winmethod_OnTop | winmethod_Fixed, 0, wintype_Graphics, 0);
_win = g_vm->glk_window_open(g_vm->glk_window_get_root(), winmethod_Arbitrary | winmethod_Fixed,
0, wintype_Graphics, 0);
}

return _win;
}

void Window::setSize(const Point &newSize) {
winid_t win = getWindow();
checkRepositionLower();

win->setSize(newSize);
/* TODO
@@ -73,6 +76,7 @@ void Window::setSize(const Point &newSize) {

void Window::setPosition(const Point &newPos) {
winid_t win = getWindow();
checkRepositionLower();

win->setPosition(newPos);
}
@@ -113,5 +117,17 @@ void Window::setProperty(WindowProperty propType, uint16 value) {
// TODO
}

void Window::checkRepositionLower() {
if (&_windows->_lower == this) {
PairWindow *parent = dynamic_cast<PairWindow *>(_win->_parent);
if (!parent)
error("Parent was not a pair window");

// Ensure the parent pair window is flagged as having children at arbitrary positions,
// just in case it isn't already
parent->_dir = winmethod_Arbitrary;
}
}

} // End of namespace Frotz
} // End of namespace Glk
@@ -64,6 +64,11 @@ class Window {
* Set a property value
*/
void setProperty(WindowProperty propType, uint16 value);

/**
* Called when trying to reposition or resize windows. Does special handling for the lower window
*/
void checkRepositionLower();
public:
/**
* Constructor
@@ -258,10 +258,11 @@ winid_t GlkAPI::glk_window_get_sibling(winid_t win) {
if (!parentWin)
return nullptr;

if (parentWin->_child1 == win)
return parentWin->_child2;
else if (parentWin->_child2 == win)
return parentWin->_child1;
int index = parentWin->_children.indexOf(win);
if (index == ((int)parentWin->_children.size() - 1))
return parentWin->_children.front();
else if (index >= 0)
return parentWin->_children[index + 1];

return nullptr;
}
@@ -150,12 +150,12 @@ enum WinType {
};

enum WinMethod {
winmethod_Left = 0x00,
winmethod_Right = 0x01,
winmethod_Above = 0x02,
winmethod_Below = 0x03,
winmethod_OnTop = 0x04, ///< Newly introduced for ScummGlk
winmethod_DirMask = 0x0f,
winmethod_Left = 0x00,
winmethod_Right = 0x01,
winmethod_Above = 0x02,
winmethod_Below = 0x03,
winmethod_Arbitrary = 0x04, ///< Newly introduced for ScummGlk
winmethod_DirMask = 0x0f,

winmethod_Fixed = 0x10,
winmethod_Proportional = 0x20,
@@ -23,13 +23,20 @@
#ifndef GLK_UTILS_H
#define GLK_UTILS_H

#include "common/array.h"
#include "common/rect.h"
#include "glk/glk_types.h"

namespace Glk {

/**
* Two dimensional point
*/
typedef Common::Point Point;

/**
* Contains a square box/rect area
*/
struct Rect : public Common::Rect {
public:
static Rect fromXYWH(int x, int y, int w, int h) {
@@ -41,6 +48,24 @@ struct Rect : public Common::Rect {
Rect(int16 x1, int16 y1, int16 x2, int16 y2) : Common::Rect(x1, y1, x2, y2) {}
};

/**
* Derived array class
*/
template<class T>class Array : public Common::Array<T> {
public:
/**
* Return the index in the array of a passed item
*/
int indexOf(T val) {
for (size_t idx = 0; idx < this->size(); ++idx) {
if ((*this).operator[](idx) == val)
return idx;
}

return -1;
}
};

/**
* Converts a decimal or hexadecimal string into a number
*/
@@ -34,13 +34,13 @@ PairWindow::PairWindow(Windows *windows, uint method, Window *key, uint size) :
_wBorder((method & winmethod_BorderMask) == winmethod_Border),
_vertical(_dir == winmethod_Left || _dir == winmethod_Right),
_backward(_dir == winmethod_Left || _dir == winmethod_Above),
_key(key), _size(size), _keyDamage(0), _child1(nullptr), _child2(nullptr) {
_key(key), _size(size), _keyDamage(0) {
_type = wintype_Pair;
}

PairWindow::~PairWindow() {
delete _child1;
delete _child2;
for (uint idx = 0; idx < _children.size(); ++idx)
delete _children[idx];
}

void PairWindow::rearrange(const Rect &box) {
@@ -51,24 +51,23 @@ void PairWindow::rearrange(const Rect &box) {
_bbox = box;

if (!_backward) {
ch1 = _child1;
ch2 = _child2;
ch1 = _children[0];
ch2 = _children[1];
} else {
ch1 = _child2;
ch2 = _child1;
ch1 = _children[1];
ch2 = _children[0];
}


if (_dir == winmethod_OnTop) {
// ch2 is on top of ch1
ch1->rearrange(box1);
if (!ch2->_bbox.isEmpty() && !ch2->_bbox.contains(box)) {
// ch2 is outside new bounds, so clip it to the new dimensions
Rect subRect = ch2->_bbox;
subRect.clip(box);
ch2->rearrange(subRect);
if (_dir == winmethod_Arbitrary) {
// When a pair window is in "arbitrary" mode, each child window has it's own independant positioning,
// so thre's no need to be readjusting it
/*
for (int ctr = 0, idx = (_backward ? (int)_children.size() - 1 : 0); ctr < (int)_children.size();
++ctr, idx += (_backward ? -1 : 1)) {
Window *w = _children[idx];
w->rearrange();
}

*/
return;
}

@@ -142,10 +141,12 @@ void PairWindow::rearrange(const Rect &box) {
void PairWindow::redraw() {
Window::redraw();

_child1->redraw();
_child2->redraw();
for (int ctr = 0, idx = (_backward ? (int)_children.size() - 1 : 0); ctr < (int)_children.size();
++ctr, idx += (_backward ? -1 : 1)) {
_children[idx]->redraw();
}

Window *child = !_backward ? _child1 : _child2;
Window *child = !_backward ? _children.front() : _children.back();
Rect box(child->_bbox.left, child->_yAdj ? child->_bbox.top - child->_yAdj : child->_bbox.top,
child->_bbox.right, child->_bbox.bottom);

@@ -184,6 +185,7 @@ void PairWindow::getArrangement(uint *method, uint *size, Window **keyWin) {
void PairWindow::setArrangement(uint method, uint size, Window *keyWin) {
uint newDir;
bool newVertical, newBackward;
assert((method & winmethod_DirMask) != winmethod_Arbitrary && _dir != winmethod_Arbitrary);

if (_key) {
Window *wx;
@@ -226,9 +228,7 @@ void PairWindow::setArrangement(uint method, uint size, Window *keyWin) {

if ((newBackward && !_backward) || (!newBackward && _backward)) {
// switch the children
Window *tmpWin = _child1;
_child1 = _child2;
_child2 = tmpWin;
SWAP(_children[0], _children[1]);
}

// set up everything else
@@ -245,11 +245,12 @@ void PairWindow::setArrangement(uint method, uint size, Window *keyWin) {
}

void PairWindow::click(const Point &newPos) {
if (_child1->_bbox.contains(newPos))
_child1->click(newPos);

if (_child2->_bbox.contains(newPos))
_child2->click(newPos);
for (int ctr = 0, idx = (!_backward ? (int)_children.size() - 1 : 0); ctr < (int)_children.size();
++ctr, idx += (_backward ? -1 : 1)) {
Window *w = _children[idx];
if (w->_bbox.contains(newPos))
w->click(newPos);
}
}

} // End of namespace Glk
@@ -24,15 +24,17 @@
#define GLK_WINDOW_PAIR_H

#include "glk/windows.h"
#include "glk/utils.h"

namespace Glk {

/**
* Pair window
* Acts as a container of child windows. Under most cases there will be exactly two children,
* though in a special new "OnTop" mode, there can be more than two
*/
class PairWindow : public Window {
public:
Window *_child1, *_child2;
Array<Window *> _children;

// split info...
uint _dir; ///< winmethod_Left, Right, Above, Below, or OnTop
Oops, something went wrong.

0 comments on commit f1d9722

Please sign in to comment.