/* * Dillo Widget * * Copyright 2005-2007 Sebastian Geerken * * 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 . */ #include "core.hh" #include "../lout/debug.hh" #include namespace dw { namespace core { namespace ui { using namespace lout; using namespace lout::object; int Embed::CLASS_ID = -1; Embed::Embed(Resource *resource) { DBG_OBJ_CREATE ("dw::core::ui::Embed"); registerName ("dw::core::ui::Embed", &CLASS_ID); this->resource = resource; resource->setEmbed (this); DBG_OBJ_ASSOC_CHILD (resource); } Embed::~Embed() { delete resource; DBG_OBJ_DELETE (); } void Embed::sizeRequestSimpl (Requisition *requisition) { resource->sizeRequest (requisition); // TODO Correction should perhaps be left to the resouces. correctRequisition(requisition, core::splitHeightPreserveAscent, true, true); } void Embed::getExtremesSimpl (Extremes *extremes) { resource->getExtremes (extremes); correctExtremes (extremes, false); extremes->adjustmentWidth = misc::max (extremes->minWidthIntrinsic, extremes->minWidth); } void Embed::sizeAllocateImpl (Allocation *allocation) { resource->sizeAllocate (allocation); } int Embed::getAvailWidthOfChild (Widget *child, bool forceValue) { return resource->getAvailWidthOfChild (child, forceValue); } int Embed::getAvailHeightOfChild (Widget *child, bool forceValue) { return resource->getAvailHeightOfChild (child, forceValue); } void Embed::correctRequisitionOfChild (Widget *child, Requisition *requisition, void (*splitHeightFun) (int, int*, int*), bool allowDecreaseWidth, bool allowDecreaseHeight) { resource->correctRequisitionOfChild (child, requisition, splitHeightFun, allowDecreaseWidth, allowDecreaseHeight); } void Embed::correctExtremesOfChild (Widget *child, Extremes *extremes, bool useAdjustmentWidth) { resource->correctExtremesOfChild (child, extremes, useAdjustmentWidth); } void Embed::containerSizeChangedForChildren () { DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren"); resource->containerSizeChangedForChildren (); DBG_OBJ_LEAVE (); } void Embed::enterNotifyImpl (core::EventCrossing *event) { resource->emitEnter(); Widget::enterNotifyImpl(event); } void Embed::leaveNotifyImpl (core::EventCrossing *event) { resource->emitLeave(); Widget::leaveNotifyImpl(event); } bool Embed::buttonPressImpl (core::EventButton *event) { bool handled; if (event->button == 3) { resource->emitClicked(event); handled = true; } else { handled = false; } return handled; } void Embed::setDisplayed (bool displayed) { resource->setDisplayed (displayed); } void Embed::setEnabled (bool enabled) { resource->setEnabled (enabled); } void Embed::draw (View *view, Rectangle *area, DrawingContext *context) { drawWidgetBox (view, area, false); resource->draw (view, area, context); } Iterator *Embed::iterator (Content::Type mask, bool atEnd) { return resource->iterator (mask, atEnd); } void Embed::setStyle (style::Style *style) { resource->setStyle (style); Widget::setStyle (style); } // ---------------------------------------------------------------------- bool Resource::ActivateEmitter::emitToReceiver (lout::signal::Receiver *receiver, int signalNo, int argc, Object **argv) { ActivateReceiver *ar = (ActivateReceiver*)receiver; Resource *res = (Resource*)((Pointer*)argv[0])->getValue (); switch (signalNo) { case 0: ar->activate (res); break; case 1: ar->enter (res); break; case 2: ar->leave (res); break; default: misc::assertNotReached (); } return false; } void Resource::ActivateEmitter::emitActivate (Resource *resource) { Pointer p (resource); Object *argv[1] = { &p }; emitVoid (0, 1, argv); } void Resource::ActivateEmitter::emitEnter (Resource *resource) { Pointer p (resource); Object *argv[1] = { &p }; emitVoid (1, 1, argv); } void Resource::ActivateEmitter::emitLeave (Resource *resource) { Pointer p (resource); Object *argv[1] = { &p }; emitVoid (2, 1, argv); } // ---------------------------------------------------------------------- Resource::~Resource () { DBG_OBJ_DELETE (); } void Resource::setEmbed (Embed *embed) { this->embed = embed; } void Resource::getExtremes (Extremes *extremes) { DBG_OBJ_ENTER0 ("resize", 0, "getExtremes"); /* Simply return the requisition width */ Requisition requisition; sizeRequest (&requisition); extremes->minWidth = extremes->maxWidth = requisition.width; extremes->minWidthIntrinsic = extremes->minWidth; extremes->maxWidthIntrinsic = extremes->maxWidth; DBG_OBJ_MSGF ("resize", 1, "result: %d / %d", extremes->minWidth, extremes->maxWidth); DBG_OBJ_LEAVE (); } void Resource::sizeAllocate (Allocation *allocation) { } int Resource::getAvailWidthOfChild (Widget *child, bool forceValue) { // Only used when the resource contains other dillo widgets. misc::notImplemented ("Resource::getAvailWidthOfChild"); return 0; } int Resource::getAvailHeightOfChild (Widget *child, bool forceValue) { // Only used when the resource contains other dillo widgets. misc::notImplemented ("Resource::getAvailHeightOfChild"); return 0; } void Resource::correctRequisitionOfChild (Widget *child, Requisition *requisition, void (*splitHeightFun) (int, int*, int*), bool allowDecreaseWidth, bool allowDecreaseHeight) { // Only used when the resource contains other dillo widgets. misc::notImplemented ("Resource::correctRequisitionOfChild"); } void Resource::correctExtremesOfChild (Widget *child, Extremes *extremes, bool useAdjustmentWidth) { // Only used when the resource contains other dillo widgets. misc::notImplemented ("Resource::correctExtremesOfChild"); } void Resource::containerSizeChangedForChildren () { // No children by default. } void Resource::setDisplayed (bool displayed) { } void Resource::draw (View *view, Rectangle *area, DrawingContext *context) { } void Resource::setStyle (style::Style *style) { } void Resource::emitEnter () { activateEmitter.emitEnter(this); } void Resource::emitLeave () { activateEmitter.emitLeave(this); } bool Resource::ClickedEmitter::emitToReceiver(lout::signal::Receiver *receiver, int signalNo, int argc, Object **argv) { ((ClickedReceiver*)receiver) ->clicked ((Resource*)((Pointer*)argv[0])->getValue (), (EventButton*)((Pointer*)argv[1])->getValue()); return false; } void Resource::ClickedEmitter::emitClicked (Resource *resource, EventButton *event) { Pointer p1 (resource); Pointer p2 (event); Object *argv[2] = { &p1, &p2 }; emitVoid (0, 2, argv); } // ---------------------------------------------------------------------- Iterator *LabelButtonResource::iterator (Content::Type mask, bool atEnd) { /** \todo Perhaps in brackets? */ // return new TextIterator (getEmbed (), mask, atEnd, getLabel ()); /** \bug Not implemented. */ return new EmptyIterator (getEmbed (), mask, atEnd); } // ---------------------------------------------------------------------- void ComplexButtonResource::LayoutReceiver::resizeQueued (bool extremesChanged) { DBG_OBJ_ENTER ("resize", 0, "LayoutReceiver::resizeQueued", "%s", extremesChanged ? "true" : "false"); resource->queueResize (extremesChanged); DBG_OBJ_LEAVE (); } ComplexButtonResource::ComplexButtonResource () { DBG_OBJ_CREATE ("dw::core::ui::ComplexButtonResource"); layout = NULL; layoutReceiver.resource = this; click_x = click_y = -1; } void ComplexButtonResource::init (Widget *widget) { childWidget = widget; layout = new Layout (createPlatform ()); setLayout (layout); DBG_OBJ_ASSOC_CHILD (layout); layout->setWidget (widget); layout->connect (&layoutReceiver); if (getEmbed ()) childWidget->setQuasiParent (getEmbed ()); } void ComplexButtonResource::setEmbed (Embed *embed) { ButtonResource::setEmbed (embed); if (childWidget) childWidget->setQuasiParent (getEmbed ()); } ComplexButtonResource::~ComplexButtonResource () { delete layout; DBG_OBJ_DELETE (); } void ComplexButtonResource::sizeRequest (Requisition *requisition) { DBG_OBJ_ENTER0 ("resize", 0, "sizeRequest"); Requisition widgetRequisition; childWidget->sizeRequest (&widgetRequisition); requisition->width = widgetRequisition.width + 2 * reliefXThickness (); requisition->ascent = widgetRequisition.ascent + reliefYThickness (); requisition->descent = widgetRequisition.descent + reliefYThickness (); DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)", requisition->width, requisition->ascent, requisition->descent); DBG_OBJ_LEAVE (); } void ComplexButtonResource::getExtremes (Extremes *extremes) { DBG_OBJ_ENTER0 ("resize", 0, "getExtremes"); Extremes widgetExtremes; childWidget->getExtremes (&widgetExtremes); extremes->minWidth = widgetExtremes.minWidth + 2 * reliefXThickness (); extremes->maxWidth = widgetExtremes.maxWidth + 2 * reliefXThickness (); extremes->minWidthIntrinsic = extremes->minWidth; extremes->maxWidthIntrinsic = extremes->maxWidth; DBG_OBJ_MSGF ("resize", 1, "result: %d / %d", extremes->minWidth, extremes->maxWidth); DBG_OBJ_LEAVE (); } void ComplexButtonResource::sizeAllocate (Allocation *allocation) { } int ComplexButtonResource::getAvailWidthOfChild (Widget *child, bool forceValue) { int embedWidth = getEmbed()->getAvailWidth (forceValue); if (embedWidth == -1) return -1; else return misc::max (embedWidth - 2 * reliefXThickness (), 0); } int ComplexButtonResource::getAvailHeightOfChild (Widget *child, bool forceValue) { int embedHeight = getEmbed()->getAvailHeight (forceValue); if (embedHeight == -1) return -1; else return misc::max (embedHeight - 2 * reliefYThickness (), 0); } void ComplexButtonResource::correctRequisitionOfChild (Widget *child, Requisition *requisition, void (*splitHeightFun) (int, int*, int*), bool allowDecreaseWidth, bool allowDecreaseHeight) { // Similar to Widget::correctRequisitionOfChild, but for percentage // the relief has to be considered. if (style::isPerLength (child->getStyle()->width)) { int availWidth = getEmbed()->getAvailHeight (false); if (availWidth != -1) { int baseWidth = misc::max (availWidth - getEmbed()->boxDiffWidth () - 2 * reliefXThickness (), 0); int newWidth = child->applyPerWidth (baseWidth, child->getStyle()->width); requisition->width = allowDecreaseWidth ? newWidth : misc::max (requisition->width, newWidth); } } else getEmbed()->correctReqWidthOfChildNoRec (child, requisition, allowDecreaseWidth); // TODO Percentage heights are ignored again. getEmbed()->correctReqHeightOfChildNoRec(child, requisition, splitHeightFun, allowDecreaseWidth); } void ComplexButtonResource::correctExtremesOfChild (Widget *child, Extremes *extremes, bool useAdjustmentWidth) { // Similar to Widget::correctExtremesOfChild, but for percentage // the relief has to be considered. if (style::isPerLength (child->getStyle()->width)) { int availWidth = getEmbed()->getAvailHeight (false); if (availWidth != -1) { int baseWidth = misc::max (availWidth - getEmbed()->boxDiffWidth () - 2 * reliefXThickness (), 0); extremes->minWidth = extremes->maxWidth = child->applyPerWidth (baseWidth, child->getStyle()->width); } } else getEmbed()->correctExtremesOfChildNoRec (child, extremes, useAdjustmentWidth); } void ComplexButtonResource::containerSizeChangedForChildren () { layout->containerSizeChanged (); } Iterator *ComplexButtonResource::iterator (Content::Type mask, bool atEnd) { /** * \bug Implementation. * This is a bit more complicated: We have two layouts here. */ return new EmptyIterator (getEmbed (), mask, atEnd); } // ---------------------------------------------------------------------- Iterator *TextResource::iterator (Content::Type mask, bool atEnd) { // return new TextIterator (getEmbed (), mask, atEnd, getText ()); /** \bug Not implemented. */ return new EmptyIterator (getEmbed (), mask, atEnd); } // ---------------------------------------------------------------------- Iterator *CheckButtonResource::iterator (Content::Type mask, bool atEnd) { //return new TextIterator (getEmbed (), mask, atEnd, // isActivated () ? "[X]" : "[ ]"); /** \bug Not implemented. */ return new EmptyIterator (getEmbed (), mask, atEnd); } // ---------------------------------------------------------------------- RadioButtonResource::GroupIterator::~GroupIterator () { } Iterator *RadioButtonResource::iterator (Content::Type mask, bool atEnd) { //return new TextIterator (getEmbed (), mask, atEnd, // isActivated () ? "(*)" : "( )"); /** \bug Not implemented. */ return new EmptyIterator (getEmbed (), mask, atEnd); } } // namespace ui } // namespace core } // namespace dw