Files
flenser/dw/stackingcontextmgr.cc

194 lines
6.0 KiB
C++

/*
* Dillo Widget
*
* Copyright 2014 Sebastian Geerken <sgeerken@dillo.org>
*
* 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 "core.hh"
#include "../lout/debug.hh"
using namespace lout::misc;
using namespace lout::container::typed;
namespace dw {
namespace core {
StackingContextMgr::StackingContextMgr (Widget *widget)
{
DBG_OBJ_CREATE ("dw::core::StackingContextMgr");
this->widget = widget;
DBG_OBJ_SET_NUM ("childSCWidgets.size", childSCWidgets.size());
numZIndices = 0;
zIndices = NULL;
DBG_OBJ_SET_NUM ("numZIndices", numZIndices);
}
StackingContextMgr::~StackingContextMgr ()
{
if (zIndices)
free (zIndices);
DBG_OBJ_DELETE ();
}
void StackingContextMgr::addChildSCWidget (Widget *widget)
{
DBG_OBJ_ENTER ("common.scm", 0, "addChildSCWidget", "%p [z-index = %d]",
widget, widget->getStyle()->zIndex);
int pos = findZIndex (widget->getStyle()->zIndex, true);
DBG_OBJ_MSGF ("common.scm", 1, "pos = %d", pos);
if (pos == -1) {
pos = findZIndex (widget->getStyle()->zIndex, false);
DBG_OBJ_MSGF ("common.scm", 1, "pos = %d", pos);
numZIndices++;
DBG_OBJ_SET_NUM ("numZIndices", numZIndices);
zIndices = (int*)(zIndices ?
realloc (zIndices, numZIndices * sizeof (int)) :
malloc (numZIndices * sizeof (int)));
for (int i = numZIndices - 1; i >= pos + 1; i--) {
zIndices[i] = zIndices[i - 1];
DBG_OBJ_ARRSET_NUM ("zIndex", i, zIndices[i]);
}
zIndices[pos] = widget->getStyle()->zIndex;
DBG_OBJ_ARRSET_NUM ("zIndex", pos, zIndices[pos]);
}
childSCWidgets.push_back (widget);
DBG_OBJ_SET_NUM ("childSCWidgets.size", childSCWidgets.size());
DBG_OBJ_ARRSET_PTR ("childSCWidgets", childSCWidgets.size() - 1, widget);
DBG_OBJ_LEAVE ();
}
int StackingContextMgr::findZIndex (int zIndex, bool mustExist)
{
int result = -123; // Compiler happiness: GCC 4.7 does not handle this?
if (numZIndices == 0)
result = mustExist ? -1 : 0;
else {
int low = 0, high = numZIndices - 1;
bool found = false;
while (!found) {
int index = (low + high) / 2;
if (zIndex == zIndices[index]) {
found = true;
result = index;
} else {
if (low >= high) {
if (mustExist) {
found = true;
result = -1;
} else {
found = true;
result = zIndex > zIndices[index] ? index + 1 : index;
}
}
if (zIndex < zIndices[index])
high = index - 1;
else
low = index + 1;
}
}
}
return result;
}
void StackingContextMgr::draw (View *view, Rectangle *area, int startZIndex,
int endZIndex, DrawingContext *context)
{
DBG_OBJ_ENTER ("draw", 0, "draw", "[%d, %d, %d * %d], %d, %d",
area->x, area->y, area->width, area->height, startZIndex,
endZIndex);
for (int zIndexIndex = 0; zIndexIndex < numZIndices; zIndexIndex++) {
// Wrong region of z-indices (top or bottom) is simply ignored
// (as well as non-defined zIndices).
if (zIndices != NULL && zIndices[zIndexIndex] >= startZIndex &&
zIndices[zIndexIndex] <= endZIndex) {
DBG_OBJ_MSGF ("draw", 1, "drawing zIndex = %d", zIndices[zIndexIndex]);
DBG_OBJ_MSG_START ();
for (std::size_t i = 0; i < childSCWidgets.size (); i++) {
Widget *child = childSCWidgets.at (i);
DBG_OBJ_MSGF ("draw", 2, "widget %p has zIndex = %d",
child, child->getStyle()->zIndex);
Rectangle childArea;
if (child->getStyle()->zIndex == zIndices[zIndexIndex] &&
child->intersects (widget, area, &childArea))
child->draw (view, &childArea, context);
}
DBG_OBJ_MSG_END ();
}
}
DBG_OBJ_LEAVE ();
}
Widget *StackingContextMgr::getWidgetAtPoint (int x, int y,
GettingWidgetAtPointContext
*context,
int startZIndex, int endZIndex)
{
DBG_OBJ_ENTER ("events", 0, "getWidgetAtPoint", "%d, %d", x, y);
Widget *widgetAtPoint = NULL;
for (int zIndexIndex = numZIndices - 1;
widgetAtPoint == NULL && zIndexIndex >= 0; zIndexIndex--) {
// Wrong region of z-indices (top or bottom) is simply ignored
// (as well as non-defined zIndices).
if (zIndices != NULL && zIndices[zIndexIndex] >= startZIndex &&
zIndices[zIndexIndex] <= endZIndex) {
DBG_OBJ_MSGF ("events", 1, "searching zIndex = %d",
zIndices[zIndexIndex]);
DBG_OBJ_MSG_START ();
for (int i = (int)childSCWidgets.size () - 1;
widgetAtPoint == NULL && i >= 0; i--) {
Widget *child = childSCWidgets.at (i);
DBG_OBJ_MSGF ("events", 2, "widget %p has zIndex = %d",
child, child->getStyle()->zIndex);
if (child->getStyle()->zIndex == zIndices[zIndexIndex])
widgetAtPoint = child->getWidgetAtPoint (x, y, context);
}
DBG_OBJ_MSG_END ();
}
}
DBG_OBJ_MSGF ("events", 0, "=> %p", widgetAtPoint);
DBG_OBJ_LEAVE ();
return widgetAtPoint;
}
} // namespace core
} // namespace dw