/* * pawstree.cpp - Author: Ondrej Hurt * * 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. * */ // CS INCLUDES #include #include #include // COMMON INCLUDES #include "util/log.h" // PAWS INCLUDES #include "pawsborder.h" #include "pawstree.h" #include "pawsmanager.h" #define SCROLLBAR_WIDTH 15 //////////////////////////////////////////////////////////// // this should be in some library //////////////////////////////////////////////////////////// // converts one hexadecimal digit to decimal value int HexToDec4(char digit) { if ((digit >= '0') && (digit <= '9')) return digit - '0'; else if ((digit >= 'A') && (digit <= 'Z')) return digit - 'A' + 10; else if ((digit >= 'a') && (digit <= 'z')) return digit - 'a' + 10; else return 0; } // converts two hexadecimal digits to decimal value int HexToDec8(char first, char second) { return (HexToDec4(first) << 4) + HexToDec4(second); } int MakeColor(const csPixelFormat * fmt, int r, int g, int b) { if (!fmt->PalEntries) return ((r >> (8 - fmt->RedBits)) << fmt->RedShift) | ((g >> (8 - fmt->GreenBits)) << fmt->GreenShift) | ((b >> (8 - fmt->BlueBits)) << fmt->BlueShift); // In paletted mode this is easy since we have a uniform 3-3-2 palette return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6); } // converts hexadecimal string to color in current pixel format int ParseColor(const csString & str, iGraphics2D *g2d) { int r, g, b; if (str.Length() != 6) return false; r = HexToDec8(str.GetAt(0), str.GetAt(1)); g = HexToDec8(str.GetAt(2), str.GetAt(3)); b = HexToDec8(str.GetAt(4), str.GetAt(5)); return MakeColor(g2d->GetPixelFormat(), r, g, b); } //////////////////////////////////////////////////////////// // // pawsTreeNode // //////////////////////////////////////////////////////////// pawsTreeNode::pawsTreeNode() { tree = NULL; parent = NULL; firstChild = NULL; prevSibling = NULL; nextSibling = NULL; collapsable = true; collapsed = false; } pawsTreeNode::~pawsTreeNode() { Clear(); } void pawsTreeNode::SetTree(pawsITreeStruct * _tree) { tree = _tree; } csString pawsTreeNode::GetAttr(const csString & name) { for ( size_t x = 0; x < attrList.Length(); x++ ) { if (attrList[x].name == name) return attrList[x].value; } return ""; } void pawsTreeNode::SetAttr(const csString & name, const csString & value) { TreeNodeAttribute attr; attr.name = name; attr.value = value; attrList.Push(attr); if (tree != NULL) tree->NodeChanged(); } pawsTreeNode * pawsTreeNode::GetParent() { return parent; } void pawsTreeNode::SetParent(pawsTreeNode * _parent) { parent = _parent; } pawsTreeNode * pawsTreeNode::GetFirstChild() { return firstChild; } pawsTreeNode * pawsTreeNode::FindNodeByPath(const csString & path) { //not implemented yet return NULL; } pawsTreeNode * pawsTreeNode::FindChildByName(const csString & name, bool indirectToo) { pawsTreeNode * child, * foundIndirect; child = firstChild; while (child != NULL) { if (name == child->name) return child; if (indirectToo) { foundIndirect = child->FindChildByName(name, true); if (foundIndirect != NULL) return foundIndirect; } child = child->GetNextSibling(); } return NULL; } pawsTreeNode * pawsTreeNode::GetPrevSibling() { return prevSibling; } pawsTreeNode * pawsTreeNode::GetNextSibling() { return nextSibling; } void pawsTreeNode::SetPrevSibling(pawsTreeNode *node) { prevSibling = node; } void pawsTreeNode::SetNextSibling(pawsTreeNode *node) { nextSibling = node; } pawsTreeNode * pawsTreeNode::FindLastChild() { return firstChild->FindLastSibling(); } void pawsTreeNode::InsertChild(pawsTreeNode * node, pawsTreeNode * nextSibling) { pawsTreeNode * prevSibling; if (nextSibling != NULL) prevSibling = nextSibling->GetPrevSibling(); else prevSibling = FindLastChild(); node->SetNextSibling(nextSibling); node->SetPrevSibling(prevSibling); if (nextSibling != NULL) nextSibling->SetPrevSibling(node); if (prevSibling != NULL) prevSibling->SetNextSibling(node); else firstChild = node; node->SetParent(this); node->SetTree(tree); tree->NewNode(node); if (tree != NULL) tree->NodeChanged(); } void pawsTreeNode::MoveChild(pawsTreeNode * node, pawsTreeNode * nextSibling) { RemoveChild(node); InsertChild(node, nextSibling); if (tree != NULL) tree->NodeChanged(); } void pawsTreeNode::RemoveChild(pawsTreeNode * node) { pawsTreeNode * prev = node->GetPrevSibling(), * next = node->GetNextSibling(); if (prev != NULL) prev->SetNextSibling(next); else firstChild = next; if (next != NULL) next->SetPrevSibling(prev); if (tree != NULL) tree->RemoveNode(node); } void pawsTreeNode::DeleteChild(pawsTreeNode * node) { RemoveChild(node); delete node; } void pawsTreeNode::Clear() { while (firstChild != NULL) DeleteChild(firstChild); } void pawsTreeNode::SetCollapsable(bool _collapsable) { collapsable = _collapsable; if (!collapsable && collapsed) Expand(); } void pawsTreeNode::Expand() { collapsed = false; SetChildrenVisibAfterCollapseChange(true); if (tree != NULL) tree->NodeChanged(); } void pawsTreeNode::ExpandAll() { pawsTreeNode * child; Expand(); child = firstChild; while (child != NULL) { child->ExpandAll(); child = child->GetNextSibling(); } } void pawsTreeNode::Collapse() { collapsed = true; SetChildrenVisibAfterCollapseChange(false); if (tree != NULL) tree->NodeChanged(); } void pawsTreeNode::CollapseAll() { pawsTreeNode * child; Collapse(); child = firstChild; while (child != NULL) { child->CollapseAll(); child = child->GetNextSibling(); } } bool pawsTreeNode::IsCollapsed() { return collapsed; } bool pawsTreeNode::BuriedInRuins() { if (parent == NULL) return false; return parent->IsCollapsed() || parent->BuriedInRuins(); } void pawsTreeNode::SetChildrenVisibAfterCollapseChange(bool expanded) { pawsTreeNode * child; child = firstChild; while (child != NULL) { if (expanded) { child->Show(); } else { child->Hide(); } if ( ! child->IsCollapsed() ) child->SetChildrenVisibAfterCollapseChange(expanded); child = child->GetNextSibling(); } } int pawsTreeNode::GetRowNum() { if (prevSibling != NULL) return prevSibling->FindLowestSubtreeNode()->GetRowNum() + 1; else if (parent != NULL) return parent->GetRowNum() + 1; else return 0; } pawsTreeNode * pawsTreeNode::FindLastSibling() { pawsTreeNode *sibling; sibling = this; while ((sibling != NULL) && (sibling->GetNextSibling() != NULL)) sibling = sibling->GetNextSibling(); return sibling; } pawsTreeNode * pawsTreeNode::FindLowestSubtreeNode() { pawsTreeNode * lastChild; lastChild = FindLastChild(); if (lastChild == NULL) return this; else return lastChild->FindLowestSubtreeNode(); } pawsTreeNode * pawsTreeNode::FindNodeAbove() { if (prevSibling != NULL) return prevSibling->FindLowestSubtreeNode(); else return parent; } pawsTreeNode * pawsTreeNode::FindNodeBelow() { pawsTreeNode * node; if (firstChild != NULL) return firstChild; else if (nextSibling != NULL) return nextSibling; else { node = parent; while ((node != NULL) && (node->GetNextSibling() == NULL)) node = node->GetParent(); if (node != NULL) return node->GetNextSibling(); else return NULL; } } bool pawsTreeNode::Load(iDocumentNode *node) { csRef xmlChildren, xmlAttrList; csRef xmlChild, xmlAttr; csString factory; pawsWidget *childAsWidget; pawsTreeNode *childNode; Clear(); name = node->GetAttributeValue("name"); xmlChildren = node->GetNodes("widget"); while (xmlChildren->HasNext()) { xmlChild = xmlChildren->Next(); factory = xmlChild->GetAttributeValue( "factory" ); childAsWidget = PawsManager::GetSingleton().CreateWidget( factory ); if ( !childAsWidget ) { Error2("Could not create node from factory: %s", factory.GetData()); return false; } childNode = dynamic_cast(childAsWidget); if (childNode == NULL) { Error1("Created node is not pawsTreeNode"); return false; } InsertChild(childNode); if (!childNode->Load(xmlChild)) { Error1("Node failed to load"); return false; } } attrList.DeleteAll(); xmlAttrList = node->GetNodes("attr"); while (xmlAttrList->HasNext()) { xmlAttr = xmlAttrList->Next(); SetAttr(xmlAttr->GetAttributeValue("name"), xmlAttr->GetAttributeValue("value")); } if (tree != NULL) tree->NodeChanged(); csString collapsed = node->GetAttributeValue("collapsed"); if (collapsed == "yes") CollapseAll(); return true; } ////////////////////////////////////////////////////////////////////// // // pawsTreeStruct // ////////////////////////////////////////////////////////////////////// pawsTreeStruct::pawsTreeStruct() { root = NULL; version = 0; } pawsTreeStruct::~pawsTreeStruct() { if (root != NULL) delete root; } void pawsTreeStruct::NodeChanged() { version++; } void pawsTreeStruct::SetRoot(pawsTreeNode * _root) { if (root != NULL) delete root; root = _root; } pawsTreeNode * pawsTreeStruct::FindNodeByName(const csString & name) { if (root != NULL) return root->FindChildByName(name, true); else return NULL; } void pawsTreeStruct::InsertChild(pawsTreeNode * parent, pawsTreeNode * node, pawsTreeNode * nextSibling) { parent->InsertChild(node, nextSibling); } void pawsTreeStruct::MoveChild(pawsTreeNode * node, pawsTreeNode * nextSibling) { pawsTreeNode * parent; parent = node->GetParent(); if (parent != NULL) parent->MoveChild(node, nextSibling); } void pawsTreeStruct::RemoveChild(pawsTreeNode * node) { pawsTreeNode * parent; parent = node->GetParent(); if (parent != NULL) parent->RemoveChild(node); } void pawsTreeStruct::DeleteChild(pawsTreeNode * node) { pawsTreeNode * parent; parent = node->GetParent(); if (parent != NULL) parent->DeleteChild(node); } void pawsTreeStruct::Clear() { if (root != NULL) root->Clear(); } void pawsTreeStruct::InsertChild(const csString & parent, pawsTreeNode * node, const csString & nextSibling) { pawsTreeNode * parentNode, * nextSiblingNode; parentNode = FindNodeByName(parent); // Allows a root to be added automatically. if (parentNode == NULL) if (!root) { SetRoot(node); node->SetTree(this); return; } else parentNode = root; nextSiblingNode = FindNodeByName(nextSibling); parentNode->InsertChild(node, nextSiblingNode); } void pawsTreeStruct::InsertChild(const csString & parent, pawsTreeNode * node) { pawsTreeNode * parentNode; parentNode = FindNodeByName(parent); if (parentNode == NULL) return; parentNode->InsertChild(node, NULL); } void pawsTreeStruct::MoveChild(const csString & name, const csString & nextSibling) { pawsTreeNode * node, * parentNode, * nextSiblingNode; node = FindNodeByName(name); if (node == NULL) return; nextSiblingNode = FindNodeByName(nextSibling); if (nextSiblingNode == NULL) return; parentNode = node->GetParent(); if (parentNode != NULL) parentNode->MoveChild(node, nextSiblingNode); } void pawsTreeStruct::DeleteChild(const csString & name) { pawsTreeNode * node, * parentNode; node = FindNodeByName(name); if (node == NULL) return; parentNode = node->GetParent(); if (parentNode != NULL) parentNode->DeleteChild(node); else Clear(); } bool pawsTreeStruct::Load(iDocumentNode *node) { csRef xmlRoot; csString factory; pawsWidget *rootAsWidget; pawsTreeNode *newRoot; version++; xmlRoot = node->GetNode("widget"); if (xmlRoot == NULL) { Error1(" tag not found"); return false; } factory = xmlRoot->GetAttributeValue("factory"); rootAsWidget = PawsManager::GetSingleton().CreateWidget(factory); if (rootAsWidget == NULL) { Error2("Could not create root from factory: %s", factory.GetData()); return false; } newRoot = dynamic_cast(rootAsWidget); if (newRoot == NULL) { Error2("Root(%s) is not pawsTreeNode",rootAsWidget->GetType()); delete rootAsWidget; return false; } SetRoot(newRoot); root->SetTree(this); return root->Load(xmlRoot); } pawsTreeNode * pawsTreeStruct::FindNodeAt(pawsTreeNode *parent, int x, int y) { pawsTreeNode *child, *foundIndirect; csRect frame; if (parent->IsCollapsed()) return false; child = parent->GetFirstChild(); while (child != NULL) { frame = child->ScreenFrame(); if (frame.Contains(x, y)) return child; foundIndirect = FindNodeAt(child, x, y); if (foundIndirect != NULL) return foundIndirect; child = child->GetNextSibling(); } return NULL; } pawsTreeNode * pawsTreeStruct::GetRoot() { return root; } ////////////////////////////////////////////////////////////////////// // // pawsStdTreeLayout // ////////////////////////////////////////////////////////////////////// pawsStdTreeLayout::pawsStdTreeLayout(pawsTree * _tree, int _rowSpacing, int _levelSpacing) { tree = _tree; rowSpacing = _rowSpacing; levelSpacing = _levelSpacing; horizScroll = 0; vertScroll = 0; lastVersion = -1; width = 0; height = 0; } void pawsStdTreeLayout::SetLayout() { pawsTreeNode *root; csRect treeFrame; int treeX, treeY, maxX, maxY; // if the tree hasn't changed, we have nothing to update if (lastVersion == tree->GetVersion()) return; root = tree->GetRoot(); if (root == NULL) return; treeFrame = tree->ScreenFrame(); treeX = treeFrame.xmin - horizScroll; treeY = treeFrame.ymin - vertScroll; maxX = treeX; maxY = treeY; root->SetSize(0, 0); SetSubtreeLayout(root, treeX, treeY, maxX, maxY); width = maxX - treeX + 1; height = maxY - treeY + 1; lastVersion = tree->GetVersion(); } void pawsStdTreeLayout::SetSubtreeLayout(pawsTreeNode * subtreeRoot, int x, int y, int & maxX, int & maxY) { pawsTreeNode *child; csRect frame; subtreeRoot->MoveTo(x, y); frame = subtreeRoot->ScreenFrame(); if (frame.xmax > maxX) maxX = frame.xmax; maxY = frame.ymax; if ( ! subtreeRoot->IsCollapsed() ) { child = subtreeRoot->GetFirstChild(); while (child != NULL) { SetSubtreeLayout(child, x + levelSpacing, maxY + rowSpacing, maxX, maxY); child = child->GetNextSibling(); } } } void pawsStdTreeLayout::SetHorizScroll(int _horizScroll) { horizScroll = _horizScroll; SetLayout(); } void pawsStdTreeLayout::SetVertScroll(int _vertScroll) { vertScroll = _vertScroll; SetLayout(); } void pawsStdTreeLayout::GetTreeSize(int & _width, int & _height) { _width = width; _height = height; } ////////////////////////////////////////////////////////////////////// // // pawsStdTreeDecorator // ////////////////////////////////////////////////////////////////////// pawsStdTreeDecorator::pawsStdTreeDecorator(pawsTree * _tree, iGraphics2D * _g2d, int _selectedColor, int _lineColor, int _collSpacing) { psImageDescription * collDesc, * expandDesc; tree = _tree; g2d = _g2d; selectedColor = _selectedColor; lineColor = _lineColor; collSpacing = _collSpacing; collImage = expandImage = NULL; collDesc = PawsManager::GetSingleton().GetTextureManager()->GetImageDescription("treecollapse"); if (collDesc != NULL) { collImage = new pawsImage( PawsManager::GetSingleton().GetObjectRegistry() ); collImage->Description( collDesc ); } expandDesc = PawsManager::GetSingleton().GetTextureManager()->GetImageDescription("treeexpand"); if (expandDesc != NULL) { expandImage = new pawsImage( PawsManager::GetSingleton().GetObjectRegistry() ); expandImage->Description( expandDesc ); } } pawsStdTreeDecorator::~pawsStdTreeDecorator() { if (collImage != NULL) delete collImage; if (expandImage != NULL) delete expandImage; } void pawsStdTreeDecorator::Decorate() { pawsTreeNode *root; root = tree->GetRoot(); if (root != NULL) DecorateSubtree(root); } void pawsStdTreeDecorator::DecorateSubtree(pawsTreeNode * node) { pawsImage * currImage; pawsTreeNode * child; csRect nodeFrame, childFrame, collSignFrame; int vertLineX, vertLineYMin, vertLineYMax; //coordinates of lines painted between siblings int horizLineXMin, horizLineY; //coordinates of lines painted between nodes and their collapse signs bool hasCollSign; // has the currently processed node collapse/expand sign ? nodeFrame = node->ScreenFrame(); if (node != tree->GetRoot()) { // paints collapse/expand sign hasCollSign = node->IsCollapsable() && (node->GetFirstChild() != NULL); if (hasCollSign) { GetCollapseSignFrame(node, collSignFrame); if (node->IsCollapsed()) currImage = expandImage; else currImage = collImage; if (currImage != NULL) currImage->Draw(collSignFrame); } // paints node selection box if (node == tree->GetSelected()) g2d->DrawBox(nodeFrame.xmin-2, nodeFrame.ymin, nodeFrame.Width()+4, nodeFrame.Height(), selectedColor); } if (node->IsCollapsed()) return; // paints children of node child = node->GetFirstChild(); if (child != NULL) { childFrame = child->ScreenFrame(); vertLineX = (nodeFrame.xmin + childFrame.xmin) / 2; vertLineYMin = childFrame.ymin; do { hasCollSign = child->IsCollapsable() && (child->GetFirstChild() != NULL); childFrame = child->ScreenFrame(); horizLineY = (childFrame.ymin + childFrame.ymax) / 2; GetCollapseSignFrame(child, collSignFrame); if (hasCollSign) { horizLineXMin = collSignFrame.xmax; vertLineYMax = collSignFrame.ymin-1; } else { horizLineXMin = vertLineX; vertLineYMax = horizLineY; } g2d->DrawLine(vertLineX, vertLineYMin, vertLineX, vertLineYMax, lineColor); g2d->DrawLine(horizLineXMin, horizLineY, childFrame.xmin - 3, horizLineY, lineColor); DecorateSubtree(child); // determines vertLineYMin for next sibling: if (hasCollSign) vertLineYMin = collSignFrame.ymax+1; else vertLineYMin = horizLineY; child = child->GetNextSibling(); } while (child != NULL); } } bool pawsStdTreeDecorator::OnMouseDown(int button, int modifiers, int x, int y) { pawsTreeNode * target, * root; root = tree->GetRoot(); if (root != NULL) { target = FindCollapsingNodeInSubtree(root, x, y); if (target != NULL) { // has the currently processed node collapse/expand sign ? bool hasCollSign = target->IsCollapsable() && (target->GetFirstChild() != NULL); if (hasCollSign) { if (target->IsCollapsed()) target->Expand(); else target->Collapse(); } } } return false; } void pawsStdTreeDecorator::GetCollapseSignFrame(pawsTreeNode * node, csRect & rect) { csRect nodeFrame = node->ScreenFrame(); rect.SetPos(nodeFrame.xmin - collSpacing - 2, nodeFrame.ymin + nodeFrame.Height()/2 - 4); rect.SetSize(10, 10); } pawsTreeNode * pawsStdTreeDecorator::FindCollapsingNodeInSubtree(pawsTreeNode * subtreeRoot, int x, int y) { csRect signFrame; pawsTreeNode * child, * found; // has the currently processed node collapse/expand sign ? bool hasCollSign = subtreeRoot->IsCollapsable() && (subtreeRoot->GetFirstChild() != NULL); if (hasCollSign) { GetCollapseSignFrame(subtreeRoot, signFrame); if (signFrame.Contains(x, y)) return subtreeRoot; } child = subtreeRoot->GetFirstChild(); while (child != NULL) { found = FindCollapsingNodeInSubtree(child, x, y); if (found != NULL) return found; child = child->GetNextSibling(); } return NULL; } ////////////////////////////////////////////////////////////////////// // // pawsTree // ////////////////////////////////////////////////////////////////////// pawsTree::pawsTree() { selected = NULL; notificationTarget = NULL; layout = 0; SetTreeLayout(new pawsStdTreeLayout(this, 5, 20)); decor = 0; SetTreeDecorator(new pawsStdTreeDecorator(this, graphics2D, 0x666666, 0x999999, 13)); horizScrollBar = NULL; vertScrollBar = NULL; } pawsTree::~pawsTree() { if (layout != NULL) delete layout; if (decor != NULL) delete decor; if (root != NULL) { pawsWidget::DeleteChild(root); root = NULL; } } void pawsTree::SetRoot(pawsTreeNode * _root) { if (root != NULL) { if (selected == root) Deselect(); pawsWidget::DeleteChild(root); } root = _root; AddChild(root); } void pawsTree::SetScrollBars(bool horiz, bool vert) { if (horiz && (horizScrollBar == NULL)) { horizScrollBar = (pawsScrollBar*)PawsManager::GetSingleton().CreateWidget("pawsScrollBar"); if (horizScrollBar == NULL) { Error1("Could not created pawsScrollBar"); return; } AddChild(horizScrollBar); horizScrollBar->SetRelativeFrame(0, defaultFrame.Width()-GetActualHeight(SCROLLBAR_WIDTH), defaultFrame.Width(), GetActualHeight(SCROLLBAR_WIDTH)); horizScrollBar->PostSetup(); horizScrollBar->SetTickValue(20); horizScrollBar->Show(); } if (!horiz && (horizScrollBar != NULL)) { pawsWidget::DeleteChild(horizScrollBar); horizScrollBar = NULL; if (layout) layout->SetHorizScroll(0); } if (vert && (vertScrollBar == NULL)) { vertScrollBar = (pawsScrollBar*)PawsManager::GetSingleton().CreateWidget("pawsScrollBar"); if (vertScrollBar == NULL) { Error1("Could not created pawsScrollBar"); return; } AddChild(vertScrollBar); vertScrollBar->SetRelativeFrame(defaultFrame.Width()-GetActualWidth(SCROLLBAR_WIDTH), 0, GetActualWidth(SCROLLBAR_WIDTH), defaultFrame.Height()); vertScrollBar->PostSetup(); vertScrollBar->SetTickValue(20); vertScrollBar->SetAttachFlags(ATTACH_TOP | ATTACH_BOTTOM | ATTACH_RIGHT ); vertScrollBar->Show(); } if (!vert && (vertScrollBar != NULL)) { pawsWidget::DeleteChild(vertScrollBar); vertScrollBar = NULL; if (layout) layout->SetVertScroll(0); } SetScrollBarMax(); } void pawsTree::Select(pawsTreeNode *node) { selected = node; if (notificationTarget != NULL) notificationTarget->OnSelected(node); } void pawsTree::Deselect() { selected = NULL; } pawsTreeNode * pawsTree::GetSelected() { return selected; } bool pawsTree::Setup(iDocumentNode * node) { csRef decorator = node->GetNode("decorator"); if (decorator) { csRGBcolor selColour = csRGBcolor(102,102,102); csRGBcolor lineColour = csRGBcolor(153,153,153); int colSpacing = 13; csRef selR = decorator->GetAttribute("selR"); if (selR) selColour.red = selR->GetValueAsInt(); csRef selG = decorator->GetAttribute("selG"); if (selG) selColour.green = selG->GetValueAsInt(); csRef selB = decorator->GetAttribute("selB"); if (selB) selColour.blue = selB->GetValueAsInt(); csRef lineR = decorator->GetAttribute("lineR"); if (lineR) lineColour.red = lineR->GetValueAsInt(); csRef lineG = decorator->GetAttribute("lineG"); if (lineG) lineColour.green = lineG->GetValueAsInt(); csRef lineB = decorator->GetAttribute("lineB"); if (lineB) lineColour.blue = lineB->GetValueAsInt(); csRef colSpace = decorator->GetAttribute("colSpacing"); if (colSpace) colSpacing = colSpace->GetValueAsInt(); SetTreeDecorator(new pawsStdTreeDecorator(this, graphics2D, MakeColor(graphics2D->GetPixelFormat(), selColour.red, selColour.blue, selColour.green), MakeColor(graphics2D->GetPixelFormat(), lineColour.red, lineColour.blue, lineColour.green), colSpacing)); } csRef layout = node->GetNode("layout"); if (layout) { int rowSpacingVal = 5; int levelSpacingVal = 20; csRef rowSpacing = layout->GetAttribute("rowSpacing"); if (rowSpacing) rowSpacingVal = rowSpacing->GetValueAsInt(); csRef levelSpacing = layout->GetAttribute("levelSpacing"); if (levelSpacing) levelSpacingVal = levelSpacing->GetValueAsInt(); SetTreeLayout(new pawsStdTreeLayout(this, rowSpacingVal, levelSpacingVal)); } return true; } void pawsTree::Draw() { csRect oldClip; if (layout) { layout->SetLayout(); SetScrollBarMax(); } ClipToParent(); DrawBackground(); graphics2D->SetClipRect(screenFrame.xmin, screenFrame.ymin, screenFrame.xmax, screenFrame.ymax); if (decor) decor->Decorate(); ClipToParent(); DrawChildren(); } void pawsTree::SetTreeLayout(pawsITreeLayout * _layout) { if (layout) { delete layout; layout = 0; } layout = _layout; layout->SetLayout(); } void pawsTree::SetTreeDecorator(pawsITreeDecorator *_decor) { if (decor) { delete decor; decor = 0; } decor = _decor; } bool pawsTree::OnMouseDown(int button, int modifiers, int x, int y) { if (button == csmbWheelUp) { if (vertScrollBar) vertScrollBar->SetCurrentValue(vertScrollBar->GetCurrentValue() - TREE_MOUSE_SCROLL_AMOUNT); return true; } else if (button == csmbWheelDown) { if (vertScrollBar) vertScrollBar->SetCurrentValue(vertScrollBar->GetCurrentValue() + TREE_MOUSE_SCROLL_AMOUNT); return true; } else { pawsTreeNode *node; if (root != NULL) { node = FindNodeAt(root, x, y); if (node != NULL) { Select(node); return true; } } if (decor != NULL) if (decor->OnMouseDown(button, modifiers, x, y)) return true; } return false; } bool pawsTree::OnKeyDown( int keyCode, int keyChar, int modifiers ) { pawsTreeNode *node; switch (keyCode) { case 1000: if (selected != NULL) { node = selected; do { node = node->FindNodeAbove(); } while ((node != NULL) && node->BuriedInRuins()); if ((node != NULL) && (node != root)) Select(node); } return true; case 1001: if (selected != NULL) { node = selected; do { node = node->FindNodeBelow(); } while ((node != NULL) && node->BuriedInRuins()); if (node != NULL) Select(node); } return true; case 13: if (selected == NULL) //some notify? return true; } return false; } bool pawsTree::LoadChildren( iDocumentNode* node ) { return pawsTreeStruct::Load(node); } void pawsTree::SetScrollBarMax() { int width, height; if (layout != NULL) { layout->GetTreeSize(width, height); if (horizScrollBar != NULL) horizScrollBar -> SetMaxValue(MAX(0, width - screenFrame.Width())); if (vertScrollBar != NULL) vertScrollBar -> SetMaxValue(MAX(0, height - screenFrame.Height())); } } void pawsTree::SetNotify(pawsWidget* _notificationTarget) { notificationTarget = _notificationTarget; } bool pawsTree::OnScroll(int scrollDirection, pawsScrollBar* widget) { int scroll; scroll = (int)widget->GetCurrentValue(); version++; if (widget == horizScrollBar) layout->SetHorizScroll(scroll); else if (widget == vertScrollBar) layout->SetVertScroll(scroll); return true; } void pawsTree::NewNode(pawsTreeNode * node) { pawsWidget::AddChild(node); } void pawsTree::RemoveNode(pawsTreeNode * node) { pawsWidget::RemoveChild(node); } ////////////////////////////////////////////////////////////////////// // // pawsSeqTreeNode // ////////////////////////////////////////////////////////////////////// pawsSeqTreeNode_widget::pawsSeqTreeNode_widget(pawsWidget * _w, int _width) { widget = _w; width = _width; } void pawsSeqTreeNode::AddSeqWidget(pawsWidget * w, int width) { csRect widgetFrame; widgets.PushBack(pawsSeqTreeNode_widget(w, width)); AddChild(w); w->MoveTo(screenFrame.xmax+1, screenFrame.ymin); w->Show(); Resize(width, 0, RESIZE_RIGHT); widgetFrame = w->ScreenFrame(); if (widgetFrame.ymax > screenFrame.ymax) Resize(0, widgetFrame.ymax - screenFrame.ymax, RESIZE_BOTTOM); } void pawsSeqTreeNode::AddSeqWidget(pawsWidget * widget) { int width = widget->ScreenFrame().Width(); AddSeqWidget(widget, width); } pawsWidget * pawsSeqTreeNode::GetSeqWidget(int index) { csList::Iterator iter(widgets); int currIndex=0; while ((iter.HasNext())) { iter.Next(); if(currIndex == index) return iter->widget; currIndex++; } return NULL; } bool pawsSeqTreeNode::Load(iDocumentNode *node) { return pawsTreeNode::Load(node); } ////////////////////////////////////////////////////////////////////// // // pawsCheckTreeNode // ////////////////////////////////////////////////////////////////////// pawsCheckTreeNode::pawsCheckTreeNode() { widget = NULL; // checkbox = NULL; } bool pawsCheckTreeNode::GetCheck() { return false; } void pawsCheckTreeNode::SetCheck(bool ch) { //checkbox->Set(ch); } void pawsCheckTreeNode::SetWidget(pawsWidget * _widget) { csRect widgetFrame; if (widget != NULL) { pawsWidget::DeleteChild(widget); widget = NULL; } widget = _widget; widgetFrame = widget->ScreenFrame(); AddChild(widget); widget->MoveTo(screenFrame.xmin, screenFrame.ymin); widget->Show(); SetSize(widgetFrame.Width(), widgetFrame.Height()); } ////////////////////////////////////////////////////////////////////// // // pawsWidgetTreeNode // ////////////////////////////////////////////////////////////////////// pawsWidgetTreeNode::pawsWidgetTreeNode() { widget = NULL; } void pawsWidgetTreeNode::SetWidget(pawsWidget * _widget) { csRect widgetFrame; if (widget != NULL) pawsWidget::DeleteChild(widget); widget = _widget; widget->MoveTo(screenFrame.xmin, screenFrame.ymin); widgetFrame = widget->ScreenFrame(); SetSize(widgetFrame.Width(), widgetFrame.Height()); AddChild(widget); } bool pawsWidgetTreeNode::Load(iDocumentNode *node) { csRef nodewidgetNode, widgetNode; csString factory; pawsWidget * newWidget; name = node->GetAttributeValue("name"); nodewidgetNode = node->GetNode("nodewidget"); if (nodewidgetNode == NULL) return false; widgetNode = nodewidgetNode->GetNode("widget"); if (widgetNode == NULL) return false; factory = widgetNode->GetAttributeValue("factory"); newWidget = PawsManager::GetSingleton().CreateWidget(factory); if (newWidget == NULL) return false; if ( ! newWidget->Load(widgetNode)) { delete newWidget; return false; } SetWidget(newWidget); return pawsTreeNode::Load(node); } ////////////////////////////////////////////////////////////////////// // // pawsSimpleTree // ////////////////////////////////////////////////////////////////////// pawsSimpleTreeNode::pawsSimpleTreeNode() { textBox = NULL; image = NULL; SetWidget(new pawsWidget()); } void pawsSimpleTreeNode::Set(int mode, bool checked, const csString & imageName, const csString & label) { csRect frame; int lastX; assert(tree != NULL); if (textBox != NULL) { widget->DeleteChild(textBox); textBox = NULL; } if (image != NULL) { widget->DeleteChild(image); image = NULL; } lastX = screenFrame.xmin - 1; if (mode & showCheckBox) { assert("checkbox nodes are not currently implemented"==0); } if (mode & showImage) { image = new pawsWidget(); image->SetSize(20, 20); image->SetBackground(imageName); image->MoveTo(lastX+1, screenFrame.ymin); widget->AddChild(image); lastX += 20; } if (mode & showLabel) { textBox = (pawsTextBox*)PawsManager::GetSingleton().CreateWidget("pawsTextBox"); textBox->SetParent(widget); if (textBox == NULL) return; textBox->SetText(label); textBox->SetSizeByText(); textBox->MoveTo(lastX+1,0); widget->AddChild(textBox); lastX += textBox->ScreenFrame().Width(); } widget->SetRelativeFrame(0,0,lastX-screenFrame.xmin,20); widget->SetSize(lastX-screenFrame.xmin, 20); widget->MoveTo(0,0); SetRelativeFrameSize(lastX - screenFrame.xmin, 20); } bool pawsSimpleTreeNode::Load(iDocumentNode *node) { csRef labelAttr, imageAttr, checkedAttr; csString labelValue, imageValue; bool checkedValue = false; int mode; if (!pawsCheckTreeNode::Load(node)) return false; mode = 0; name = node->GetAttributeValue("name"); checkedAttr = node->GetAttribute("checked"); if (checkedAttr != NULL) { checkedValue = (checkedAttr->GetValueAsInt() == 1); mode |= showCheckBox; } imageAttr = node->GetAttribute("image"); if (imageAttr != NULL) { imageValue = imageAttr->GetValue(); mode |= showImage; } labelAttr = node->GetAttribute("label"); if (labelAttr != NULL) { labelValue = PawsManager::GetSingleton().Translate(labelAttr->GetValue()); mode |= showLabel; } Set(mode, checkedValue, imageValue, labelValue); return true; } bool pawsSimpleTree::Setup(iDocumentNode *node) { csString colorStr; colorStr = node->GetAttributeValue("colour"); name = node->GetAttributeValue("name"); if (colorStr.GetData() != NULL) defaultColor = ParseColor(colorStr.GetData(), graphics2D); else defaultColor = 0xffffff; return true; } int pawsSimpleTree::GetDefaultColor() { return defaultColor; } void pawsSimpleTree::SetDefaultColor(int _color) { defaultColor = _color; } void pawsSimpleTree::InsertChildL(const csString & parent, const csString & name, const csString & label, const csString & nextSibling) { pawsSimpleTreeNode * node = new pawsSimpleTreeNode(); pawsTreeStruct::InsertChild(parent, node, nextSibling); node->SetColour(defaultColor); node->Set(showLabel, false, "", label); node->SetName(name); } void pawsSimpleTree::InsertChildI(const csString & parent, const csString & name, const csString & image, const csString & nextSibling) { pawsSimpleTreeNode * node = new pawsSimpleTreeNode(); pawsTreeStruct::InsertChild(parent, node, nextSibling); node->SetColour(defaultColor); node->Set(showImage, false, image, ""); node->SetName(name); } void pawsSimpleTree::InsertChildIL(const csString & parent, const csString & name, const csString & image, const csString & label, const csString & nextSibling) { pawsSimpleTreeNode * node = new pawsSimpleTreeNode(); pawsTreeStruct::InsertChild(parent, node, nextSibling); node->SetColour(defaultColor); node->Set(showLabel | showImage, false, image, label); node->SetName(name); } pawsSimpleTree::pawsSimpleTree() { layout = new pawsStdTreeLayout(this, 5, 20); decor = new pawsStdTreeDecorator(this, graphics2D, 0x0000ff, 0x00ffff, 13); }