/* * pawswidget.cpp - Author: Andrew Craig * * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.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 (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ // pawswidget.cpp: implementation of the pawsWidget class. // ////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "util/localization.h" #include "pawswidget.h" #include "pawsmanager.h" #include "pawstexturemanager.h" #include "pawsprefmanager.h" #include "pawsborder.h" #include "pawsmenu.h" #include "pawsmainwidget.h" #include "util/log.h" #include "util/psstring.h" #include "widgetconfigwindow.h" #define RX(x) ((int) ((((float)x)*ratioX)+.5)) #define RY(y) ((int) ((((float)y)*ratioY)+.5)) //#define PAWS_CONSTRUCTION // Enable this to be able to move around widgets at will ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// pawsWidget::pawsWidget( ) { graphics2D = PawsManager::GetSingleton().GetGraphics2D(); screenFrame = csRect(0,0,0,0); clipRect = csRect(0,0,0,0); saveWidgetPositions = false; visible = true; movable = false; alwaysOnTop = false; isResizable = false; showResize = true; resizeToScreen = true; id = -1; parent = NULL; bgColour = -1; bgImage = NULL; border = NULL; name = "None"; attachFlags = 0; fadeVal = 100; fadeSpeed = 8.0f; fade = true; alphaMin=0; alpha=0; hasFocus = false; hasMouseFocus=false; configurable = false; fontStyle = 0; min_height = DEFAULT_MIN_HEIGHT; min_width = DEFAULT_MIN_WIDTH; max_height = graphics2D->GetHeight(); max_width = graphics2D->GetWidth(); hasBorderColours = false; contextMenu = NULL; xmlbinding = ""; ignore = false; maskImage = NULL; onEnter = NULL; margin = 0; close_widget = 0; extraData = 0; defaultFontColour = -1; fontSize = 10; fontScaling = 0; // none } pawsWidget::~pawsWidget() { // Check to see if the widget position should be save. if ( saveWidgetPositions ) SavePosition(); if ( configurable ) SaveSettings(); if ( fontScaling ) SaveFontSettings(); while ( children.Length() > 0 ) { pawsWidget* wdg = children.Pop(); if (wdg) delete wdg; } if (contextMenu != NULL) { PawsManager::GetSingleton().GetMainWidget()->DeleteChild(contextMenu); contextMenu = NULL; } PawsManager::GetSingleton().UnSubscribe(this); PawsManager::GetSingleton().OnWidgetDeleted(this); delete bgImage; delete border; if (maskImage) delete maskImage; delete extraData; if (parent) parent->RemoveChild(this); } void pawsWidget::SetFilename(const char *name) { filename=name; } const char *pawsWidget::GetFilename() { return filename; } bool pawsWidget::CheckButtonPressed( int button, int modifiers, pawsWidget* pressedWidget ) { if ( pressedWidget->GetName()!=NULL && GetCloseName()!=NULL && strcmp( pressedWidget->GetName(),GetCloseName())==0 ) { Close(); return true; } else return OnButtonPressed( button, modifiers, pressedWidget ); } /* * Check to see if this widget contains these coordinates at all. * Recurse through children to see if they could the one the mouse is over. * Return this widget if no children contain the coords. */ pawsWidget* pawsWidget::WidgetAt( int x, int y ) { if ( ignore ) return NULL; if ( Contains( x, y ) == false ) { return NULL; } //Recurse through children to see if they could the one the mouse is over. for (size_t z = 0; z < children.Length(); z++ ) { if ( !children[z]->ignore && children[z]->IsVisible() ) { if ( children[z]->Contains(x,y) ) return children[z]->WidgetAt( x , y ); } } //Return this widget if no children contain the coords. return this; } bool pawsWidget::Contains( int x, int y ) { if ( border ) { return border->GetRect().Contains(x,y); } else return screenFrame.Contains(x,y); } void pawsWidget::SetParent( pawsWidget* newParent ) { parent = newParent; } void pawsWidget::AddChild( pawsWidget* childWidget ) { if ( !childWidget ) return; if ( childWidget->IsAlwaysOnTop() ) children.Insert( 0, childWidget ); else children.Push( childWidget ); // Let the child know that he is attached to this widget. childWidget->SetParent( this ); } void pawsWidget::RemoveChild( pawsWidget* widget ) { if ( !widget ) return; children.Delete( widget ); } void pawsWidget::DeleteChild( pawsWidget* widget ) { RemoveChild(widget); delete widget; } bool pawsWidget::IsIndirectChild( pawsWidget * widget ) { for (size_t z = 0; z < children.Length(); z++ ) { if (children[z] == widget) return true; if (children[z]->IsIndirectChild(widget)) return true; } return false; } bool pawsWidget::Includes( pawsWidget * widget ) { return widget && (widget == this || IsIndirectChild(widget)); } bool pawsWidget::LoadAttributes( iDocumentNode* node ) { // Get the name for this widget. csRef atr = node->GetAttribute("name"); if ( !atr ) { Error1("Widget has not defined a name. Error in XML"); return false; } SetName(csString( atr->GetValue() )); atr = node->GetAttribute("style"); if (atr) PawsManager::GetSingleton().ApplyStyle(atr->GetValue(), node); atr = node->GetAttribute("ignore"); if ( atr ) { csString choice = csString( atr->GetValue() ); if ( choice == "yes" ) ignore = true; if ( choice == "no" ) ignore = false; } // Check to see if this widget is visible directly after a load. atr = node->GetAttribute( "visible" ); if ( atr ) { csString choice = csString( atr->GetValue() ); if ( choice == "yes" ) Show(); if ( choice == "no" ) Hide(); } // Check to see if this widget should save it's position atr = node->GetAttribute("savepositions"); if ( atr ) { csString choice = csString(atr->GetValue()); if ( choice == "yes" ) saveWidgetPositions = true; if ( choice == "no" ) saveWidgetPositions = false; } // Check to see if this widget is movable atr = node->GetAttribute("movable"); if ( atr ) { csString choice = csString(atr->GetValue()); if ( choice == "yes" ) movable = true; if ( choice == "no" ) movable = false; } // Check to see if this widget is configurable atr = node->GetAttribute("configurable"); if ( atr ) { csString choice = csString(atr->GetValue()); if ( choice == "yes" ) configurable = true; if ( choice == "no" ) configurable = false; } // Check to see if this widget's font is configurable atr = node->GetAttribute("scalablefont"); if ( atr ) { csString choice = csString(atr->GetValue()); if ( choice == "yes" ) fontScaling = 100; if ( choice == "no" ) fontScaling = 0; } if ( fontScaling ) { LoadFontSettings(); } atr = node->GetAttribute( "resizable" ); if ( atr ) { csString choice = csString(atr->GetValue()); if ( choice == "yes" ) isResizable = true; if ( choice == "no" ) isResizable = false; } atr = node->GetAttribute( "resizetoscreen" ); if ( atr ) { resizeToScreen = atr->GetValueAsBool(); } else if (parent) { resizeToScreen = parent->resizeToScreen; } atr = node->GetAttribute( "ContextMenu" ); if ( atr ) contextMenuFile = atr->GetValue(); atr = node->GetAttribute( "id" ); if ( atr ) { id = atr->GetValueAsInt(); } atr = node->GetAttribute( "xmlbinding" ); if ( atr ) { xmlbinding = atr->GetValue(); } // Get tool tip, if any atr = node->GetAttribute( "tooltip" ); if (atr) { toolTip = atr->GetValue(); defaultToolTip =toolTip; } // Get the optional font for this widget csRef fontAttribute = node->GetNode("font"); if ( fontAttribute ) { fontName = fontAttribute->GetAttributeValue("name"); fontSize = fontAttribute->GetAttributeValueAsFloat("size"); bool scaleToScreen = fontAttribute->GetAttributeValueAsBool("resizetoscreen",true); if ( this->resizeToScreen && scaleToScreen ) fontSize *= PawsManager::GetSingleton().GetFontFactor(); if (fontScaling) fontSize *= ((float)fontScaling / 100.0f); myFont = graphics2D->GetFontServer()->LoadFont( fontName , (fontSize)? fontSize:10 ); if ( !myFont ) { Error2("Could not load font: >%s<", (const char*)fontName ); return false; } int r = fontAttribute->GetAttributeValueAsInt( "r" ); int g = fontAttribute->GetAttributeValueAsInt( "g" ); int b = fontAttribute->GetAttributeValueAsInt( "b" ); if ( r == -1 && g == -1 && b == -1 ) defaultFontColour = PawsManager::GetSingleton().GetPrefs()->GetDefaultFontColour(); else defaultFontColour = graphics2D->FindRGB( r, g, b ); r = fontAttribute->GetAttributeValueAsInt( "sr" ); g = fontAttribute->GetAttributeValueAsInt( "sg" ); b = fontAttribute->GetAttributeValueAsInt( "sb" ); defaultFontShadowColour = graphics2D->FindRGB( r, g, b ); if (fontAttribute->GetAttributeValueAsBool( "shadow" )) fontStyle |= FONT_DROPSHADOW; } // Get the frame for this widget. csRef frameNode = node->GetNode( "frame" ); if ( frameNode ) { defaultFrame.xmin = GetActualWidth(frameNode->GetAttributeValueAsInt("x")); defaultFrame.ymin = GetActualHeight(frameNode->GetAttributeValueAsInt("y")); int width = GetActualWidth(frameNode->GetAttributeValueAsInt("width")); int height = GetActualHeight(frameNode->GetAttributeValueAsInt("height")); if (width < min_width) width = min_width; if (height < min_height) height = min_height; defaultFrame.SetSize( width, height ); // If this widget has a parent then move it to it's correct relative position. if ( parent ) { MoveTo(parent->ScreenFrame().xmin + defaultFrame.xmin, parent->ScreenFrame().ymin + defaultFrame.ymin); screenFrame.SetSize( width, height ); } else { MoveTo( defaultFrame.xmin, defaultFrame.ymin ); SetSize( defaultFrame.Width(), defaultFrame.Height() ); } csRef useBorder = frameNode->GetAttribute("border"); if ( useBorder ) { csString borderString = useBorder->GetValue(); if ( borderString != "no" ) { if ( borderString == "yes" ) borderString.Replace("line"); border = new pawsBorder(borderString ); border->SetParent(this); } } if ( border ) { csRef useJustTitle = frameNode->GetAttribute("justtitle"); if ( useJustTitle ) { csString useJustTitleString = useJustTitle->GetValue(); if ( useJustTitleString != "no" ) border->JustTitle(); } } atr = frameNode->GetAttribute( "margin" ); if (atr) margin = atr->GetValueAsInt(); } // Process title bar, if any csRef titleNode = node->GetNode("title"); if (titleNode) { csString title = titleNode->GetAttributeValue("text"); csString image = titleNode->GetAttributeValue("resource"); csString align = titleNode->GetAttributeValue("align"); csString close = titleNode->GetAttributeValue( "close_button" ); SetTitle( title, image, align, close ); } csRef borderNode = node->GetNode( "childborders" ); if (borderNode) LoadBorderColours(borderNode); csRef bgColourNode = node->GetNode( "bgcolour" ); if ( bgColourNode ) { int r = bgColourNode->GetAttributeValueAsInt("r"); int g = bgColourNode->GetAttributeValueAsInt("g"); int b = bgColourNode->GetAttributeValueAsInt("b"); bgColour = graphics2D->FindRGB( r, g, b ); } else { bgColour = -1; } // Get the background image attribute csRef bgImageNode = node->GetNode( "bgimage" ); if ( bgImageNode ) { csString image = bgImageNode->GetAttributeValue("resource"); psImageDescription* imageDesc = PawsManager::GetSingleton().GetTextureManager()->GetImageDescription( image ); if(!imageDesc) { Warning2(LOG_PAWS, "GUI image '%s' not found.\n", image.GetData()); } else { bgImage = new pawsImage( PawsManager::GetSingleton().GetObjectRegistry() ); bgImage->Description( imageDesc ); csRef alphaattr = bgImageNode->GetAttribute("alpha"); if ( alphaattr ) bgImage->SetAlpha( alphaattr->GetValueAsInt() ); // Get the initial alpha value alpha = bgImage->GetAlpha(); //alphaMax = alpha; csRef fadeattr = bgImageNode->GetAttribute("fading"); if (fadeattr) fade = fadeattr->GetValueAsBool(); } } else { bgImage = NULL; } if ( configurable ) { LoadSettings(); } // Get the masking image attribute csRef maskImageNode = node->GetNode( "mask" ); if ( maskImageNode ) { csString imageStr = maskImageNode->GetAttributeValue("resource"); if (imageStr != "") SetMaskingImage(imageStr); } // Get the data subscriptions csRef subsNode = node->GetNode( "subscriptions" ); if ( subsNode ) { overwrite_subscription = subsNode->GetAttributeValueAsBool("overwrite",true); subscription_format = subsNode->GetAttributeValue("format"); csRef points = subsNode->GetNodes(); while ( points->HasNext() ) { csRef point = points->Next(); if (point->GetAttributeValue("data")) { PawsManager::GetSingleton().Subscribe(point->GetAttributeValue("data"),this); } } } // Get the attachment points csRef attachPointsNode = node->GetNode( "attachpoints" ); if ( attachPointsNode ) { csRef points = attachPointsNode->GetNodes(); while ( points->HasNext() ) { csRef point = points->Next(); attachFlags |= GetAttachFlag( point->GetAttributeValue("point") ); } } // Get the min width and height csRef minFrameNode = node->GetNode( "minframe" ); if ( minFrameNode ) { min_width = GetActualWidth(minFrameNode->GetAttributeValueAsInt("width")); min_height = GetActualHeight(minFrameNode->GetAttributeValueAsInt("height")); } // Get the max width and height csRef maxFrameNode = node->GetNode( "maxframe" ); if ( maxFrameNode ) { max_width = GetActualWidth(maxFrameNode->GetAttributeValueAsInt("width")); max_height = GetActualHeight(maxFrameNode->GetAttributeValueAsInt("height")); } return true; } void pawsWidget::ReloadWidget() { if (!GetFilename()) parent->ReloadWidget(); else { csString copyname = filename; delete this; PawsManager::GetSingleton().LoadWidget(copyname); } } bool pawsWidget::Load( iDocumentNode* node ) { if ( ! LoadAttributes(node) ) return false; // Call the setup for this widget. if ( !Setup( node ) ) { Error2("Widget %s Setup Failed", GetName() ); return false; } if ( ! LoadChildren(node) ) return false; if ( !PostSetup() ) { Error2("Failed the PostSetup for %s", GetName() ); return false; } // Check to see if we have possible saved positions to use. if ( saveWidgetPositions ) { csRect pos = LoadPositions(); // Resize to loaded positions. MoveTo( pos.xmin, pos.ymin ); //only set size if widget is resizable if ( IsResizable() ) SetSize( pos.Width(), pos.Height() ); } Resize(); Resize( 0, 0, RESIZE_RIGHT | RESIZE_BOTTOM | RESIZE_TOP | RESIZE_BOTTOM ); StopResize(); return true; } bool pawsWidget::LoadChildren( iDocumentNode* node ) { pawsWidget* widget; // Get an iterator over all the child widgets csRef childIter = node->GetNodes ("widget"); while ( childIter->HasNext() ) { csRef childWidgetNode = childIter->Next(); widget=NULL; // Check if the child should be loaded from csString file = childWidgetNode->GetAttributeValue( "file" ); if (!file.IsEmpty()) { size_t i; csArray childarray; PawsManager::GetSingleton().LoadChildWidgets(file,childarray); for (i=0;i 1) return true; if (childarray.Length()) widget=childarray[0]; } // If a widget hasn't been loaded here - either due to a failure to load above or // because no file was specified, parse this node as an embedded widget definition if (!widget) { csString factory = childWidgetNode->GetAttributeValue( "factory" ); if ( factory.Length() == 0 ) { Error1("Could not read factory from XML file. Error in XML"); return false; } widget = PawsManager::GetSingleton().CreateWidget( factory ); CS_ASSERT( widget ); AddChild( widget ); } // Let the widget parse the rest of the node information if ( widget->Load( childWidgetNode ) == false ) { Error1("Failed to load child widget"); return false; } } // Need to load form properties here, because we need to have the children loaded // Get form properties csRef formNode = node->GetNode("form"); if (formNode) { csRef fNode = formNode->GetNodes(); while(fNode->HasNext()) { csRef lNode = fNode->Next(); if (!strcmp(lNode->GetValue(),"enter")) { onEnter = FindWidget(lNode->GetAttributeValue("name")); } if (!strcmp(lNode->GetValue(),"tab")) { pawsWidget* wdg = FindWidget(lNode->GetAttributeValue("name")); if (wdg) taborder.Push(wdg); } } } return true; } void pawsWidget::ShowBehind() { visible = true; if ( border ) border->Show(); pawsWidget * focused = PawsManager::GetSingleton().GetCurrentFocusedWidget(); if ( focused ) focused->Show(); } void pawsWidget::Show() { visible = true; if ( border ) border->Show(); BringToTop( this ); } void pawsWidget::Hide() { visible = false; if ( border ) border->Hide(); PawsManager::GetSingleton().OnWidgetHidden(this); } void pawsWidget::SetRelativeFrame( int x, int y, int width, int height ) { SetRelativeFramePos( x, y ); SetRelativeFrameSize( width, height ); } void MoveRect(csRect & rect, int x, int y) { int width = rect.Width(); int height = rect.Height(); rect.Set(x, y, x+width, y+height); } void pawsWidget::SetRelativeFramePos( int x, int y ) { MoveRect(defaultFrame, x, y); if (parent != NULL) MoveRect(screenFrame, parent->ScreenFrame().xmin + x, parent->ScreenFrame().ymin + y); else MoveRect(screenFrame, y, y); for ( size_t x = 0; x < children.Length(); x++ ) children[x]->RecalcScreenPositions(); } void pawsWidget::SetRelativeFrameSize( int width, int height ) { defaultFrame .SetSize( width, height ); screenFrame .SetSize( width, height ); OnResize(); for ( size_t x = 0; x < children.Length(); x++ ) children[x]->RecalcScreenPositions(); } void pawsWidget::RecalcScreenPositions() { if ( parent ) { screenFrame.xmin = parent->ScreenFrame().xmin + defaultFrame.xmin; screenFrame.ymin = parent->ScreenFrame().ymin + defaultFrame.ymin; screenFrame.SetSize( defaultFrame.Width(), defaultFrame.Height() ); for ( size_t x = 0; x < children.Length(); x++ ) children[x]->RecalcScreenPositions(); } } void pawsWidget::UseBorder( const char* style ) { border = new pawsBorder( style ); border->SetParent( this ); } void pawsWidget::SetBackground( const char* image ) { psImageDescription* imageDesc = PawsManager::GetSingleton().GetTextureManager()->GetImageDescription( image ); if ( imageDesc == NULL ) { csString parentName("None"); if ( parent ) parentName = parent->GetName(); Warning4( LOG_PAWS, "Widget: %s (Parent: %s) Could Not load image: %s", name.GetData(), parentName.GetData(), image ); return; } if ( bgImage ) delete bgImage; bgImage = new pawsImage( PawsManager::GetSingleton().GetObjectRegistry() ); bgImage->Description( imageDesc ); // Get the initial alpha value alpha = bgImage->GetAlpha(); } csString pawsWidget::GetBackground() { if (bgImage && bgImage->GetDescription() ) { return bgImage->GetDescription()->resourceName; } return csString(""); } void pawsWidget::SetBackgroundAlpha( int value ) { if ( bgImage ) { bgImage->SetAlpha( value ); // Get the initial alpha value alpha = value; alphaMin = value; } } pawsWidget* pawsWidget::FindWidget( const char* name, bool complain ) { if (!name) return NULL; csString temp(name); if ( this->name == temp ) return this; for ( size_t z = 0; z < children.Length(); z++ ) { pawsWidget* widget = children[z]->FindWidget( name, false ); if ( widget != NULL ) return widget; } /*This check needs to be done here, because it might happen that even if this->name == "None", it has children and so it can return a widget! */ if (this->name == "None") return NULL; if (complain) Error3( "Could not locate widget %s in %s", name, this->name.GetData() ); return NULL; } pawsWidget* pawsWidget::FindWidget( int ID, bool complain ) { if ( this->id == ID ) return this; for ( size_t z = 0; z < children.Length(); z++ ) { pawsWidget* widget = children[z]->FindWidget( ID, false ); if ( widget != NULL ) return widget; } if (complain) Error3( "Could not locate widget ID=%i in %s", ID, name.GetData() ); return NULL; } pawsWidget* pawsWidget::FindWidgetXMLBinding( const char* xmlbinding ) { csString temp(xmlbinding); if ( (this->xmlbinding == temp) || (this->xmlbinding == "" && name == temp )) return this; for ( size_t z = 0; z < children.Length(); z++ ) { pawsWidget* widget = children[z]->FindWidgetXMLBinding( xmlbinding ); if ( widget != NULL ) return widget; } return NULL; } void pawsWidget::DrawBackground() { if ( bgColour != -1 ) { graphics2D->DrawBox( screenFrame.xmin, screenFrame.ymin, screenFrame.Width(), screenFrame.Height(), bgColour ); } if ( bgImage ) { bool focus = hasFocus; // If my children are focused, I should fade like I am focused if (!focus) { for ( size_t x = children.Length(); x-- > 0; ) focus = children[x]->HasFocus(); } // if the fading feature for this widget is enabled if (alpha && fade) { // if the widget hasn't got the focus if (!focus) { // and the mouse is inside the widget if (hasMouseFocus) // slowly become opaque fadeVal-=fadeSpeed; else // else slowly fade out fadeVal+=fadeSpeed; } else // when it has got the focus become/stay opaque fadeVal=0; if (fadeVal<0) fadeVal=0; if (fadeVal>100) fadeVal=100; bgImage->SetAlpha((int)(alphaMin + (alpha-alphaMin) * fadeVal * 0.010)); if (maskImage) maskImage->SetAlpha((int)(alphaMin + (alpha-alphaMin) * fadeVal * 0.010)); } bgImage->Draw( screenFrame ); } if (fade && parent && parent->GetMaxAlpha() >= 0 && bgImage != NULL && maskImage != NULL) { fadeVal = parent->GetFadeVal(); alpha = parent->GetMaxAlpha(); alphaMin = parent->GetMinAlpha(); int drawAlpha = (int) (alphaMin + (alpha-alphaMin) * fadeVal * 0.010); if ( bgImage )bgImage->SetAlpha(drawAlpha); if ( maskImage )maskImage->SetAlpha(drawAlpha); } if ( border ) border->Draw(); if ( IsResizable() && showResize ) { pawsImage* resize = PawsManager::GetSingleton().GetResizeImage(); resize->Draw( ScreenFrame().xmax-8, ScreenFrame().ymax-8,8,8 ); } } void pawsWidget::Draw() { // Setup our clipping rect so we know where we can draw ClipToParent(); // If we can't draw anywhere, then don't try. Our children can't be drawn either. if (clipRect.IsEmpty()) return; DrawBackground(); DrawChildren(); // Draw the masking image if (maskImage) { graphics2D->SetClipRect( 0,0, graphics2D->GetWidth(), graphics2D->GetHeight()); maskImage->Draw( screenFrame.xmin, screenFrame.ymin, defaultFrame.Width(), defaultFrame.Height() ); } } void pawsWidget::DrawWidgetText(const char *text, int x, int y, int style) { csRef font = GetFont(); if (style==-1) style = GetFontStyle(); if (parent && !parent->GetBackground().IsEmpty() && parent->isFadeEnabled() && parent->GetMaxAlpha() != parent->GetMinAlpha()) { int a = (int) (255 - (parent->GetMinAlpha() + (parent->GetMaxAlpha()-parent->GetMinAlpha()) * parent->GetFadeVal() * 0.010)); int r, g, b; if (style & FONT_DROPSHADOW) { graphics2D->GetRGB(GetFontShadowColour(), r, g, b); graphics2D->Write( font, x+2, y+2, graphics2D->FindRGB(r, g, b, a), -1, text ); } graphics2D->GetRGB(GetFontColour(), r, g, b); graphics2D->Write( font, x, y, graphics2D->FindRGB(r, g, b, a), -1, text); } else { if (style & FONT_DROPSHADOW) graphics2D->Write( font, x+2, y+2, GetFontShadowColour(), -1, text ); graphics2D->Write( font, x, y, GetFontColour(), -1, text); } } void pawsWidget::SetFade(bool value) { fade = value; if ( !value && bgImage ) bgImage->SetAlpha(alphaMin); } void pawsWidget::FormatToolTip( const char *fmt, ... ) { char text[128]; va_list args; va_start(args, fmt); cs_vsnprintf(text,sizeof(text),fmt,args); va_end(args); SetToolTip( (const char*)text ); } void pawsWidget::DrawToolTip(int x, int y) { if (toolTip.Length() == 0) return; if(!IsVisible()) return; int width=0; int height=0; int realX = x, realY = y; //iFont* font = GetFont(); csString fontName = "/planeshift/data/ttf/cupandtalon.ttf"; csRef font = graphics2D->GetFontServer()->LoadFont(fontName,16); iFont* fontPtr = font; if (!fontPtr) { Error2("Couldn't load font '%s', reverting to default",fontName.GetData()); fontPtr = GetFont(); } fontPtr->GetDimensions( toolTip , width, height ); // Draw above the cursor for the time being realY = realY - height - 2; realX += 2; realY += 1; if (realY < 0) { realY = 5; realX += PawsManager::GetSingleton().GetMouse()->GetImageSize().width + 2; } if (realX + width > graphics2D->GetWidth()) realX = graphics2D->GetWidth() - width - 5; // Note: negative value on realX is impossible //Shadow graphics2D->Write( fontPtr, realX+1, realY+1, graphics2D->FindRGB(0, 0, 0), -1, toolTip); //Text graphics2D->Write( fontPtr, realX, realY, graphics2D->FindRGB(255, 255, 255), -1, toolTip); } void pawsWidget::DrawChildren() { for ( size_t x = children.Length(); x-- > 0; ) { if ( children[x]->IsVisible() ) { children[x]->Draw(); } } } int pawsWidget::CalcChildPosition(pawsWidget * child) { int pos; pos = 0; if ( ! child->IsAlwaysOnTop() ) { for (size_t x = 0; x < children.Length(); x++ ) if ( children[x]->IsAlwaysOnTop() ) pos++; } return pos; } void pawsWidget::BringToTop( pawsWidget* widget ) { for (size_t x = 0; x < children.Length(); x++ ) { if ( children[x] == widget ) { children.DeleteIndex(x); children.Insert(CalcChildPosition(widget), widget); break; } } if ( parent ) parent->BringToTop( this ); } void pawsWidget::SetTitle(const char *title) { if (border!=NULL) { border->SetTitle(title); border->Draw(); } } void pawsWidget::SaveSettings() { csRef cfgMgr; cfgMgr = CS_QUERY_REGISTRY( PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager ); csRef config = cfgMgr->LookupDomain(PawsManager::GetSingleton().GetConfigFile()); char buffer[512]; sprintf(buffer, "PlaneShift.GUI.%s.MinTransparency", GetName() ); config->SetInt(buffer, alphaMin ); sprintf(buffer, "PlaneShift.GUI.%s.MaxTransparency", GetName() ); config->SetInt(buffer, alpha ); sprintf(buffer, "PlaneShift.GUI.%s.FadeSpeed", GetName() ); config->SetFloat( buffer, fadeSpeed ); sprintf(buffer, "PlaneShift.GUI.%s.Fade", GetName() ); config->SetBool( buffer, fade ); config->Save(); } void pawsWidget::LoadSettings() { csRef cfgMgr; cfgMgr = CS_QUERY_REGISTRY( PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager ); char buffer[512]; csRef config = cfgMgr->LookupDomain(PawsManager::GetSingleton().GetConfigFile()); sprintf(buffer, "PlaneShift.GUI.%s.MaxTransparency", GetName() ); SetBackgroundAlpha(config->GetInt (buffer, alpha )); sprintf(buffer, "PlaneShift.GUI.%s.MinTransparency", GetName() ); alphaMin = config->GetInt (buffer, alphaMin ); sprintf(buffer, "PlaneShift.GUI.%s.Fade", GetName() ); fade = config->GetBool (buffer, fade ); if(!fade && bgImage) bgImage->SetAlpha(alphaMin); sprintf(buffer, "PlaneShift.GUI.%s.FadeSpeed", GetName() ); fadeSpeed = config->GetFloat (buffer, fadeSpeed ); } void pawsWidget::SaveFontSettings() { csRef cfgMgr; cfgMgr = CS_QUERY_REGISTRY( PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager ); csRef config = cfgMgr->LookupDomain(PawsManager::GetSingleton().GetConfigFile()); char buffer[512]; sprintf(buffer, "PlaneShift.GUI.%s.FontScaling", GetName() ); config->SetInt(buffer, fontScaling); config->Save(); } void pawsWidget::LoadFontSettings() { csRef cfgMgr; cfgMgr = CS_QUERY_REGISTRY( PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager ); csRef config = cfgMgr->LookupDomain(PawsManager::GetSingleton().GetConfigFile()); char buffer[512]; sprintf(buffer, "PlaneShift.GUI.%s.FontScaling", GetName() ); fontScaling = config->GetInt (buffer, fontScaling); } void pawsWidget::CreateWidgetConfigWindow() { psString title = name + "settings"; pawsWidget * widget = PawsManager::GetSingleton().GetMainWidget()->FindWidget(title); // there can only be one config window active for each widget WidgetConfigWindow* configWindow = dynamic_cast(widget); if ( widget ==NULL) { configWindow = new WidgetConfigWindow(); configWindow->LoadFromFile("data/gui/widgetconfigwindow.xml"); configWindow->SetConfigurableWidget(this); configWindow->SetName(title); configWindow->Show(); PawsManager::GetSingleton().GetMainWidget()->AddChild(configWindow); } else { configWindow->SetConfigurableWidget(this); configWindow->Show(); } } void pawsWidget::DestroyWidgetConfigWindow() { psString title = name + "settings"; pawsWidget * widget = PawsManager::GetSingleton().GetMainWidget()->FindWidget(title); // there can only be one config window active for each widget WidgetConfigWindow* configWindow = dynamic_cast(widget); if(configWindow) { configWindow->Hide(); PawsManager::GetSingleton().GetMainWidget()->DeleteChild(configWindow); } } bool pawsWidget::CreateContextMenu() { psPoint mousePos; mousePos = PawsManager::GetSingleton().GetMouse()->GetPosition(); contextMenu = new pawsMenu(); if ( ! contextMenu->LoadFromFile(contextMenuFile) ) { delete contextMenu; contextMenu = NULL; return false; } contextMenu->SetNotify(this); PawsManager::GetSingleton().GetMainWidget()->AddChild(contextMenu); contextMenu->CenterTo(mousePos.x, mousePos.y); contextMenu->MakeFullyVisible(); contextMenu->Show(); contextMenu->SetAlwaysOnTop(true); // add an 'settings' option to the menu if 'configurable' // is set to 'yes' if (configurable) { // add menu item "ConfigWindow" pawsMenuItem *item = new pawsMenuItem(); item->MakeFullyVisible(); item->Show(); item->SetAlwaysOnTop(true); item->SetColour(0xffffff); item->SetLabel("Settings"); item->SetSizes(-1, 1, 1); item->SetName("Settings"); // assign "configure"-action to this menu item pawsMenuAction action; action.name="configure"; item->SetAction(action); // item->SetConfigurableWidget(this); // add item to menu contextMenu->AddItem(item); } return true; } int pawsWidget::ResizeFlags( int x, int y ) { csRect frame = ScreenFrame(); csRect hotButton( 0,0,0,0 ); int flag = 0; hotButton= csRect( frame.xmax-8, frame.ymax-8, frame.xmax, frame.ymax ); if ( hotButton.Contains(x,y) ) { flag |= RESIZE_BOTTOM; flag |= RESIZE_RIGHT; } return flag; } bool pawsWidget::OnMouseEnter() { if ( parent ) return parent->OnChildMouseEnter( this ); else return true; } bool pawsWidget::OnChildMouseEnter( pawsWidget* widget ) { return true; } bool pawsWidget::OnMouseExit() { if ( parent ) return parent->OnChildMouseExit( this ); else return true; } bool pawsWidget::OnChildMouseExit( pawsWidget* child ) { return true; } bool pawsWidget::OnMouseDown( int button, int modifiers, int x, int y ) { #ifdef PAWS_CONSTRUCTION if ( modifiers == 1 ) { SetMovable(true); isResizable = true; showResize = true; } if ( modifiers == 2 ) { printf("-----------WIDGET %s DUMP---------\n", name.GetData() ); printf("Position: (%d,%d)\n", ScreenFrame().xmin-parent->ScreenFrame().xmin, ScreenFrame().ymin-parent->ScreenFrame().ymin); printf("Size : (%d,%d)\n", ScreenFrame().Width(), ScreenFrame().Height()); } if ( modifiers == 3 ) { ReloadWidget(); return true; } #endif if ( !PawsManager::GetSingleton().GetDragDropWidget() ) { if (button == csmbLeft) { if ( isResizable && showResize ) { // Check to see if the mouse was in the resizing flags int flags = ResizeFlags(x,y) ; if ( flags ) { PawsManager::GetSingleton().ResizingWidget( this, flags ); return true; } } if ( movable ) { PawsManager::GetSingleton().MovingWidget( this ); return true; } } else if (button == csmbRight) { if ((contextMenu == NULL) && (contextMenuFile != "")) { CreateContextMenu(); } else if ((contextMenuFile=="") && (configurable)) { CreateWidgetConfigWindow(); } } } if ( parent ) return parent->OnMouseDown( button, modifiers, x, y ); return false; } bool pawsWidget::OnMenuAction ( pawsWidget * widget, const pawsMenuAction & action ) { if (action.name == MENU_DESTROY_ACTION_NAME) { PawsManager::GetSingleton().GetMainWidget()->DeleteChild(widget); if (widget == contextMenu) contextMenu = NULL; return true; } if (action.name=="configure") CreateWidgetConfigWindow(); return false; } csRect pawsWidget::ScreenFrame() { return screenFrame; } bool pawsWidget::OnMouseUp( int button, int modifiers, int x, int y ) { if ( parent ) return parent->OnMouseUp( button, modifiers, x, y ); else return false; } bool pawsWidget::OnDoubleClick( int button, int modifiers, int x, int y ) { if ( parent ) { return parent->OnDoubleClick( button, modifiers, x, y ); } else { return false; } } bool pawsWidget::OnKeyDown( int keyCode, int key, int modifiers ) { if (keyCode == CSKEY_ENTER) { if (!onEnter && parent) return parent->OnKeyDown(keyCode,key,modifiers); onEnter->OnMouseDown(1,0,0,0) ; return true; } bool tab = false; bool forward = true; if (keyCode==CSKEY_TAB && modifiers == 1) { tab = true; forward = false; } else if (keyCode==CSKEY_TAB) { tab = true; forward = true; } if (tab && taborder.Length() > 0) { int z; for (z = 0; z < (int)taborder.Length(); z++ ) { if (taborder[z]->HasFocus()) { break; } } while(true) { // take proper action if (forward) if (z + 1 < (int)taborder.Length()) z++; else z = 0; else if (z - 1 >= 0) z--; else z = (int)taborder.Length() - 1; // if this is a vaild widget to focus on, break the loop if (taborder[z]->OnGainFocus(false)) break; } // Set current focued widget PawsManager::GetSingleton().SetCurrentFocusedWidget(taborder[z]); } if (keyCode < 255 && keyCode > 31) { for (size_t i=0; iCheckKeyHandled(toupper(keyCode)); if (testKey) return true; } } if ( parent ) return parent->OnKeyDown( keyCode, key, modifiers ); return false; } void pawsWidget::MoveDelta( int deltaX, int deltaY ) { //snap to edge of screen if (movable) //avoid moving internal elements { const int SNAP_RANGE = 3; int screenWidth = graphics2D->GetWidth(); int screenHeight = graphics2D->GetHeight(); int titleHeight; if (border && border->GetTitle()) titleHeight = 20; else titleHeight = 0; if (abs(screenFrame.xmin + deltaX) < SNAP_RANGE) deltaX = 0 - screenFrame.xmin; else if (abs(screenFrame.xmax + deltaX - screenWidth) < SNAP_RANGE) deltaX = screenWidth - screenFrame.xmax; if (abs(screenFrame.ymin + deltaY - titleHeight) < SNAP_RANGE) deltaY = 0 + titleHeight - screenFrame.ymin; else if (abs(screenFrame.ymax + deltaY - screenHeight) < SNAP_RANGE) deltaY = screenHeight - screenFrame.ymax; } screenFrame.xmin += deltaX; screenFrame.ymin += deltaY; screenFrame.xmax += deltaX; screenFrame.ymax += deltaY; for ( size_t x = children.Length(); x-- > 0; ) { children[x]->MoveDelta( deltaX, deltaY ); } } void pawsWidget::MoveTo( int x, int y ) { int deltaX = x - screenFrame.xmin; int deltaY = y - screenFrame.ymin; int width = screenFrame.Width(); int height = screenFrame.Height(); screenFrame.xmin = x; screenFrame.ymin = y; screenFrame.SetSize( width, height ); for ( size_t z = children.Length(); z-- > 0; ) { children[z]->MoveDelta(deltaX, deltaY ); } for ( size_t z = 0; z < children.Length(); z++ ) { children[z]->RecalcScreenPositions(); } } void pawsWidget::CenterTo( int x, int y ) { MoveTo(x - screenFrame.Width()/2, y - screenFrame.Height()/2); } void pawsWidget::CenterToMouse() { psPoint mouse; mouse = PawsManager::GetSingleton().GetMouse()->GetPosition(); CenterTo(mouse.x, mouse.y); MakeFullyVisible(); } csRect pawsWidget::LoadPositions() { csRef cfgMgr; cfgMgr = CS_QUERY_REGISTRY( PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager ); char buffer[512]; csRef config = cfgMgr->LookupDomain(PawsManager::GetSingleton().GetConfigFile()); sprintf(buffer, "PlaneShift.GUI.%s.Visible", GetName() ); SetVisibility(config->GetBool (buffer, visible )); sprintf(buffer, "PlaneShift.GUI.%s.PosX", GetName() ); int winPosX = config->GetInt (buffer, defaultFrame.xmin ); sprintf(buffer, "PlaneShift.GUI.%s.PosY", GetName() ); int winPosY = config->GetInt (buffer, defaultFrame.ymin ); winPosX = GetActualWidth( winPosX ); winPosY = GetActualHeight( winPosY ); int screenWidth = graphics2D->GetWidth(); int screenHeight = graphics2D->GetHeight(); int winWidth = 0; int winHeight = 0; //don't do this if widget is not resizable if ( IsResizable() ) { sprintf(buffer, "PlaneShift.GUI.%s.Width", GetName() ); winWidth = config->GetInt (buffer, defaultFrame.Width() ); sprintf(buffer, "PlaneShift.GUI.%s.Height", GetName() ); winHeight = config->GetInt (buffer, defaultFrame.Height() ); if (resizeToScreen) { float ratio = ((float) winHeight) / ((float) winWidth); if (winWidth > 800) { winWidth = 800; if (ratio > 1.0f) ratio = 1.0f; winHeight = int (800.0f * ratio); } else if (winHeight > 600) { winHeight = 600; if (ratio > 1.0f) ratio = 1.0f; winWidth = int (600.0f / ratio); } winWidth = GetActualWidth( winWidth ); winHeight = GetActualHeight( winHeight ); } if ( winWidth < min_width ) winWidth = min_width; if ( winHeight < min_height ) winHeight = min_height; } if ( winPosX < 0 ) winPosX = 0; if ( winPosY < 0 ) winPosY = 0; if ( winPosX + winWidth > screenWidth ) winPosX = screenWidth - winWidth; if ( winPosY + winHeight > screenHeight ) winPosY = screenHeight - winHeight; csRect newPosition = csRect(winPosX,winPosY, winPosX+winWidth, winPosY+winHeight); return newPosition; } void pawsWidget::PerformAction( const char* action ) { csString temp(action); if ( temp == "togglevisibility" ) { if ( IsVisible() ) { Hide(); } else { Show(); } return; } } void pawsWidget::SavePosition() { csRef cfgMgr; cfgMgr = CS_QUERY_REGISTRY( PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager ); csRef config = cfgMgr->LookupDomain(PawsManager::GetSingleton().GetConfigFile()); char buffer[512]; int desktopWidth = graphics2D->GetWidth(); int desktopHeight = graphics2D->GetHeight(); float ratioX = (float) 800.0f / (float)desktopWidth; float ratioY = (float) 600.0f / (float)desktopHeight; if (!resizeToScreen) ratioX = ratioY = 1; sprintf(buffer, "PlaneShift.GUI.%s.Visible", GetName() ); config->SetBool( buffer, visible ); sprintf(buffer, "PlaneShift.GUI.%s.PosX", GetName() ); config->SetInt( buffer, RX(screenFrame.xmin) ); sprintf(buffer, "PlaneShift.GUI.%s.PosY", GetName() ); config->SetInt( buffer, RY(screenFrame.ymin) ); if ( IsResizable() ) { sprintf(buffer, "PlaneShift.GUI.%s.Width", GetName() ); config->SetInt( buffer, RX(screenFrame.Width()) ); sprintf(buffer, "PlaneShift.GUI.%s.Height", GetName() ); config->SetInt( buffer, RY(screenFrame.Height()) ); } config->Save(); } void pawsWidget::SetForceSize( int newWidth, int newHeight ) { screenFrame.SetSize( newWidth, newHeight ); OnResize(); } void pawsWidget::SetSize( int newWidth, int newHeight ) { SetForceSize(newWidth,newHeight); for ( size_t x = children.Length(); x-- > 0; ) { children[x]->Resize(); } } void pawsWidget::StopResize() { for ( size_t x = 0; x < children.Length(); x++ ) { children[x]->StopResize(); } } void pawsWidget::Resize( int deltaX, int deltaY, int flags ) { csRect newFrame = screenFrame; if ( flags & RESIZE_LEFT) { newFrame.xmin += deltaX; } if ( flags & RESIZE_RIGHT ) { newFrame.xmax += deltaX; } if ( flags & RESIZE_TOP ) { newFrame.ymin += deltaY; } if ( flags & RESIZE_BOTTOM ) { newFrame.ymax += deltaY; } /// prevent the widget from going below its min height and width if (newFrame.xmax - newFrame.xmin < min_width) newFrame.xmax = newFrame.xmin + min_width; if (newFrame.ymax - newFrame.ymin < min_height) newFrame.ymax = newFrame.ymin + min_height; /// prevent the widget from going beyond its max size if (newFrame.xmax - newFrame.xmin > max_width) newFrame.xmax = max_width + newFrame.xmin; if (newFrame.ymax - newFrame.ymin > max_height) newFrame.ymax = max_height + newFrame.ymin; screenFrame = newFrame; OnResize(); for ( size_t x = children.Length(); x-- > 0; ) { children[x]->Resize(); } } void pawsWidget::Resize() { if ( attachFlags & ATTACH_LEFT ) { int width = screenFrame.Width(); screenFrame.xmin = parent->ScreenFrame().xmin + defaultFrame.xmin; screenFrame.SetSize( width, screenFrame.Height() ); // Left-Right Attachment if ( attachFlags & ATTACH_RIGHT ) { int newX = parent->DefaultFrame().Width() - (defaultFrame.xmin + defaultFrame.Width()); screenFrame.xmax = parent->ScreenFrame().xmax - newX; } // Left-Right Proportional Attachment if ( attachFlags & PROPORTIONAL_RIGHT ) { int z = (parent->ScreenFrame().Width() * ( parent->DefaultFrame().Width() - defaultFrame.xmax ) ) / parent->DefaultFrame().Width(); int newMax = parent->ScreenFrame().xmax - z; screenFrame.xmax = newMax; } } if ( attachFlags & ATTACH_RIGHT ) { //Attach Right Only if ( !(attachFlags & ATTACH_LEFT) ) { int width = screenFrame.Width(); screenFrame.xmin = parent->ScreenFrame().xmax - ( parent->DefaultFrame().Width() - defaultFrame.xmax + width ); screenFrame.SetSize( width, screenFrame.Height() ); } //Attach Right-Left Proportional if ( attachFlags & PROPORTIONAL_LEFT ) { int z = (parent->ScreenFrame().Width() * defaultFrame.xmin ) / parent->DefaultFrame().Width(); int newMin = parent->ScreenFrame().xmin + z; screenFrame.xmin = newMin; } } if ( attachFlags & PROPORTIONAL_LEFT ) { //Attach Proportional Left Only if ( ! (attachFlags & ATTACH_RIGHT) && !(attachFlags & PROPORTIONAL_RIGHT) ) { int z = (parent->ScreenFrame().Width() * defaultFrame.xmin ) / parent->DefaultFrame().Width(); int newMin = parent->ScreenFrame().xmin + z; int width = screenFrame.Width(); screenFrame.xmin = newMin; screenFrame.SetSize( width, screenFrame.Height() ); } } if ( attachFlags & PROPORTIONAL_RIGHT ) { //Attach Proportional RIGHT Only if ( ! (attachFlags & ATTACH_LEFT) && !(attachFlags & PROPORTIONAL_LEFT) ) { int z = (parent->ScreenFrame().Width() * ( parent->DefaultFrame().Width() - defaultFrame.xmax ) ) / parent->DefaultFrame().Width(); int newMin = parent->ScreenFrame().xmax - z - defaultFrame.Width(); int width = screenFrame.Width(); screenFrame.xmin = newMin; screenFrame.SetSize( width, screenFrame.Height() ); } //Attach PropLeft-PropRight if ( attachFlags & PROPORTIONAL_LEFT ) { int z = (parent->ScreenFrame().Width() * ( parent->DefaultFrame().Width() - defaultFrame.xmax ) ) / parent->DefaultFrame().Width(); int newMax = parent->ScreenFrame().xmax - z; screenFrame.xmax = newMax; z = (parent->ScreenFrame().Width() * defaultFrame.xmin ) / parent->DefaultFrame().Width(); int newMin = parent->ScreenFrame().xmin + z; screenFrame.xmin = newMin; } } if ( attachFlags & ATTACH_TOP ) { int height = defaultFrame.Height(); screenFrame.ymin = parent->ScreenFrame().ymin + defaultFrame.ymin; screenFrame.SetSize( screenFrame.Width(), height ); //Attach TOP-BOTTOM if ( attachFlags & ATTACH_BOTTOM ) { int newY = parent->DefaultFrame().Height() - (defaultFrame.ymin + defaultFrame.Height()); screenFrame.ymax = parent->ScreenFrame().ymax - newY; } //Attach TOP-BOTTOM Proportional if ( attachFlags & PROPORTIONAL_BOTTOM ) { int z = (parent->ScreenFrame().Height() * ( parent->DefaultFrame().Height() - defaultFrame.ymax ) ) / parent->DefaultFrame().Height(); int newMax = parent->ScreenFrame().ymax - z; screenFrame.ymax = newMax; } } if ( attachFlags & ATTACH_BOTTOM ) { // Attach BOTTOM Only if ( !(attachFlags & ATTACH_TOP) ) { int height = screenFrame.Height(); screenFrame.ymin = parent->ScreenFrame().ymax - ( parent->DefaultFrame().Height() - defaultFrame.ymax + height ); screenFrame.SetSize( screenFrame.Width(), height ); } //Attach BOTTOM-TOP Proportional if ( attachFlags & PROPORTIONAL_TOP ) { int z = (parent->ScreenFrame().Height() * defaultFrame.ymin ) / parent->DefaultFrame().Height(); int newMin = parent->ScreenFrame().ymin + z; screenFrame.ymin = newMin; } } // Attach Proportional TOP Only if ( attachFlags & PROPORTIONAL_TOP ) { if ( ! (attachFlags & ATTACH_BOTTOM) && !(attachFlags & PROPORTIONAL_BOTTOM) ) { int z = (parent->ScreenFrame().Height() * defaultFrame.ymin ) / parent->DefaultFrame().Height(); int newMin = parent->ScreenFrame().ymin + z; int height = screenFrame.Height(); screenFrame.ymin = newMin; screenFrame.SetSize( screenFrame.Width(), height ); } } if ( attachFlags & PROPORTIONAL_BOTTOM ) { // Attach Proportional BOTTOM Only if ( ! (attachFlags & ATTACH_TOP) && !(attachFlags & PROPORTIONAL_TOP) ) { int z = (parent->ScreenFrame().Height() * ( parent->DefaultFrame().Height() - defaultFrame.ymax ) ) / parent->DefaultFrame().Height(); int newMin = parent->ScreenFrame().ymax - z - defaultFrame.Height(); int height = screenFrame.Height(); screenFrame.ymin = newMin; screenFrame.SetSize( screenFrame.Width(), height ); } // Attach PropTOP-PropBOTTOM if ( attachFlags & PROPORTIONAL_TOP ) { int z = (parent->ScreenFrame().Height() * ( parent->DefaultFrame().Height() - defaultFrame.ymax ) ) / parent->DefaultFrame().Height(); int newMax = parent->ScreenFrame().ymax - z; screenFrame.ymax = newMax; z = (parent->ScreenFrame().Height() * defaultFrame.ymin ) / parent->DefaultFrame().Height(); int newMin = parent->ScreenFrame().ymin + z; screenFrame.ymin = newMin; } } OnResize(); for ( size_t x = children.Length(); x-- > 0; ) { children[x]->Resize(); } } void pawsWidget::OnResize() { SetCloseButtonPos(); } void pawsWidget::SetModalState( bool isModal ) { if ( isModal ) PawsManager::GetSingleton().SetModalWidget( this ); else PawsManager::GetSingleton().SetModalWidget( 0 ); } int pawsWidget::GetAttachFlag( const char* flag ) { csString str( flag ); if ( str == "ATTACH_RIGHT" ) return ATTACH_RIGHT; if ( str == "ATTACH_LEFT" ) return ATTACH_LEFT; if ( str == "ATTACH_BOTTOM" ) return ATTACH_BOTTOM; if ( str == "ATTACH_TOP" ) return ATTACH_TOP; if ( str == "PROPORTIONAL_LEFT" ) return PROPORTIONAL_LEFT; if ( str == "PROPORTIONAL_RIGHT" ) return PROPORTIONAL_RIGHT; if ( str == "PROPORTIONAL_TOP" ) return PROPORTIONAL_TOP; if ( str == "PROPORTIONAL_BOTTOM" ) return PROPORTIONAL_BOTTOM; return 0; } void pawsWidget::MouseOver(bool value) { hasMouseFocus = value; } //csRef ParseFile(iObjectRegistry* object_reg, const csString & name); bool pawsWidget::LoadFromFile(const csString & fileName) { csRef doc; csRef root, topNode, widgetNode; doc = ParseFile(PawsManager::GetSingleton().GetObjectRegistry(), PawsManager::GetSingleton().GetLocalization()->FindLocalizedFile(fileName)); if (doc == NULL) return false; root = doc->GetRoot(); if (root == NULL) { Error1("No root in XML"); return false; } topNode = root->GetNode("widget_description"); if (topNode == NULL) { Error1("No in XML"); return false; } widgetNode = topNode->GetNode("widget"); if (widgetNode == NULL) { Error1("No in "); return false; } if ( ! Load(widgetNode) ) return false; return true; } void pawsWidget::MakeFullyVisible() { csRect parentFrame; int targetX, targetY; if (parent == NULL) return; parentFrame = parent->ScreenFrame(); if (screenFrame.xmin < parentFrame.xmin) targetX = parentFrame.xmin; else if (screenFrame.xmax > parentFrame.xmax) targetX = parentFrame.xmax - screenFrame.Width() + 1; else targetX = screenFrame.xmin; if (screenFrame.ymin < parentFrame.ymin) targetY = parentFrame.ymin; else if (screenFrame.ymax > parentFrame.ymax) targetY = parentFrame.ymax - screenFrame.Height() + 1; else targetY = screenFrame.ymin; if ((targetX != screenFrame.xmin) || (targetY != screenFrame.ymin)) MoveTo(targetX, targetY); } void pawsWidget::ClipToParent() { if ( !parent ) { // If we have no parent widget, then we are top level and clip only to the 2D canvas region graphics2D->SetClipRect( 0,0, graphics2D->GetWidth(), graphics2D->GetHeight()); clipRect = csRect(0,0, graphics2D->GetWidth(), graphics2D->GetHeight()); } else { // Otherwise we should clip to the overlap of our parent frame and either our frame or our border frame // If we have a border, start with that, otherwise use our widget frame if ( border && border->GetTitleImage()) clipRect = border->GetRect(); else clipRect = screenFrame; // Calculate intersection of our frame and parent frame clipRect.Intersect(parent->ClipRect()); // If we wont be drawing anyway, don't bother making a graphics call to adjust clipping if (clipRect.IsEmpty()) return; // Adjust the canvas clipping for future draw calls to clip to our allowed area graphics2D->SetClipRect( ClipRect().xmin, ClipRect().ymin, ClipRect().xmax, ClipRect().ymax ); } } void pawsWidget::LoadBorderColours( iDocumentNode* node ) { csRef iter = node->GetNodes(); int index = 0; while ( index < 5 && iter->HasNext() ) { csRef colour = iter->Next(); int r = colour->GetAttributeValueAsInt( "r" ); int g = colour->GetAttributeValueAsInt( "g" ); int b = colour->GetAttributeValueAsInt( "b" ); int col = graphics2D->FindRGB( r, g, b ); borderColours[index++] = col; } hasBorderColours = true; } int pawsWidget::GetBorderColour(int which) { if (hasBorderColours) return borderColours[which]; else if (parent) return parent->GetBorderColour(which); else return PawsManager::GetSingleton().GetPrefs()->GetBorderColour(which); } void pawsWidget::SetFont( const char* Name , int Size) { if (Name) { fontSize = Size; if (resizeToScreen) fontSize *= PawsManager::GetSingleton().GetFontFactor(); if (fontScaling) fontSize *= ((float)fontScaling / 100.0f); fontName = Name; myFont = graphics2D->GetFontServer()->LoadFont( Name, fontSize ); } else { myFont = NULL; } } void pawsWidget::SetColour( int newColour ) { if ( newColour != -1 ) { defaultFontColour = newColour; } else { defaultFontColour = PawsManager::GetSingleton().GetPrefs()->GetDefaultFontColour(); } } void pawsWidget::ChangeFontSize(int newSize) { if (newSize == fontSize) return; fontSize = newSize; if (resizeToScreen) fontSize *= PawsManager::GetSingleton().GetFontFactor(); if (fontScaling) fontSize *= ((float)fontScaling / 100.0f); if (fontName.IsEmpty()) fontName = PawsManager::GetSingleton().GetPrefs()->GetDefaultFontName(); myFont = graphics2D->GetFontServer()->LoadFont( fontName, fontSize ); } void pawsWidget::SetFontScaling(int newFontScaling) { if (newFontScaling == fontScaling) return; fontSize *= float(newFontScaling) / float(fontScaling); fontScaling = newFontScaling; if (fontName.IsEmpty()) fontName = PawsManager::GetSingleton().GetPrefs()->GetDefaultFontName(); myFont = graphics2D->GetFontServer()->LoadFont( fontName, fontSize ); } iFont *pawsWidget::GetFont( bool scaled ) { csRef font; if (myFont) font = myFont; else if (parent) font = parent->GetFont( scaled ); else font = PawsManager::GetSingleton().GetPrefs()->GetDefaultFont( scaled ); return font; } int pawsWidget::GetFontColour() { if (defaultFontColour != -1) return defaultFontColour; else if (parent) return parent->GetFontColour(); else return PawsManager::GetSingleton().GetPrefs()->GetDefaultFontColour(); } int pawsWidget::GetFontShadowColour() { if (myFont) return defaultFontShadowColour; else if (parent) return parent->GetFontShadowColour(); else return graphics2D->FindRGB(0,0,0); } float pawsWidget::GetFontSize() { if (myFont) return fontSize; else if (parent) return parent->GetFontSize(); else return DEFAULT_FONT_SIZE; } int pawsWidget::GetFontStyle() { if (myFont) return fontStyle; else if (parent) return parent->GetFontStyle(); else return DFFAULT_FONT_STYLE; } bool pawsWidget::SelfPopulateXML( const char *xmlstr ) { csRef xml = csPtr(new csTinyDocumentSystem); csRef doc= xml->CreateDocument(); const char *error = doc->Parse( xmlstr ); if (error) { Error1(error); return false; } csRef root = doc->GetRoot(); if(!root) { Error2("Missing root in %s", xmlstr); return false; } csRef topNode = root->GetNode(xmlbinding!=""?xmlbinding:name); if (topNode) { return SelfPopulate(topNode); } else { Error3("SelfPopulate failed because tag <%s> could not be found in xmlstr '%s'.\n",name.GetData(),xmlstr); return false; } } bool pawsWidget::SelfPopulate( iDocumentNode *node) { // No self population here since generic widgets have no data // Now generically check to populate children if any are here if (!children.Length()) return true; csRef iter = node->GetNodes(); while ( iter->HasNext() ) { csRef node = iter->Next(); if ( node->GetType() != CS_NODE_ELEMENT ) continue; pawsWidget *nodewidget = FindWidgetXMLBinding(node->GetValue()); if (nodewidget) { if (!nodewidget->SelfPopulate(node)) return false; } else Warning2( LOG_PAWS, "Could not locate widget with XML binding %s", node->GetValue() ); } return true; } bool pawsWidget::OnChange(pawsWidget * widget) { if (parent != NULL) return parent->OnChange(widget); else return false; } void pawsWidget::Dump(csString tab) { printf("%s\n",tab.GetData(),name.GetData()); for ( size_t x = 0; x < children.Length(); x++ ) { children[x]->Dump(tab+"\t"); } printf("%s\n",tab.GetData()); } //------------------------------------------------------------------------ void pawsWidgetFactory::Register( const char* name ) { factoryName = name; PawsManager::GetSingleton().RegisterWidgetFactory( this ); } pawsWidget* pawsWidgetFactory::Create() { return NULL; } void pawsWidget::SetCloseButtonPos() { pawsButton * button = dynamic_cast (FindWidget(GetCloseName(), false)); if (button != NULL) button->SetRelativeFrame( defaultFrame.Width() - 20, - 18, 16, 16 ); } void pawsWidget::RemoveTitle() { if(border) border->SetTitle(NULL); border->SetTitleImage(NULL); if(close_widget) close_widget->DeleteYourself(); } bool pawsWidget::SetTitle( const char* text, const char* image, const char* align, const char* close_button ) { if ( !border ) { return false; } else { border->SetTitle( text ); psImageDescription* imageDesc = PawsManager::GetSingleton().GetTextureManager()->GetImageDescription( image ); pawsImage *titleImage = new pawsImage( PawsManager::GetSingleton().GetObjectRegistry() ); titleImage->Description( imageDesc ); border->SetTitleImage(titleImage); int alignValue = ALIGN_LEFT; if (align) { if (!strcmp(align,"center")) alignValue = ALIGN_CENTER; else if (!strcmp(align,"right")) alignValue = ALIGN_RIGHT; } border->SetTitleAlign(alignValue); if ( close_button && (strcmp(close_button,"yes") == 0) ) { close_widget = (pawsButton*)PawsManager::GetSingleton().CreateWidget("pawsButton"); close_widget->SetParent( this ); close_widget->SetBackground( "quit" ); csString name( GetName() ); name.Append( "_close" ); close_widget->SetName( name ); int flags = ATTACH_TOP | ATTACH_RIGHT; close_widget->SetAttachFlags( flags ); AddChild( close_widget ); SetCloseButtonPos(); close_widget->SetSound("gui.cancel"); } } return true; } csString pawsWidget::GetPathInWidgetTree() { csString path, widget; widget = "n="; widget += name; widget +=" f="; widget += factory; if (parent != NULL) { csString path; path = parent->GetPathInWidgetTree(); path += " ---> "; path += widget; return path; } else return widget; } void pawsWidget::SetMaskingImage(const char* image) { if (maskImage) delete maskImage; maskImage = new pawsImage( PawsManager::GetSingleton().GetObjectRegistry() ); psImageDescription* imageDesc = PawsManager::GetSingleton().GetTextureManager()->GetImageDescription( image ); if ( !imageDesc ) { Warning3( LOG_PAWS, "Could not locate masking image %s for widget %s",image,GetName()); } else maskImage->Description(imageDesc); } void pawsWidget::ClearMaskingImage() { if (maskImage) delete maskImage; maskImage = NULL; } void pawsWidget::SetBackgroundColor(int r,int g, int b) { bgColour = graphics2D->FindRGB(r,g,b); }