kwwidgets-1.0.0~cvs20100930/0000755000175000017500000000000011461110203015046 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/vtkKWCornerAnnotationEditor.h0000644000175000017500000001426410542004506022656 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWCornerAnnotationEditor.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWCornerAnnotationEditor - a corner annotation widget // .SECTION Description // A class that provides a UI for vtkCornerAnnotation. User can set the // text for each corner, set the color of the text, and turn the annotation // on and off. #ifndef __vtkKWCornerAnnotationEditor_h #define __vtkKWCornerAnnotationEditor_h #include "vtkKWCheckButtonWithPopupFrame.h" class vtkCornerAnnotation; class vtkKWFrame; class vtkKWGenericComposite; class vtkKWLabel; class vtkKWPopupButtonWithLabel; class vtkKWTextWithLabel; class vtkKWRenderWidget; class vtkKWScaleWithEntry; class vtkKWTextPropertyEditor; class KWWidgets_EXPORT vtkKWCornerAnnotationEditor : public vtkKWCheckButtonWithPopupFrame { public: static vtkKWCornerAnnotationEditor* New(); vtkTypeRevisionMacro(vtkKWCornerAnnotationEditor,vtkKWCheckButtonWithPopupFrame); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Makes the text property sub-widget popup (instead of displaying the // whole text property UI, which can be long). // This has to be called before Create(). Ignored if PopupMode is true. vtkSetMacro(PopupTextProperty, int); vtkGetMacro(PopupTextProperty, int); vtkBooleanMacro(PopupTextProperty, int); // Description: // Set/Get the vtkKWView or the vtkKWRenderWidget that owns this annotation. // vtkKWView and vtkKWRenderWidget are two different frameworks, choose one // or the other (ParaView uses vtkKWView, VolView uses vtkKWRenderWidget). // Note that in vtkKWView mode, each view has a vtkKWCornerAnnotationEditor. // In vtkKWRenderWidget, each widget has a vtkCornerAnnotation, which is // controlled by a unique (decoupled) vtkKWCornerAnnotationEditor in the GUI. // It is not ref-counted. virtual void SetRenderWidget(vtkKWRenderWidget*); vtkGetObjectMacro(RenderWidget,vtkKWRenderWidget); // Description: // Get the underlying vtkCornerAnnotation. // In vtkKWView mode, the CornerAnnotation is created automatically and // handled by this class (i.e. each vtkKWCornerAnnotationEditor has a // vtkCornerAnnotation). // In vtkKWRenderWidget, the corner prop is part of vtkKWRenderWidget, and // this method is just a gateway to vtkKWRenderWidget::GetCornerAnnotation(). vtkGetObjectMacro(CornerAnnotation, vtkCornerAnnotation); // Description: // Set/Get the annotation visibility virtual void SetVisibility(int i); virtual int GetVisibility(); vtkBooleanMacro(Visibility, int); // Description: // Set/Get corner text virtual void SetCornerText(const char *txt, int corner); virtual const char *GetCornerText(int i); // Description: // Change the color of the annotation virtual void SetTextColor(double r, double g, double b); virtual void SetTextColor(double *rgb) { this->SetTextColor(rgb[0], rgb[1], rgb[2]); } virtual double *GetTextColor(); // Description: // Set/Get the maximum line height. virtual void SetMaximumLineHeight(float); // Description: // Set the event invoked when the anything in the annotation is changed. // Defaults to vtkKWEvent::ViewAnnotationChangedEvent vtkSetMacro(AnnotationChangedEvent, int); vtkGetMacro(AnnotationChangedEvent, int); // Description: // Access to sub-widgets virtual vtkKWCheckButton* GetCornerVisibilityButton() { return this->GetCheckButton(); }; // Description: // Update the GUI according to the value of the ivars virtual void Update(); // Description: // When used with a vtkKWView, close out and remove any composites/props // prior to deletion. Has no impact when used with a vtkKWRenderWidget. virtual void Close(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Access to the TextPropertyWidget from a script. vtkGetObjectMacro(TextPropertyWidget, vtkKWTextPropertyEditor); // Description: // Callbacks. Internal, do not use. virtual void CheckButtonCallback(int state); virtual void CornerTextCallback(int i); virtual void MaximumLineHeightCallback(double value); virtual void MaximumLineHeightEndCallback(double value); virtual void TextPropertyCallback(); protected: vtkKWCornerAnnotationEditor(); ~vtkKWCornerAnnotationEditor(); // Description: // Create the widget. virtual void CreateWidget(); int AnnotationChangedEvent; vtkCornerAnnotation *CornerAnnotation; vtkKWRenderWidget *RenderWidget; // GUI int PopupTextProperty; vtkKWFrame *CornerFrame; vtkKWTextWithLabel *CornerText[4]; vtkKWFrame *PropertiesFrame; vtkKWScaleWithEntry *MaximumLineHeightScale; vtkKWTextPropertyEditor *TextPropertyWidget; vtkKWPopupButtonWithLabel *TextPropertyPopupButton; virtual void Render(); // Get the value that should be used to set the checkbutton state // (i.e. depending on the value this checkbutton is supposed to reflect, // for example, an annotation visibility). // This does *not* return the state of the widget. virtual int GetCheckButtonState() { return this->GetVisibility(); }; // Send an event representing the state of the widget virtual void SendChangedEvent(); private: vtkKWCornerAnnotationEditor(const vtkKWCornerAnnotationEditor&); // Not implemented void operator=(const vtkKWCornerAnnotationEditor&); // Not Implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWWidgetSet.h0000644000175000017500000001741511157522002020123 0ustar domibeldomibel/*========================================================================= Module: vtkKWWidgetSet.h,v Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWWidgetSet - an abstract set of a specific type of vtkKWWidget // .SECTION Description // This class is a composite widget that can be used to conveniently // allocate, store and layout a set of widgets of the same type. // Each widget is created, removed or queried based on a unique ID provided // by the user (ids are *not* handled by the class since it is likely that // they will be defined as enum's or #define by the user for easier retrieval). // Widgets are packed (gridded) in the order they were added to the set. // // IMPORTANT: this is an abstract superclass, it can not be used as-is. // A subclass of vtkKWWidgetSet is tailored for a *specific* type of widget // (see vtkKWPushButtonSet, which is a set of vtkKWPushButton); it can not be // used to store or layout a set of heterogeneous widgets. // // This class acts as a container of widgets of the same type; the main point // of this container is not to provide a layout mechanism, but to make it a // little more convenient to create and allocate a whole bunch of widgets // of the same type without explicitly declaring a pointer to each and // everyone of them. Say, if you need ten buttons, and you do not want to // make 10 calls to vtkKWPushButton::New(), 10 calls to // vtkKWPushButton::Create(), and 10 calls to vtkKWPushButton::Delete(): just // create one instance of a vtkKWPushButtonSet, then call // vtkKWPushButtonSet::AddWidget to automatically allocate and create an // instance of a vtkKWPushButton. This widget will be packed in a grid // fashion with the other widgets in the set, as a bonus. Widgets that are // added, allocated and created that way are automatically de-allocated when // the vtkKWWidgetSet instance is deleted. // // Be aware that the pretty much all subclasses of vtkKWWidgetSet are // generated automatically out of the vtkKWWidgetSetSubclass template located // in the Templates directory. Therefore, even though the source code for // those vtkKWWidgetSet subclasses does not exist in the KWWidgets repository, // they are still generated automatically and documented in the API online; // check the vtkKWWidgetSet API online for its subclasses, as well as the // \subpage kwwidgets_autogenerated_page page. // Classes related to the same template can be found in the // \ref kwwidgets_autogenerated_widget_set_group section. // Subclasses need to implement AllocateAndCreateWidget // .SECTION See Also // vtkKWCheckButtonSet vtkKWComboBoxSet vtkKWEntrySet vtkKWLabelSet vtkKWLabelWithLabelSet vtkKWPushButtonSet vtkKWScaleSet vtkKWScaleWithEntrySet vtkKWSpinBoxSet #ifndef __vtkKWWidgetSet_h #define __vtkKWWidgetSet_h #include "vtkKWCompositeWidget.h" class vtkKWWidget; class vtkKWWidgetSetInternals; class KWWidgets_EXPORT vtkKWWidgetSet : public vtkKWCompositeWidget { public: vtkTypeRevisionMacro(vtkKWWidgetSet,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the number of widget in the set. virtual int GetNumberOfWidgets(); // Description: // Retrieve the id of the n-th widget (-1 if not found) virtual int GetIdOfNthWidget(int rank); // Description: // Check if a widget is in the set, given its unique id. // Return 1 if exists, 0 otherwise. virtual int HasWidget(int id); // Description: // Retrieve the position in the set the widget was inserted at. // Return pos if exists, -1 otherwise virtual int GetWidgetPosition(int id); // Description: // Hide/show a widget, given its unique id. // Get the number of visible widget in the set. // Since the changing the widget visibility will trigger an expensive call // to Pack(), one can use SetWidgetsVisibility to change the visibility of // many widgets in a single call. virtual void HideWidget(int id); virtual void ShowWidget(int id); virtual int GetWidgetVisibility(int id); virtual void SetWidgetVisibility(int id, int flag); virtual int GetNumberOfVisibleWidgets(); virtual int GetIdOfNthVisibleWidget(int rank); virtual void SetWidgetsVisibility(int nb_ids, int *ids, int *flags); // Description: // Delete all widgets. virtual void DeleteAllWidgets(); // Description: // Set the packing direction to be horizontal (default is vertical). virtual void SetPackHorizontally(int); vtkBooleanMacro(PackHorizontally, int); vtkGetMacro(PackHorizontally, int); // Description: // Set the maximum number of widgets that will be packed in the packing // direction (i.e. horizontally or vertically). // For example, if set to 3 and the packing direction is horizontal, // the layout ends up as 3 columns of widgets. // The default is 0, i.e. all widgets are packed along the same direction. virtual void SetMaximumNumberOfWidgetsInPackingDirection(int); vtkGetMacro(MaximumNumberOfWidgetsInPackingDirection, int); // Description: // Set/Get the padding that will be applied around each widget. // (default to 0). virtual void SetWidgetsPadX(int); vtkGetMacro(WidgetsPadX, int); virtual void SetWidgetsPadY(int); vtkGetMacro(WidgetsPadY, int); // Description: // Set/Get the internal padding that will be left around each widget. // This space is added inside the widget border. // (default to 0). virtual void SetWidgetsInternalPadX(int); vtkGetMacro(WidgetsInternalPadX, int); virtual void SetWidgetsInternalPadY(int); vtkGetMacro(WidgetsInternalPadY, int); // Description: // Set the layout to allow the widgets to expand automatically // within the set. virtual void SetExpandWidgets(int); vtkBooleanMacro(ExpandWidgets, int); vtkGetMacro(ExpandWidgets, int); // Description: // Set/Get if the column/row layout should be uniform (enforce same size). virtual void SetUniformColumns(int); vtkBooleanMacro(UniformColumns, int); vtkGetMacro(UniformColumns, int); virtual void SetUniformRows(int); vtkBooleanMacro(UniformRows, int); vtkGetMacro(UniformRows, int); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); protected: vtkKWWidgetSet(); ~vtkKWWidgetSet(); // Description: // Create the widget. virtual void CreateWidget(); int PackHorizontally; int MaximumNumberOfWidgetsInPackingDirection; int WidgetsPadX; int WidgetsPadY; int WidgetsInternalPadX; int WidgetsInternalPadY; int ExpandWidgets; int UniformColumns; int UniformRows; // Description: // To be implemented by superclasses. // Allocate and create a widget of the right type. // Return a pointer to the superclass though. virtual vtkKWWidget* AllocateAndCreateWidget() = 0; // BTX // PIMPL Encapsulation for STL containers vtkKWWidgetSetInternals *Internals; //ETX // Helper methods virtual vtkKWWidget* GetWidgetInternal(int id); virtual vtkKWWidget* InsertWidgetInternal(int id, int pos); // Description: // Pack the widgets virtual void Pack(); private: vtkKWWidgetSet(const vtkKWWidgetSet&); // Not implemented void operator=(const vtkKWWidgetSet&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWSmallCounterLabel.cxx0000644000175000017500000000644011076647462022165 0ustar domibeldomibel/*========================================================================= Module: vtkKWSmallCounterLabel.cxx,v Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWSmallCounterLabel.h" #include "vtkKWOptions.h" #include "vtkKWIcon.h" #include "vtkKWTopLevel.h" #include "vtkObjectFactory.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWSmallCounterLabel ); vtkCxxRevisionMacro(vtkKWSmallCounterLabel, "1.119"); //---------------------------------------------------------------------------- vtkKWSmallCounterLabel::vtkKWSmallCounterLabel() { this->Value = 0; this->OriginalParent = NULL; } //---------------------------------------------------------------------------- vtkKWSmallCounterLabel::~vtkKWSmallCounterLabel() { } //---------------------------------------------------------------------------- void vtkKWSmallCounterLabel::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // We need to override this->OriginalParent = this->Parent; this->SetParent(this->GetParentTopLevel()); // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // It's an icon, really this->SetText(NULL); this->SetHighlightThickness(0); this->SetBorderWidth(0); this->SetPadX(0); this->SetPadY(0); this->UpdateIcon(); this->Place(); } //---------------------------------------------------------------------------- void vtkKWSmallCounterLabel::SetValue(unsigned int arg) { if (arg < 0) { arg = 0; } else if (arg > 10) { arg = 10; } if (this->Value == arg) { return; } int old_value = this->Value; this->Value = arg; this->Modified(); this->UpdateIcon(); if (!arg || !old_value) { this->Place(); } } //---------------------------------------------------------------------------- void vtkKWSmallCounterLabel::UpdateIcon() { if (this->Value) { int v = (this->Value > 10 ? 10 : this->Value); this->SetImageToPredefinedIcon(vtkKWIcon::IconSmallCounterBlue1 + v - 1); } } //---------------------------------------------------------------------------- void vtkKWSmallCounterLabel::Place() { if (!this->IsCreated()) { return; } if (!this->Value || (!this->GetParent()->IsPacked() && !this->GetParent()->IsGridded() && !this->GetParent()->IsPlaced())) { this->Unplace(); } else { this->Script( "place %s -anchor center -relx 0.70 -y -3 -in %s", this->GetWidgetName(), this->OriginalParent->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWSmallCounterLabel::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Value: " << this->Value << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWMenu.cxx0000644000175000017500000015756611205017055017520 0ustar domibeldomibel/*========================================================================= Module: vtkKWMenu.cxx,v Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWMenu.h" #include "vtkKWApplication.h" #include "vtkObjectFactory.h" #include "vtkKWWindowBase.h" #include "vtkKWTkUtilities.h" #include "vtkKWIcon.h" #include "vtkKWOptions.h" #include #include #include #include #include #define VTK_KW_MENU_CB_VARNAME_PATTERN "CB_group%d" #define VTK_KW_MENU_RB_DEFAULT_GROUP "RB_group" #define VTK_KW_MENU_VAR_SEPARATOR "_" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWMenu ); vtkCxxRevisionMacro(vtkKWMenu, "$Revision: 1.129 $"); //---------------------------------------------------------------------------- class vtkKWMenuInternals { public: int ItemCounter; int IndexOfLastActiveItem; vtksys_stl::string GetItemCommandTemp; struct CascadePoolType: public vtksys_stl::map {}; CascadePoolType CascadePool; }; //---------------------------------------------------------------------------- vtkKWMenu::vtkKWMenu() { this->TearOff = 0; this->Internals = new vtkKWMenuInternals; this->Internals->ItemCounter = 0; this->Internals->IndexOfLastActiveItem = -1; } //---------------------------------------------------------------------------- vtkKWMenu::~vtkKWMenu() { if (this->Internals) { delete this->Internals; this->Internals = NULL; } } //---------------------------------------------------------------------------- void vtkKWMenu::CreateWidget() { // Call the superclass to create the widget and set the appropriate flags if (!vtkKWWidget::CreateSpecificTkWidget(this, "menu")) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } this->SetConfigurationOptionAsInt("-tearoff", this->TearOff); this->SetBinding("<>", this, "DisplayHelpCallback %W"); } //---------------------------------------------------------------------------- int vtkKWMenu::GetLabelWithoutUnderline( const char *label, char **clean_label, int *underline_index) { const char marker = '&'; // Find the marker (should not be the last char, or followed by space) char *found = const_cast(strchr(label, marker)); while(found) { ++found; if(*found && *found != ' ') { break; } found = const_cast(strchr(const_cast(found), marker)); } // Not found, sorry if (!found) { *clean_label = const_cast(label); *underline_index = -1; return 0; } // Create the clean one *underline_index = found - label - 1; size_t clean_label_len = *underline_index + strlen(found); *clean_label = new char [clean_label_len + 1]; if (*underline_index) { memcpy(*clean_label, label, *underline_index); // contents before marker } memcpy(*clean_label + *underline_index, const_cast(found), clean_label_len - *underline_index); // contents after marker (*clean_label)[clean_label_len] = '\0'; return 1; } //---------------------------------------------------------------------------- int vtkKWMenu::AddGeneric(const char* type, const char *label, const char* extra) { return this->InsertGeneric(this->GetNumberOfItems(), type, label, extra); } //---------------------------------------------------------------------------- int vtkKWMenu::InsertGeneric(int index, const char* type, const char *label, const char* extra) { if (!this->IsCreated()) { return -1; } if (index < 0) { index = 0; } if (index == 0) { if (this->TearOff) // If tearoff, then entry 0 is always taken { index = 1; } } else { int nb_items = this->GetNumberOfItems(); // cap the index if (index > nb_items) { index = nb_items; } } vtksys_ios::ostringstream str; str << this->GetWidgetName() << " insert " << index << " " << type; char *clean_label = NULL; int underline_index, cleaned = 0; if (label) { cleaned = this->GetLabelWithoutUnderline(label, &clean_label, &underline_index); str << " -label {" << clean_label << "}"; } if(extra) { str << " " << extra; } this->Script(str.str().c_str()); if (label) { this->SetItemHelpString(index, clean_label); if (cleaned) { this->SetItemUnderline(index, underline_index); delete [] clean_label; } } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::AddCommand(const char *label) { return this->AddCommand(label, NULL, NULL); } //---------------------------------------------------------------------------- int vtkKWMenu::AddCommand(const char *label, vtkObject *object, const char *method) { int index = this->AddGeneric("command", label, NULL); if (index >= 0) { this->SetItemCommand(index, object, method); this->InvokeEvent(vtkKWMenu::CommandItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::InsertCommand(int index, const char *label) { return this->InsertCommand(index, label, NULL, NULL); } //---------------------------------------------------------------------------- int vtkKWMenu::InsertCommand(int index, const char *label, vtkObject *object, const char *method) { index = this->InsertGeneric(index, "command", label, NULL); if (index >= 0) { this->SetItemCommand(index, object, method); this->InvokeEvent(vtkKWMenu::CommandItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemCommand(int index, vtkObject *object, const char *method) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } char *command = NULL; this->SetObjectMethodCommand(&command, object, method); // Let's add the CommandInvokedCallback wrapper // The wrapper is used to send an event when the entry is invoked. this->Script( "%s entryconfigure %d -command {%s CommandInvokedCallback {%s}}", this->GetWidgetName(), index, this->GetTclName(), command); delete [] command; } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetItemCommand(int index) { const char *command = this->GetItemOption(index, "-command"); if (!command || !*command) { return command; } // Let's strip the CommandInvokedCallback wrapper out // The wrapper is used to send an event when the entry is invoked. vtksys_stl::string &temp = this->Internals->GetItemCommandTemp; temp = command; const char *pattern = "CommandInvokedCallback {"; vtksys_stl::string::size_type pos = temp.find(pattern); if(pos != vtksys_stl::string::npos) { temp[temp.size() - 1] = '\0'; // Remove the last enclosing '}' return temp.c_str() + pos + strlen(pattern); } return command; } //---------------------------------------------------------------------------- void vtkKWMenu::CommandInvokedCallback(const char *command) { int index = this->Internals->IndexOfLastActiveItem; if (index >= 0) { this->InvokeEvent(vtkKWMenu::MenuItemInvokedEvent, &index); } this->InvokeObjectMethodCommand(command); } //---------------------------------------------------------------------------- int vtkKWMenu::AddCheckButton(const char *label) { return this->AddCheckButton(label, NULL, NULL); } //---------------------------------------------------------------------------- int vtkKWMenu::AddCheckButton(const char *label, vtkObject *object, const char *method) { int index = this->AddGeneric("checkbutton", label, NULL); if (index >= 0) { this->SetItemCommand(index, object, method); char group_name[200]; sprintf(group_name, VTK_KW_MENU_CB_VARNAME_PATTERN, this->Internals->ItemCounter++); this->SetItemVariable(index, this, group_name); this->SetItemSelectedValueAsInt(index, 1); this->SetItemDeselectedValueAsInt(index, 0); this->InvokeEvent(vtkKWMenu::CheckButtonItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::InsertCheckButton(int index, const char *label) { return this->InsertCheckButton(index, label, NULL, NULL); } //---------------------------------------------------------------------------- int vtkKWMenu::InsertCheckButton(int index, const char *label, vtkObject *object, const char *method) { index = this->InsertGeneric(index, "checkbutton", label, NULL); if (index >= 0) { this->SetItemCommand(index, object, method); char group_name[200]; sprintf(group_name, VTK_KW_MENU_CB_VARNAME_PATTERN, this->Internals->ItemCounter++); this->SetItemVariable(index, this, group_name); this->SetItemSelectedValueAsInt(index, 1); this->SetItemDeselectedValueAsInt(index, 0); this->InvokeEvent(vtkKWMenu::CheckButtonItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- void vtkKWMenu::SelectItem(int index) { const char *temp = this->GetItemVariable(index); if (temp) { vtksys_stl::string varname(temp); this->SetItemVariableValue( varname.c_str(), this->GetItemSelectedValue(index)); } } //---------------------------------------------------------------------------- void vtkKWMenu::SelectItem(const char *label) { this->SelectItem(this->GetIndexOfItem(label)); } //---------------------------------------------------------------------------- void vtkKWMenu::DeselectItem(int index) { const char *temp = this->GetItemVariable(index); if (temp) { vtksys_stl::string varname(temp); this->SetItemVariableValue( varname.c_str(), this->GetItemDeselectedValue(index)); } } //---------------------------------------------------------------------------- void vtkKWMenu::DeselectItem(const char *label) { this->DeselectItem(this->GetIndexOfItem(label)); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemSelectedState(int index, int state) { if (state) { this->SelectItem(index); } else { this->DeselectItem(index); } } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemSelectedState(const char *label, int state) { this->SetItemSelectedState(this->GetIndexOfItem(label), state); } //---------------------------------------------------------------------------- int vtkKWMenu::GetItemSelectedState(int index) { const char *temp = this->GetItemVariableValue(this->GetItemVariable(index)); if (temp) { vtksys_stl::string current_val(temp); temp = this->GetItemSelectedValue(index); if (temp) { return !strcmp(current_val.c_str(), temp) ? 1 : 0; } } return 0; } //---------------------------------------------------------------------------- int vtkKWMenu::GetItemSelectedState(const char *label) { return this->GetItemSelectedState(this->GetIndexOfItem(label)); } //---------------------------------------------------------------------------- char* vtkKWMenu::CreateItemVariableName(vtkKWObject *object, const char *suffix) { char *buffer = NULL; const char *objname = object->GetTclName(); if (objname && suffix) { size_t objname_len = strlen(objname); size_t suffix_len = strlen(suffix); size_t sep_len = strlen(VTK_KW_MENU_VAR_SEPARATOR); buffer = new char[objname_len + sep_len + suffix_len + 1]; sprintf(buffer, "%s%s", objname, VTK_KW_MENU_VAR_SEPARATOR); char *buffer_ptr = buffer + objname_len + sep_len; const char *suffix_end = suffix + suffix_len; while (suffix < suffix_end) { if (*suffix >= 0 && *suffix != ' ') { *buffer_ptr = *suffix; buffer_ptr++; } suffix++; } *buffer_ptr = '\0'; } return buffer; } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetSuffixOutOfCreatedItemVariableName( const char *varname) { if (varname) { return varname + strlen(this->GetTclName()) + strlen(VTK_KW_MENU_VAR_SEPARATOR); } return NULL; } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetItemVariableValue(const char *varname) { if (varname && *varname) { return this->Script("set %s", varname); } return NULL; } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemVariableValue(const char *varname, const char *value) { if (varname) { this->Script("if {![info exists %s] || \"$%s\" ne \"%s\"} {set %s \"%s\"}", varname, varname, value ? value : "", varname, value ? value : ""); } } //---------------------------------------------------------------------------- int vtkKWMenu::GetItemVariableValueAsInt(const char *varname) { const char *temp = this->GetItemVariableValue(varname); if (temp) { return atoi(temp); } return 0; } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemVariableValueAsInt(const char *varname, int value) { if (varname) { this->Script("if {![info exists %s] || $%s != %d} {set %s %d}", varname, varname, value, varname, value); } } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemVariable(int index, const char *varname) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } if (varname) { this->Script("%s entryconfigure %d -variable {%s}", this->GetWidgetName(), index, varname); } } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemVariable(int index, vtkKWObject *object, const char *suffix) { char *varname = this->CreateItemVariableName(object, suffix); this->SetItemVariable(index, varname); delete [] varname; } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetItemVariable(int index) { return this->GetItemOption(index, "-variable"); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemSelectedValue(int index, const char* value) { if (!this->IsCreated()) { return; } vtksys_stl::string value_safe(value ? value : ""); if (index < 0 || index >= this->GetNumberOfItems()) { return; } vtksys_stl::string type( this->Script("%s type %d", this->GetWidgetName(), index)); if (!strcmp("radiobutton", type.c_str())) { this->Script("%s entryconfigure %d -value {%s}", this->GetWidgetName(), index, value_safe.c_str()); } else if (!strcmp("checkbutton", type.c_str())) { this->Script("%s entryconfigure %d -onvalue {%s}", this->GetWidgetName(), index, value_safe.c_str()); } } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetItemSelectedValue(int index) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return NULL; } vtksys_stl::string type( this->Script("%s type %d", this->GetWidgetName(), index)); if (!strcmp("radiobutton", type.c_str())) { return this->GetItemOption(index, "-value"); } else if (!strcmp("checkbutton", type.c_str())) { return this->GetItemOption(index, "-onvalue"); } return NULL; } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemSelectedValueAsInt(int index, int value) { char buffer[50]; sprintf(buffer, "%d", value); this->SetItemSelectedValue(index, buffer); } //---------------------------------------------------------------------------- int vtkKWMenu::GetItemSelectedValueAsInt(int index) { return atoi(this->GetItemSelectedValue(index)); } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfItemWithSelectedValue( const char *value) { if (value) { vtksys_stl::string value_safe(value); int nb_of_items = this->GetNumberOfItems(); for(int i = 0; i < nb_of_items; i++) { const char *temp = this->GetItemSelectedValue(i); if (temp && !strcmp(temp, value_safe.c_str())) { return i; } } } return -1; } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfItemWithSelectedValueAsInt(int value) { char buffer[50]; sprintf(buffer, "%d", value); return this->GetIndexOfItemWithSelectedValue(buffer); } //---------------------------------------------------------------------------- int vtkKWMenu::SelectItemWithSelectedValue(const char *value) { int index = this->GetIndexOfItemWithSelectedValue(value); if (index >= 0) { this->SelectItem(index); } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::SelectItemWithSelectedValueAsInt( int value) { char buffer[50]; sprintf(buffer, "%d", value); return this->SelectItemWithSelectedValue(buffer); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemDeselectedValue(int index, const char* value) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } this->Script("%s entryconfigure %d -offvalue {%s}", this->GetWidgetName(), index, value ? value : ""); } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetItemDeselectedValue(int index) { return this->GetItemOption(index, "-offvalue"); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemDeselectedValueAsInt(int index, int value) { char buffer[50]; sprintf(buffer, "%d", value); this->SetItemDeselectedValue(index, buffer); } //---------------------------------------------------------------------------- int vtkKWMenu::GetItemDeselectedValueAsInt(int index) { return atoi(this->GetItemDeselectedValue(index)); } //---------------------------------------------------------------------------- int vtkKWMenu::AddRadioButton(const char *label) { return this->AddRadioButton(label, NULL, NULL); } //---------------------------------------------------------------------------- int vtkKWMenu::AddRadioButton(const char *label, vtkObject *object, const char *method) { int index = this->AddGeneric("radiobutton", label, NULL); if (index >= 0) { this->SetItemCommand(index, object, method); this->SetItemVariable(index, this, VTK_KW_MENU_RB_DEFAULT_GROUP); this->SetItemSelectedValue(index, label); this->InvokeEvent(vtkKWMenu::RadioButtonItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::AddRadioButtonImage(const char *imgname) { return this->AddRadioButtonImage(imgname, NULL, NULL); } //---------------------------------------------------------------------------- int vtkKWMenu::AddRadioButtonImage(const char *imgname, vtkObject *object, const char *method) { vtksys_stl::string str("-image "); str += imgname; str += " -selectimage "; str += imgname; // Uses the imgname as label, so that the help string can work. int index = this->AddGeneric("radiobutton", imgname, str.c_str()); if (index >= 0) { this->SetItemCommand(index, object, method); this->SetItemVariable(index, this, VTK_KW_MENU_RB_DEFAULT_GROUP); this->SetItemSelectedValue(index, imgname); this->InvokeEvent(vtkKWMenu::RadioButtonItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::InsertRadioButton(int index, const char *label) { return this->InsertRadioButton(index, label, NULL, NULL); } //---------------------------------------------------------------------------- int vtkKWMenu::InsertRadioButton(int index, const char *label, vtkObject *object, const char *method) { index = this->InsertGeneric(index, "radiobutton", label, NULL); if (index >= 0) { this->SetItemCommand(index, object, method); this->SetItemVariable(index, this, VTK_KW_MENU_RB_DEFAULT_GROUP); this->SetItemSelectedValue(index, label); this->InvokeEvent(vtkKWMenu::RadioButtonItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::InsertRadioButtonImage(int index, const char *imgname) { return this->InsertRadioButtonImage(index, imgname, NULL, NULL); } //---------------------------------------------------------------------------- int vtkKWMenu::InsertRadioButtonImage(int index, const char *imgname, vtkObject *object, const char *method) { vtksys_stl::string str("-image "); str += imgname; str += " -selectimage "; str += imgname; // Uses the imgname as label, so that the help string can work. index = this->InsertGeneric(index, "radiobutton", imgname, str.c_str()); if (index >= 0) { this->SetItemCommand(index, object, method); this->SetItemVariable(index, this, VTK_KW_MENU_RB_DEFAULT_GROUP); this->SetItemSelectedValue(index, imgname); this->InvokeEvent(vtkKWMenu::RadioButtonItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- void vtkKWMenu::PutItemInGroup(int index, int index_g) { this->SetItemGroupName( index, this->GetItemGroupName(index_g)); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemGroupName(int index, const char *group_name) { char *varname = this->CreateItemVariableName(this, group_name); this->SetItemVariable(index, varname); delete [] varname; } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetItemGroupName(int index) { return this->GetSuffixOutOfCreatedItemVariableName( this->GetItemVariable(index)); } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfItemWithVariableAndSelectedValue( const char *varname, const char *value) { if (varname && value) { vtksys_stl::string varname_safe(varname); vtksys_stl::string value_safe(value); int nb_of_items = this->GetNumberOfItems(); for(int i = 0; i < nb_of_items; i++) { const char *temp = this->GetItemVariable(i); if (temp && !strcmp(varname_safe.c_str(), temp)) { temp = this->GetItemSelectedValue(i); if (temp && !strcmp(temp, value_safe.c_str())) { return i; } } } } return -1; } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfItemWithVariableAndSelectedValueAsInt( const char *varname, int value) { char buffer[50]; sprintf(buffer, "%d", value); return this->GetIndexOfItemWithVariableAndSelectedValue(varname, buffer); } //---------------------------------------------------------------------------- int vtkKWMenu::SelectItemInGroupWithSelectedValue( const char *group_name, const char *value) { int index = -1; char *varname = this->CreateItemVariableName(this, group_name); if (varname) { index = this->GetIndexOfItemWithVariableAndSelectedValue( varname, value); if (index >= 0) { this->SelectItem(index); } delete [] varname; } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::SelectItemInGroupWithSelectedValueAsInt( const char *group_name, int value) { char buffer[50]; sprintf(buffer, "%d", value); return this->SelectItemInGroupWithSelectedValue( group_name, buffer); } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfSelectedItemInGroup(const char *group_name) { int index = -1; char *varname = this->CreateItemVariableName(this, group_name); const char *temp = this->GetItemVariableValue(varname); if (temp) { vtksys_stl::string varvalue(temp); index = this->GetIndexOfItemWithVariableAndSelectedValue( varname, varvalue.c_str()); } delete [] varname; return index; } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfSelectedItem() { vtksys_stl::string group( this->GetItemGroupName(this->GetNumberOfItems() - 1)); return this->GetIndexOfSelectedItemInGroup(group.c_str()); } //---------------------------------------------------------------------------- int vtkKWMenu::AddSeparator() { int index = this->AddGeneric("separator", NULL, NULL); this->InvokeEvent(vtkKWMenu::SeparatorItemAddedEvent, &index); return index; } //---------------------------------------------------------------------------- int vtkKWMenu::InsertSeparator(int index) { index = this->InsertGeneric(index, "separator", NULL, NULL); this->InvokeEvent(vtkKWMenu::SeparatorItemAddedEvent, &index); return index; } //---------------------------------------------------------------------------- int vtkKWMenu::AddCascade(const char *label, vtkKWMenu* menu) { int index = this->AddGeneric("cascade", label, NULL); if (index >= 0) { this->SetItemCascade(index, menu); this->InvokeEvent(vtkKWMenu::CascadeItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::InsertCascade(int index, const char *label, vtkKWMenu* menu) { index = this->InsertGeneric(index, "cascade", label, NULL); if (index >= 0) { this->SetItemCascade(index, menu); this->InvokeEvent(vtkKWMenu::CascadeItemAddedEvent, &index); } return index; } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfCascadeItem(vtkKWMenu *menu) { if (menu && menu->IsCreated()) { int i, nb_of_items = this->GetNumberOfItems(); for (i = 0; i < nb_of_items; i++) { const char *menu_opt = this->GetItemOption(i, "-menu"); if (menu_opt && !strcmp(menu_opt, menu->GetWidgetName())) { return i; } } } return -1; } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemCascade(int index, const char *menu_name) { if (!menu_name) { return; } vtksys_stl::string menu_name_safe(menu_name); const char *wname = this->GetWidgetName(); vtksys_ios::ostringstream str; str << wname << " entryconfigure " << index; // The cascade menu has to be a child // (i.e. the parent + '.' + at least a letter) // If not, clone it. int parent_length = (int)(strlen(wname)); int child_length = (int)(menu_name_safe.size()); if (child_length < (parent_length + 2) || strncmp(wname, menu_name_safe.c_str(), parent_length) || menu_name_safe[parent_length] != '.') { vtksys_ios::ostringstream clone_menu; vtksys_stl::string menu_name_safe_no_dots(menu_name_safe); vtksys::SystemTools::ReplaceString(menu_name_safe_no_dots, ".", "_"); clone_menu << wname << ".clone" << menu_name_safe_no_dots.c_str(); this->Script("catch { destroy %s } \n %s clone %s", clone_menu.str().c_str(), menu_name_safe.c_str(), clone_menu.str().c_str()); str << " -menu {" << clone_menu.str().c_str() << "}"; } else { str << " -menu {" << menu_name_safe.c_str() << "}"; } this->Script(str.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemCascade(int index, vtkKWMenu *menu) { if (menu) { this->SetItemCascade(index, menu->GetWidgetName()); const char *menu_opt = this->GetItemOption(index, "-menu"); if (menu_opt && *menu_opt && this->Internals) { this->Internals->CascadePool[menu_opt] = menu; } } } //---------------------------------------------------------------------------- vtkKWMenu* vtkKWMenu::GetItemCascade(int index) { const char *menu_opt = this->GetItemOption(index, "-menu"); if (menu_opt && *menu_opt && this->Internals) { vtkKWMenuInternals::CascadePoolType::iterator it = this->Internals->CascadePool.find(menu_opt); if (it != this->Internals->CascadePool.end()) { return it->second; } } return NULL; } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfItem(const char *label) { // This one is tricky // Calling 'index' only works if the parameter is not a number, or // not any of 'active', 'end', 'last', 'none' or '@number', which are // interpreted differently. Detect that, and loop over all entries if // required if (!label || !*label || !this->IsCreated()) { return -1; } // Check if it is a number const char *ptr = label; while (*ptr && *ptr > 0 && isdigit(*ptr)) { ++ptr; } // If it is not a number, and it is not of the special keyword, use 'index' if (*ptr && strcmp(label, "active") && strcmp(label, "end") && strcmp(label, "last") && strcmp(label, "none") && *label != '@') { char *clean_label = NULL; int underline_index, cleaned = this->GetLabelWithoutUnderline(label, &clean_label, &underline_index); const char *res = this->Script("catch {%s index {%s}} %s_getindex", this->GetWidgetName(), clean_label, this->GetTclName()); if (cleaned) { delete [] clean_label; } if (!res || atoi(res)) { return -1; } return atoi(this->Script("set %s_getindex", this->GetTclName())); } // OK, it is either a number or one of the special keywords, check manually int found = -1, nb_of_items = this->GetNumberOfItems(); for (int i = 0; i < nb_of_items; i++) { const char *label_opt = this->GetItemOption(i, "-label"); if (label_opt && *label_opt && !strcmp(label_opt, label)) { found = i; break; } } return found; } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfActiveItem(const char *widget_name) { if (widget_name) { const char *index_active = this->Script("%s index active", widget_name); if (strcmp(index_active, "none")) { return atoi(index_active); } } return -1; } //---------------------------------------------------------------------------- int vtkKWMenu::GetIndexOfCommandItem( vtkObject *object, const char *method) { if (object || method) { char *command = NULL; this->SetObjectMethodCommand(&command, object, method); int nb_of_items = this->GetNumberOfItems(); for (int i = 0; i < nb_of_items; i++) { const char *command_opt = this->GetItemCommand(i); if (command_opt && !strcmp(command_opt, command)) { delete [] command; return i; } } delete [] command; } return -1; } //---------------------------------------------------------------------------- int vtkKWMenu::HasItem(const char *label) { return this->GetIndexOfItem(label) >= 0 ? 1 : 0; } //---------------------------------------------------------------------------- int vtkKWMenu::SetItemLabel(int index, const char *label) { if (this->IsCreated() && index >= 0 && index < this->GetNumberOfItems()) { char *clean_label = NULL; int underline_index, cleaned = this->GetLabelWithoutUnderline(label, &clean_label, &underline_index); this->Script("%s entryconfigure %d -label {%s}", this->GetWidgetName(), index, clean_label); const char *help = this->GetItemHelpString(index); if(!help || !*help) { this->SetItemHelpString(index, clean_label); } if (cleaned) { this->SetItemUnderline(index, underline_index); delete [] clean_label; } return 1; } return 0; } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetItemLabel(int index) { return this->GetItemOption(index, "-label"); } //---------------------------------------------------------------------------- int vtkKWMenu::GetItemType(int index) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return vtkKWMenu::UnknownItemType; } const char *type = this->Script("%s type %d", this->GetWidgetName(), index); if (!type || !*type) { return vtkKWMenu::UnknownItemType; } if (!strcmp(type, "command")) { return vtkKWMenu::CommandItemType; } if (!strcmp(type, "checkbutton")) { return vtkKWMenu::CheckButtonItemType; } if (!strcmp(type, "radiobutton")) { return vtkKWMenu::CheckButtonItemType; } if (!strcmp(type, "separator")) { return vtkKWMenu::SeparatorItemType; } if (!strcmp(type, "cascade")) { return vtkKWMenu::CascadeItemType; } return vtkKWMenu::UnknownItemType; } //---------------------------------------------------------------------------- void vtkKWMenu::InvokeItem(int index) { this->Script("%s invoke %d", this->GetWidgetName(), index); } //---------------------------------------------------------------------------- void vtkKWMenu::DeleteItem(int index) { this->SetItemAccelerator(index, NULL); const char *wname = this->GetWidgetName(); this->Script( "catch {%s delete %d} ; set {%sHelpArray([%s entrycget %d -label])} {}", wname, index, wname, wname, index); } //---------------------------------------------------------------------------- void vtkKWMenu::DeleteAllItems() { int nb_of_items = this->GetNumberOfItems(); if (!nb_of_items) { return; } vtksys_ios::ostringstream tk_cmd; const char *wname = this->GetWidgetName(); for (int i = nb_of_items - 1; i >= 0; --i) { tk_cmd << "catch {" << wname << " delete " << i << "}" << endl << "set {" << wname << "HelpArray([" << wname << " entrycget " << i << " -label])} {}" << endl; } this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- int vtkKWMenu::GetNumberOfItems() { if (this->IsAlive()) { const char *end = this->Script("%s index end", this->GetWidgetName()); if (strcmp(end, "none")) { return atoi(end) + 1; } } return 0; } //---------------------------------------------------------------------------- int vtkKWMenu::GetItemState(int index) { return vtkKWOptions::GetStateFromTkOptionValue( this->GetItemOption(index, "-state")); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemState(int index, int state) { if (this->IsCreated()) { this->Script("catch {%s entryconfigure %d -state %s}", this->GetWidgetName(), index, vtkKWOptions::GetStateAsTkOptionValue(state)); } } void vtkKWMenu::SetItemStateToDisabled(int index) { this->SetItemState(index, vtkKWOptions::StateDisabled); }; void vtkKWMenu::SetItemStateToNormal(int index) { this->SetItemState(index, vtkKWOptions::StateNormal); }; //---------------------------------------------------------------------------- int vtkKWMenu::GetItemState(const char *label) { return this->GetItemState(this->GetIndexOfItem(label)); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemState(const char *label, int state) { this->SetItemState(this->GetIndexOfItem(label), state); } void vtkKWMenu::SetItemStateToDisabled(const char *label) { this->SetItemState(label, vtkKWOptions::StateDisabled); }; void vtkKWMenu::SetItemStateToNormal(const char *label) { this->SetItemState(label, vtkKWOptions::StateNormal); }; //---------------------------------------------------------------------------- void vtkKWMenu::SetState(int state) { int nb_of_items = this->GetNumberOfItems(); if (!nb_of_items) { return; } vtksys_ios::ostringstream tk_cmd; const char *wname = this->GetWidgetName(); const char *statestr = vtkKWOptions::GetStateAsTkOptionValue(state); for (int i = 0; i < nb_of_items; i++) { tk_cmd << "catch {" << wname << " entryconfigure " << i << " -state " << statestr << "}" << endl; } this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemImage(int index, const char *imgname) { vtksys_stl::string img(imgname ? imgname : ""); if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } // -image is not supported on MacOS Aqua system int tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); if (tcl_major < 8 || (tcl_major == 8 && (tcl_minor < 4 || (tcl_minor == 4 && tcl_patch_level <= 12)))) { vtksys_stl::string sys( vtkKWTkUtilities::GetWindowingSystem(this->GetApplication())); if (!sys.compare("aqua")) { return; } } this->Script("%s entryconfigure %d -image %s", this->GetWidgetName(), index, img.c_str()); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemSelectImage(int index, const char *imgname) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } this->Script("%s entryconfigure %d -selectimage %s", this->GetWidgetName(), index, imgname); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemImageToPredefinedIcon(int index, int icon_index) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } char buffer[1024]; sprintf(buffer, "%s.PredefinedIcon_%d", this->GetTclName(), icon_index); if (!vtkKWTkUtilities::FindPhoto(this->GetApplication(), buffer)) { vtkKWTkUtilities::UpdatePhotoFromPredefinedIcon( this->GetApplication(), buffer, icon_index); } this->SetItemImage(index, buffer); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemSelectImageToPredefinedIcon(int index, int icon_index) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } char buffer[1024]; sprintf(buffer, "%s.PredefinedIcon_%d", this->GetTclName(), icon_index); if (!vtkKWTkUtilities::FindPhoto(this->GetApplication(), buffer)) { vtkKWTkUtilities::UpdatePhotoFromPredefinedIcon( this->GetApplication(), buffer, icon_index); } this->SetItemSelectImage(index, buffer); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemImageToIcon(int index, vtkKWIcon *icon) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } char buffer[1024]; sprintf(buffer, "%s.Icon_%d_%p", this->GetTclName(), index, icon); vtkKWTkUtilities::UpdatePhotoFromIcon(this->GetApplication(), buffer, icon); this->SetItemImage(index, buffer); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemSelectImageToIcon(int index, vtkKWIcon *icon) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } char buffer[1024]; sprintf(buffer, "%s.Icon_%d_%p", this->GetTclName(), index, icon); vtkKWTkUtilities::UpdatePhotoFromIcon(this->GetApplication(), buffer, icon); this->SetItemSelectImage(index, buffer); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemCompoundMode(int index, int mode) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } this->Script("%s entryconfigure %d -compound %s", this->GetWidgetName(), index, vtkKWOptions::GetCompoundModeAsTkOptionValue(mode)); } void vtkKWMenu::SetItemCompoundModeToNone(int index) { this->SetItemCompoundMode(index, vtkKWOptions::CompoundModeNone); }; void vtkKWMenu::SetItemCompoundModeToLeft(int index) { this->SetItemCompoundMode(index, vtkKWOptions::CompoundModeLeft); }; void vtkKWMenu::SetItemCompoundModeToCenter(int index) { this->SetItemCompoundMode(index, vtkKWOptions::CompoundModeCenter); }; void vtkKWMenu::SetItemCompoundModeToRight(int index) { this->SetItemCompoundMode(index, vtkKWOptions::CompoundModeRight); }; void vtkKWMenu::SetItemCompoundModeToTop(int index) { this->SetItemCompoundMode(index, vtkKWOptions::CompoundModeTop); }; void vtkKWMenu::SetItemCompoundModeToBottom(int index) { this->SetItemCompoundMode(index, vtkKWOptions::CompoundModeBottom); }; //---------------------------------------------------------------------------- int vtkKWMenu::GetItemCompoundMode(int index) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return vtkKWOptions::CompoundModeUnknown; } return vtkKWOptions::GetCompoundModeFromTkOptionValue( this->GetItemOption(index, "-compound")); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemMarginVisibility(int index, int flag) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } this->Script("%s entryconfigure %d -hidemargin %d", this->GetWidgetName(), index, flag ? 0 : 1); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemIndicatorVisibility(int index, int flag) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } this->Script("%s entryconfigure %d -indicatoron %d", this->GetWidgetName(), index, flag ? 1 : 0); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemAccelerator(int index, const char *accelerator) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems() || !this->HasItemOption(index, "-accelerator")) { return; } // Install the new one this->Script("%s entryconfigure %d -accelerator {%s}", this->GetWidgetName(), index, accelerator ? accelerator : ""); } //---------------------------------------------------------------------------- void vtkKWMenu::SetBindingForItemAccelerator(int index, vtkKWWidget *widget) { const char *accelerator = this->GetItemOption(index, "-accelerator"); if (accelerator && *accelerator && widget) { char *keybinding = NULL; this->ConvertItemAcceleratorToKeyBinding(accelerator, &keybinding); if (keybinding && *keybinding) { const char *command = this->GetItemCommand(index); if (command && *command) { vtksys_stl::string command_safe(command); const char *label = this->GetItemLabel(index); vtksys_stl::string label_safe(label ? label : ""); widget->SetKeyBinding( keybinding, NULL, command_safe.c_str(), widget->GetClassName(), label_safe.c_str()); } } delete [] keybinding; } } //---------------------------------------------------------------------------- void vtkKWMenu::RemoveBindingForItemAccelerator(int index, vtkKWWidget *widget) { const char *accelerator = this->GetItemOption(index, "-accelerator"); if (accelerator && *accelerator && widget) { char *keybinding = NULL; this->ConvertItemAcceleratorToKeyBinding(accelerator, &keybinding); if (keybinding && *keybinding) { widget->RemoveKeyBinding(keybinding); } delete [] keybinding; } } //---------------------------------------------------------------------------- void vtkKWMenu::ConvertItemAcceleratorToKeyBinding( const char *accelerator, char **keybinding) { vtksys_stl::string keybinding_str; if (accelerator && *accelerator) { vtksys_stl::string accelerator_safe(accelerator); // Let's try to transform it into a binding vtksys::SystemTools::ReplaceString( accelerator_safe, "+", "-"); vtksys::SystemTools::ReplaceString( accelerator_safe, "Ctrl", "Control"); // Accelerator are usually specified as Ctrl-O, with the letter // in uppercase. Switch it to lowercase vtksys_stl::string::size_type accel_size = accelerator_safe.size(); vtksys_stl::string::size_type last_sep = accelerator_safe.rfind("-"); if((last_sep != vtksys_stl::string::npos && last_sep == accel_size - 2) || (last_sep == vtksys_stl::string::npos && accel_size == 1)) { accelerator_safe[accel_size - 1] = static_cast( tolower(accelerator_safe[accel_size - 1])); } keybinding_str = "<"; if(last_sep == vtksys_stl::string::npos) { keybinding_str += "Key-"; } keybinding_str += accelerator_safe; keybinding_str += ">"; } *keybinding = new char[keybinding_str.size() + 1]; strcpy(*keybinding, keybinding_str.c_str()); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemHelpString(int index, const char *help) { vtksys_stl::string help_safe(help ? help : ""); const char *label = this->GetItemLabel(index); if (!label || !*label) { return; } vtksys_stl::string label_safe(label); this->Script("set {%sHelpArray(%s)} {%s}", this->GetTclName(), label_safe.c_str(), help_safe.c_str()); } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetItemHelpString(int index) { const char *label = this->GetItemLabel(index); if (!label || !*label) { return NULL; } // This hack should be cleaned vtksys_stl::string label_safe(label); const char *tname = this->GetTclName(); return this->Script( "if [catch {set %sTemp $%sHelpArray(%s)} %sTemp ]" " { set %sTemp \"\"}; set %sTemp", tname, tname, label_safe.c_str(), tname, tname, tname); } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemUnderline(int index, int underline_index) { #ifndef __APPLE__ if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems() || underline_index < 0) { return; } this->Script("%s entryconfigure %d -underline %d", this->GetWidgetName(), index, underline_index); #else (void)index; (void)underline_index; #endif } //---------------------------------------------------------------------------- void vtkKWMenu::SetItemColumnBreak(int index, int flag) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return; } this->Script("%s entryconfigure %d -columnbreak %d", this->GetWidgetName(), index, flag); } //---------------------------------------------------------------------------- void vtkKWMenu::SetTearOff(int val) { if (val == this->TearOff) { return; } this->Modified(); this->TearOff = val; this->SetConfigurationOptionAsInt("-tearoff", this->TearOff); } //---------------------------------------------------------------------------- void vtkKWMenu::PopUp(int x, int y) { if (this->IsCreated()) { this->Script("tk_popup %s %d %d", this->GetWidgetName(), x, y); } } //---------------------------------------------------------------------------- void vtkKWMenu::SetEnabled(int e) { int old_enabled = this->GetEnabled(); this->Superclass::SetEnabled(e); // So even if the requested state was the same, propagate to the entries if (this->GetEnabled() == old_enabled) { this->UpdateEnableState(); } } //---------------------------------------------------------------------------- void vtkKWMenu::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->SetState(this->GetEnabled()); } //---------------------------------------------------------------------------- int vtkKWMenu::HasItemOption(int index, const char *option) { if (!this->IsCreated() || index < 0 || index >= this->GetNumberOfItems()) { return 0; } return !this->GetApplication()->EvaluateBooleanExpression( "catch {%s entrycget %d %s}", this->GetWidgetName(), index, option); } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetItemOption(int index, const char *option) { if (!this->HasItemOption(index, option)) { return NULL; } return this->Script("%s entrycget %d %s", this->GetWidgetName(), index, option); } //---------------------------------------------------------------------------- void vtkKWMenu::DisplayHelpCallback(const char* widget_name) { int index = this->GetIndexOfActiveItem(widget_name); if (index >= 0) { this->Internals->IndexOfLastActiveItem = index; } const char *help = this->GetItemHelpString(index); if(help) { vtksys_stl::string help_safe(help); vtkKWWindowBase *window = vtkKWWindowBase::SafeDownCast( this->GetParentTopLevel()); if (window) { window->SetStatusText(help_safe.c_str()); } } } //---------------------------------------------------------------------------- void vtkKWMenu::GetBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWMenu::GetBackgroundColor() { return this->GetConfigurationOptionAsColor("-background"); } //---------------------------------------------------------------------------- void vtkKWMenu::SetBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- void vtkKWMenu::GetForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWMenu::GetForegroundColor() { return this->GetConfigurationOptionAsColor("-foreground"); } //---------------------------------------------------------------------------- void vtkKWMenu::SetForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWMenu::GetActiveBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWMenu::GetActiveBackgroundColor() { return this->GetConfigurationOptionAsColor("-activebackground"); } //---------------------------------------------------------------------------- void vtkKWMenu::SetActiveBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWMenu::GetActiveForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-activeforeground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWMenu::GetActiveForegroundColor() { return this->GetConfigurationOptionAsColor("-activeforeground"); } //---------------------------------------------------------------------------- void vtkKWMenu::SetActiveForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-activeforeground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWMenu::SetBorderWidth(int width) { this->SetConfigurationOptionAsInt("-bd", width); } //---------------------------------------------------------------------------- int vtkKWMenu::GetBorderWidth() { return this->GetConfigurationOptionAsInt("-bd"); } //---------------------------------------------------------------------------- void vtkKWMenu::SetRelief(int relief) { this->SetConfigurationOption( "-relief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWMenu::SetReliefToRaised() { this->SetRelief(vtkKWOptions::ReliefRaised); } void vtkKWMenu::SetReliefToSunken() { this->SetRelief(vtkKWOptions::ReliefSunken); } void vtkKWMenu::SetReliefToFlat() { this->SetRelief(vtkKWOptions::ReliefFlat); } void vtkKWMenu::SetReliefToRidge() { this->SetRelief(vtkKWOptions::ReliefRidge); } void vtkKWMenu::SetReliefToSolid() { this->SetRelief(vtkKWOptions::ReliefSolid); } void vtkKWMenu::SetReliefToGroove() { this->SetRelief(vtkKWOptions::ReliefGroove); } //---------------------------------------------------------------------------- int vtkKWMenu::GetRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-relief")); } //---------------------------------------------------------------------------- void vtkKWMenu::SetFont(const char *font) { this->SetConfigurationOption("-font", font); } //---------------------------------------------------------------------------- const char* vtkKWMenu::GetFont() { return this->GetConfigurationOption("-font"); } //---------------------------------------------------------------------------- void vtkKWMenu::GetDisabledForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-disabledforeground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWMenu::GetDisabledForegroundColor() { return this->GetConfigurationOptionAsColor("-disabledforeground"); } //---------------------------------------------------------------------------- void vtkKWMenu::SetDisabledForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-disabledforeground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWMenu::GetSelectColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-selectcolor", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWMenu::GetSelectColor() { return this->GetConfigurationOptionAsColor("-selectcolor"); } //---------------------------------------------------------------------------- void vtkKWMenu::SetSelectColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-selectcolor", r, g, b); } //---------------------------------------------------------------------------- void vtkKWMenu::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "TearOff: " << this->GetTearOff() << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWFavoriteDirectoriesFrame.cxx0000644000175000017500000012151411354642044023532 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWFavoriteDirectoriesFrame.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWFavoriteDirectoriesFrame.h" #include "vtkKWApplication.h" #include "vtkDirectory.h" #include "vtkKWEntry.h" #include "vtkKWEntryWithLabel.h" #include "vtkKWFileBrowserUtilities.h" #include "vtkKWFrame.h" #include "vtkKWFrameWithScrollbar.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWMenu.h" #include "vtkKWMessageDialog.h" #include "vtkKWOptions.h" #include "vtkKWPushButton.h" #include "vtkKWRegistryHelper.h" #include "vtkKWSimpleEntryDialog.h" #include "vtkKWToolbar.h" #include "vtkObjectFactory.h" #include #include #include #define VTK_KW_DIR_REGISTRY_PATHNAME_KEYNAME_PATTERN "Path%02d" #define VTK_KW_DIR_REGISTRY_LABEL_KEYNAME_PATTERN "Path%02dLabel" #define VTK_KW_FAVORITE_DIR_KEY "KWFavoriteDirs" #define VTK_KW_DIR_REGISTRY_MAX_ENTRIES 30 #define VTK_KW_DIR_REGISTRY_MIN_ENTRIES 1 #ifdef _WIN32 #define VTK_KW_WIN32_REGIRSTRY_PLACES_BAR_KEY "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32\\PlacesBar" #define VTK_KW_WIN32_REGIRSTRY_NUM_PLACES 5 #include "vtkKWWin32RegistryHelper.h" #include "vtkWindows.h" //for GetLogicalDrives on Windows #include #include #endif //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWFavoriteDirectoriesFrame ); vtkCxxRevisionMacro(vtkKWFavoriteDirectoriesFrame, "$Revision: 1.27 $"); //---------------------------------------------------------------------------- class vtkKWFavoriteDirectoriesFrameInternals { public: vtkKWFavoriteDirectoriesFrameInternals() { // Some constants this->SelectedFavoriteDirectoryBackgroundColor[0] = 0.98; this->SelectedFavoriteDirectoryBackgroundColor[1] = 0.98; this->SelectedFavoriteDirectoryBackgroundColor[2] = 0.98; } class FavoriteDirectoryEntry { public: vtksys_stl::string Path; vtksys_stl::string Name; int IsEqual(const char *path, const char *) { return (path && !strcmp(path, this->Path.c_str())); } }; // Favorite directories list typedef vtksys_stl::list FavoriteDirectoryEntryContainer; typedef vtksys_stl::list::iterator FavoriteDirectoryEntryIterator; FavoriteDirectoryEntryContainer FavoriteDirectories; // Constants double SelectedFavoriteDirectoryBackgroundColor[3]; }; //---------------------------------------------------------------------------- vtkKWFavoriteDirectoriesFrame::vtkKWFavoriteDirectoriesFrame() { this->Internals = new vtkKWFavoriteDirectoriesFrameInternals; this->MaximumNumberOfFavoriteDirectoriesInRegistry = 15; this->Toolbar = vtkKWToolbar::New(); this->ContainerFrame = vtkKWFrameWithScrollbar::New(); this->AddFavoriteDirectoryButton = vtkKWPushButton::New(); this->ContextMenu = NULL; this->UseSystemDefaultPlaces = 0; this->AddFavoriteDirectoryCommand = NULL; this->FavoriteDirectorySelectedCommand = NULL; this->RegistryKey = NULL; } //---------------------------------------------------------------------------- vtkKWFavoriteDirectoriesFrame::~vtkKWFavoriteDirectoriesFrame() { if (this->RegistryKey) { delete [] this->RegistryKey; this->RegistryKey = NULL; } if (this->AddFavoriteDirectoryCommand) { delete [] this->AddFavoriteDirectoryCommand; this->AddFavoriteDirectoryCommand = NULL; } if (this->FavoriteDirectorySelectedCommand) { delete [] this->FavoriteDirectorySelectedCommand; this->FavoriteDirectorySelectedCommand = NULL; } if (this->ContextMenu) { this->ContextMenu->Delete(); this->ContextMenu = NULL; } this->AddFavoriteDirectoryButton->Delete(); this->Toolbar->Delete(); if (this->ContainerFrame) { if (this->ContainerFrame->GetFrame()) { this->ContainerFrame->GetFrame()->RemoveAllChildren(); } this->ContainerFrame->Delete(); this->ContainerFrame = NULL; } // Clear internals list this->ClearInternalList(); if (this->Internals) { delete this->Internals; } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::ClearInternalList() { if (this->Internals) { vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator end = this->Internals->FavoriteDirectories.end(); for (; it != end; ++it) { if (*it) { delete *it; } } this->Internals->FavoriteDirectories.clear(); } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Toolbar for Favorite Frame this->Toolbar->SetParent(this); this->Toolbar->Create(); this->Toolbar->SetWidth(20); // Favorite Add button for Toolbar this->AddFavoriteDirectoryButton->SetParent(this->Toolbar->GetFrame()); this->AddFavoriteDirectoryButton->Create(); this->AddFavoriteDirectoryButton->SetImageToPredefinedIcon( vtkKWIcon::IconFavorites); this->AddFavoriteDirectoryButton->SetBalloonHelpString( "Add to favorites"); this->AddFavoriteDirectoryButton->SetCommand( this, "AddFavoriteDirectoryCallback"); this->AddFavoriteDirectoryButton->SetConfigurationOptionAsInt( "-takefocus", 0); this->Toolbar->AddWidget(this->AddFavoriteDirectoryButton); this->Toolbar->SetToolbarAspectToFlat(); this->Toolbar->SetWidgetsAspectToFlat(); this->Script("pack %s -side top -anchor nw -fill x", this->Toolbar->GetWidgetName()); // Favorite button frame to hold favorite directory buttons. this->ContainerFrame->SetParent(this); this->ContainerFrame->SetHorizontalScrollbarVisibility(0); this->ContainerFrame->Create(); this->ContainerFrame->SetBackgroundColor(0.5, 0.5, 0.5); this->ContainerFrame->SetBorderWidth(1); this->ContainerFrame->SetReliefToSunken(); this->Script("pack %s -side top -fill both -expand true", this->ContainerFrame->GetWidgetName()); // Initialize if (!this->GetRegistryKey()) { this->SetRegistryKey(VTK_KW_FAVORITE_DIR_KEY); } // Retrieve the favorite directories from registry this->RestoreFavoriteDirectoriesFromRegistry(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::Update() { this->UpdateEnableState(); } //---------------------------------------------------------------------------- int vtkKWFavoriteDirectoriesFrame::HasFavoriteDirectoryWithName( const char* name) { if (name && *name) { vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator end = this->Internals->FavoriteDirectories.end(); for(; it!=end; it++) { if (strcmp(((*it)->Name).c_str(), name) == 0) { return 1; } } } return 0; } //---------------------------------------------------------------------------- const char* vtkKWFavoriteDirectoriesFrame::GetNameOfFavoriteDirectory( const char *path) { if (path && *path) { vtksys_stl::string dirpath = path; vtksys::SystemTools::ConvertToUnixSlashes(dirpath); vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator end = this->Internals->FavoriteDirectories.end(); vtksys_stl::string currPath; for(; it!=end; it++) { currPath = (*it)->Path; vtksys::SystemTools::ConvertToUnixSlashes(currPath); if (KWFileBrowser_ComparePath(currPath.c_str(), dirpath.c_str())) { return (*it)->Name.c_str(); } } } return NULL; } //---------------------------------------------------------------------------- vtkKWPushButton* vtkKWFavoriteDirectoriesFrame::GetButtonOfFavoriteDirectoryWithName( const char* name) { if (name && *name) { int nb_children = this->ContainerFrame->GetFrame()->GetNumberOfChildren(); for (int index = 0; index < nb_children; index++) { vtkKWPushButton *child = vtkKWPushButton::SafeDownCast( this->ContainerFrame->GetFrame()->GetNthChild(index)); if (child && child->IsPacked() && strcmp(child->GetText(), name) == 0) { return child; } } } return NULL; } //---------------------------------------------------------------------------- int vtkKWFavoriteDirectoriesFrame::HasFavoriteDirectory(const char* path) { return this->GetNameOfFavoriteDirectory(path) ? 1 : 0; } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::SetFavoriteDirectoryPath( const char* oldpath, const char* newpath) { vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); for(; it != this->Internals->FavoriteDirectories.end(); it++) { if (strcmp((*it)->Path.c_str(), oldpath) == 0) { vtkKWPushButton *child = this->GetButtonOfFavoriteDirectoryWithName((*it)->Name.c_str()); (*it)->Path = newpath; this->UpdateFavoriteDirectoryButton( child, (*it)->Path.c_str(), (*it)->Name.c_str()); this->WriteFavoriteDirectoriesToRegistry(); break; } } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::SetFavoriteDirectoryName( const char* oldname, const char* newname) { vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); for(; it != this->Internals->FavoriteDirectories.end(); it++) { if (strcmp((*it)->Name.c_str(), oldname) == 0) { vtkKWPushButton *child = this->GetButtonOfFavoriteDirectoryWithName((*it)->Name.c_str()); (*it)->Name = newname; this->UpdateFavoriteDirectoryButton( child, (*it)->Path.c_str(), (*it)->Name.c_str()); this->WriteFavoriteDirectoriesToRegistry(); break; } } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::SelectFavoriteDirectory( const char* path) { if (path && *path && !this->IsFavoriteDirectorySelected(path)) { this->ClearFavoriteDirectorySelection(); vtksys_stl::string path_str(path); const char *name_of_fav = this->GetNameOfFavoriteDirectory(path_str.c_str()); if (name_of_fav) { vtksys_stl::string name_of_fav_str(name_of_fav); this->SelectFavoriteDirectoryWithName(name_of_fav_str.c_str()); this->InvokeFavoriteDirectorySelectedCommand( path_str.c_str(), name_of_fav_str.c_str()); } } } //---------------------------------------------------------------------------- int vtkKWFavoriteDirectoriesFrame::IsFavoriteDirectorySelected( const char* path) { if (path && *path) { vtksys_stl::string path_str(path); const char *name_of_fav = this->GetNameOfFavoriteDirectory(path_str.c_str()); if (name_of_fav) { vtksys_stl::string name_of_fav_str(name_of_fav); const char *sel_path = this->GetSelectedFavoriteDirectory(); if (sel_path && *sel_path) { vtksys_stl::string sel_path_str(sel_path); const char *sel_name_of_fav = this->GetNameOfFavoriteDirectory(sel_path_str.c_str()); if (sel_name_of_fav) { vtksys_stl::string sel_name_of_fav_str(sel_name_of_fav); if (!strcmp(sel_name_of_fav_str.c_str(), name_of_fav_str.c_str())) { return 1; } } } } } return 0; } //---------------------------------------------------------------------------- const char* vtkKWFavoriteDirectoriesFrame::GetSelectedFavoriteDirectory() { int nb_children = this->ContainerFrame->GetFrame()->GetNumberOfChildren(); for (int index = 0; index < nb_children; index++) { vtkKWPushButton *child = vtkKWPushButton::SafeDownCast( this->ContainerFrame->GetFrame()->GetNthChild(index)); if (child && child->IsPacked() && child->GetRelief() == vtkKWOptions::ReliefRidge) { return this->GetSelectedFavoriteDirectoryWithName(child->GetText()); } } return NULL; } //---------------------------------------------------------------------------- const char* vtkKWFavoriteDirectoriesFrame:: GetSelectedFavoriteDirectoryWithName(const char* name) { if (name && *name) { vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); for(; it != this->Internals->FavoriteDirectories.end(); it++) { if (strcmp((*it)->Name.c_str(), name) == 0) { return KWFileBrowser_GetUnixPath((*it)->Path.c_str()); } } } return NULL; } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::SelectFavoriteDirectoryWithName( const char* name) { this->ClearFavoriteDirectorySelection(); vtkKWPushButton *child = this->GetButtonOfFavoriteDirectoryWithName(name); if (child) { child->SetReliefToRidge(); child->SetBackgroundColor( this->Internals->SelectedFavoriteDirectoryBackgroundColor); } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::ClearFavoriteDirectorySelection() { if (!this->ContainerFrame->IsCreated()) { return; } int nb_children = this->ContainerFrame->GetFrame()->GetNumberOfChildren(); for(int index = 0; index < nb_children; index++) { vtkKWPushButton *child = vtkKWPushButton::SafeDownCast( this->ContainerFrame->GetFrame()->GetNthChild(index)); if (child) { child->SetReliefToFlat(); child->SetBackgroundColor( this->ContainerFrame->GetFrame()->GetBackgroundColor()); } } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::AddFavoriteDirectory( const char *path, const char *name) { if (!path || !*path || !name || !*name) { return; } vtksys_stl::string dirpath = path; vtkDirectory *dir = vtkDirectory::New(); if (!dir->Open(dirpath.c_str())) { dir->Delete(); return; } dir->Delete(); this->AddFavoriteDirectoryToFrame(dirpath.c_str(), name); if (this->Internals->FavoriteDirectories.size() > (size_t)this->MaximumNumberOfFavoriteDirectoriesInRegistry) { this->PruneFavoriteDirectoriesInRegistry(); } this->WriteFavoriteDirectoriesToRegistry(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::AddFavoriteDirectoryToFrame( const char *path, const char* name) { if (this->HasFavoriteDirectory(path)) { return; } // Add selected folder to favorite directory list vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntry *direntry = new vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntry; direntry->Path = path; direntry->Name = name; this->Internals->FavoriteDirectories.push_front(direntry); vtkKWPushButton *dirbutton = vtkKWPushButton::New(); dirbutton->SetParent(this->ContainerFrame->GetFrame()); dirbutton->Create(); dirbutton->SetReliefToFlat(); dirbutton->SetOverReliefToRaised(); dirbutton->SetCompoundModeToTop(); dirbutton->SetImageToPredefinedIcon(vtkKWIcon::IconFolder32); dirbutton->SetBackgroundColor( this->ContainerFrame->GetBackgroundColor()); dirbutton->SetActiveBackgroundColor( this->ContainerFrame->GetBackgroundColor()); dirbutton->SetConfigurationOptionAsInt("-takefocus", 0); this->UpdateFavoriteDirectoryButton(dirbutton, path, name); int nb_children = this->ContainerFrame->GetFrame()->GetNumberOfPackedChildren(); if (nb_children > 0) { this->Script("pack %s -side top -fill x -pady 2 -before %s", dirbutton->GetWidgetName(), this->ContainerFrame->GetFrame()->GetNthChild(nb_children-1)->GetWidgetName()); } else { this->Script("pack %s -side top -fill x -pady 2", dirbutton->GetWidgetName()); } dirbutton->Delete(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::UpdateFavoriteDirectoryButton( vtkKWPushButton *button, const char *path, const char* name) { if (!name || !path) { return; } button->SetText(name); button->SetBalloonHelpString(path); char cmd[256]; sprintf(cmd, "SelectFavoriteDirectoryCallback \"%s\" \"%s\"", vtksys::SystemTools::EscapeChars( path, KWFileBrowser_ESCAPE_CHARS).c_str(), name); button->SetCommand(this, cmd); char rightclickcmd[256]; sprintf(rightclickcmd, "PopupFavoriteDirectoryCallback \"%s\" %%X %%Y", vtksys::SystemTools::EscapeChars( path, KWFileBrowser_ESCAPE_CHARS).c_str()); button->AddBinding("", this, rightclickcmd); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::PopulateContextMenu( vtkKWMenu *menu, const char *path) { char command[256]; vtksys_stl::string buttonpath = path; #ifdef _WIN32 // Explore to open native explorer file sprintf(command, "ExploreFavoriteDirectoryCallback \"%s\"", vtksys::SystemTools::EscapeChars( buttonpath.c_str(), KWFileBrowser_ESCAPE_CHARS).c_str()); menu->AddCommand("Explore", this, command); #endif // Rename file sprintf(command, "RenameFavoriteDirectoryCallback \"%s\"", vtksys::SystemTools::EscapeChars( buttonpath.c_str(), KWFileBrowser_ESCAPE_CHARS).c_str()); menu->AddCommand("Rename", this, command); // Delete file sprintf(command, "RemoveFavoriteDirectoryCallback \"%s\"", vtksys::SystemTools::EscapeChars( buttonpath.c_str(), KWFileBrowser_ESCAPE_CHARS).c_str()); menu->AddCommand("Delete", this, command); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::AddFavoriteDirectoryCallback() { this->InvokeAddFavoriteDirectoryCommand(); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::SelectFavoriteDirectoryCallback( const char* path, const char* name) { this->SelectFavoriteDirectory(path); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::SetAddFavoriteDirectoryCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->AddFavoriteDirectoryCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::InvokeAddFavoriteDirectoryCommand() { if (this->AddFavoriteDirectoryCommand && *this->AddFavoriteDirectoryCommand) { this->Script("%s", this->AddFavoriteDirectoryCommand); } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::SetFavoriteDirectorySelectedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->FavoriteDirectorySelectedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::InvokeFavoriteDirectorySelectedCommand( const char* path, const char* name) { if (this->FavoriteDirectorySelectedCommand && *this->FavoriteDirectorySelectedCommand) { this->Script("%s \"%s\" \"%s\"", this->FavoriteDirectorySelectedCommand, vtksys::SystemTools::EscapeChars(KWFileBrowser_GetUnixPath(path), KWFileBrowser_ESCAPE_CHARS).c_str(), vtksys::SystemTools::EscapeChars(name, KWFileBrowser_ESCAPE_CHARS).c_str()); } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::PopupFavoriteDirectoryCallback( const char* path, int x, int y) { if (!path || !(*path)) { return; } if (!this->ContextMenu) { this->ContextMenu = vtkKWMenu::New(); } if (!this->ContextMenu->IsCreated()) { this->ContextMenu->SetParent(this); this->ContextMenu->Create(); } this->ContextMenu->DeleteAllItems(); this->PopulateContextMenu(this->ContextMenu, path); if (this->ContextMenu->GetNumberOfItems()) { this->ContextMenu->PopUp(x, y); } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::RemoveFavoriteDirectoryCallback( const char* path) { if (!path || !(*path)) { return; } vtksys_stl::string path_str = path; vtksys_stl::string message( "Are you sure you want to delete this favorite directory? \n"); message.append(path_str.c_str()); // Prompt the user for confirmation if (vtkKWMessageDialog::PopupYesNo( this->GetApplication(), this, ks_("Favorite Directories|Title|Delete favorites"), k_(message.c_str()), vtkKWMessageDialog::WarningIcon | vtkKWMessageDialog::InvokeAtPointer)) { this->RemoveFavoriteDirectory(path_str.c_str()); this->Update(); } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::ExploreFavoriteDirectoryCallback( const char* path) { #ifdef _WIN32 if (path && *path && vtksys::SystemTools::FileIsDirectory(path)) { this->GetApplication()->OpenLink(path); } #endif } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::RenameFavoriteDirectoryCallback( const char* path) { if (!path || !(*path)) { return; } const char *name = this->GetNameOfFavoriteDirectory(path); if (!name) { vtkKWMessageDialog::PopupMessage( this->GetApplication(), this, ks_("Favorite Directories|Title|Error!"), "No valid directory found!", vtkKWMessageDialog::ErrorIcon | vtkKWMessageDialog::InvokeAtPointer); return; } // Prompt the user for the new name of the favorite vtkKWSimpleEntryDialog *dlg = vtkKWSimpleEntryDialog::New(); dlg->SetParent(this); dlg->SetMasterWindow(this->GetParentTopLevel()); dlg->SetDisplayPositionToPointer(); dlg->SetTitle( ks_("Favorite Directories|Dialog|Title|Rename favorite")); dlg->SetStyleToOkCancel(); dlg->Create(); dlg->GetEntry()->GetLabel()->SetText( ks_("Favorite Directories|Dialog|Favorite name:")); dlg->GetEntry()->GetWidget()->SetValue(name); dlg->SetText( ks_("Favorite Directories|Dialog|Enter a new favorite name:")); int ok = dlg->Invoke(); vtksys_stl::string newname = dlg->GetEntry()->GetWidget()->GetValue(); dlg->Delete(); if (ok) { if (newname.empty() || strcmp(newname.c_str(), "") == 0 || strcmp(newname.c_str(), ".") == 0 || strcmp(newname.c_str(), "..") == 0) { vtkKWMessageDialog::PopupMessage( this->GetApplication(), this, ks_("Favorite Directories|Title|Error!"), "Please enter a valid favorite name!", vtkKWMessageDialog::ErrorIcon | vtkKWMessageDialog::InvokeAtPointer); return; } } else { return; } // Do we have that name already? if (this->HasFavoriteDirectoryWithName(newname.c_str())) { vtkKWMessageDialog::PopupMessage( this->GetApplication(), this, ks_("Favorite Directories|Title|Error!"), "This favorite name is already used!", vtkKWMessageDialog::ErrorIcon | vtkKWMessageDialog::InvokeAtPointer); return; } // Rename this->SetFavoriteDirectoryName(name, newname.c_str()); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::RemoveFavoriteDirectory( const char *path) { vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); for(; it != this->Internals->FavoriteDirectories.end(); it++) { if (strcmp((*it)->Path.c_str(), path) == 0) { vtkKWPushButton *child = this->GetButtonOfFavoriteDirectoryWithName((*it)->Name.c_str()); if (child) { child->Unpack(); child->SetParent(NULL); } delete *it; this->Internals->FavoriteDirectories.erase(it); this->WriteFavoriteDirectoriesToRegistry(); break; } } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::WriteFavoriteDirectoriesToRegistry() { if(this->GetApplication() && this->GetApplication()->GetRegistryLevel() <=0) { return; } this->WriteFavoriteDirectoriesToRegistry( this->RegistryKey, this->MaximumNumberOfFavoriteDirectoriesInRegistry); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::WriteFavoriteDirectoriesToRegistry( const char *reg_key, int max_nb) { if (!this->GetApplication()) { vtkErrorMacro("Error! Application not set!"); return; } if (!reg_key) { vtkErrorMacro("Error! Can not write to empty key in registry!"); return; } char dirname_key[20], label_key[20]; vtkKWRegistryHelper* registryhelper = vtkKWRegistryHelper::New(); if (!registryhelper->Open(VTK_KW_FAVORITE_TOPLEVEL, reg_key, 1)) { vtkErrorMacro( "Error! Failed to open the registry key for writing!"); registryhelper->Delete(); return; } // Store all favorite dir entries to registry vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator end = this->Internals->FavoriteDirectories.end(); int count = 0; for (; it != end && count < max_nb; ++it) { if (*it) { sprintf(dirname_key, VTK_KW_DIR_REGISTRY_PATHNAME_KEYNAME_PATTERN, count); sprintf(label_key, VTK_KW_DIR_REGISTRY_LABEL_KEYNAME_PATTERN, count); registryhelper->SetValue(reg_key, dirname_key, (*it)->Path.c_str()); if ((*it)->Name.size()) { registryhelper->SetValue(reg_key, label_key, (*it)->Name.c_str()); } ++count; } } // As a convenience, remove all others for (; count < VTK_KW_DIR_REGISTRY_MAX_ENTRIES; count++) { sprintf(dirname_key, VTK_KW_DIR_REGISTRY_PATHNAME_KEYNAME_PATTERN, count); sprintf(label_key, VTK_KW_DIR_REGISTRY_LABEL_KEYNAME_PATTERN, count); registryhelper->DeleteValue(reg_key, dirname_key); registryhelper->DeleteValue(reg_key, label_key); } registryhelper->Close(); registryhelper->Delete(); #ifdef _WIN32 this->WriteFavoriteDirectoriesToSystemRegistry(); #endif } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::RestoreFavoriteDirectoriesFromRegistry() { if(this->GetApplication() && this->GetApplication()->GetRegistryLevel() <=0) { return; } // Remove all if (this->ContainerFrame && this->ContainerFrame->GetFrame()) { this->ContainerFrame->GetFrame()->UnpackChildren(); this->ContainerFrame->GetFrame()->RemoveAllChildren(); } this->ClearInternalList(); // We will always have the directory, set by "HOME" // evironment variable, as favorite vtksys_stl::string dir; if(vtksys::SystemTools::GetEnv("HOME", dir)) { if(vtksys::SystemTools::FileIsDirectory(dir.c_str())) { this->AddFavoriteDirectoryToFrame(dir.c_str(), vtksys::SystemTools::GetFilenameName(dir).c_str()); } } // Restore the set of registry keys created by users this->RestoreFavoriteDirectoriesFromUserRegistry( this->RegistryKey, this->MaximumNumberOfFavoriteDirectoriesInRegistry); #ifdef _WIN32 // Load system favorites this->RestoreFavoriteDirectoriesFromSystemRegistry(); #endif } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::RestoreFavoriteDirectoriesFromUserRegistry( const char *reg_key, int max_nb) { if (!this->GetApplication()) { vtkErrorMacro("Error! Application not set!"); return; } if (!reg_key) { vtkErrorMacro("Error! Can not load from empty key in registry!"); return; } vtkKWRegistryHelper* registryhelper = vtkKWRegistryHelper::New(); if (!registryhelper->Open(VTK_KW_FAVORITE_TOPLEVEL, reg_key, 0)) { registryhelper->Delete(); return; } char dirname_key[20], label_key[20]; char dirname[1024], label[1024]; int i; for (i = VTK_KW_DIR_REGISTRY_MAX_ENTRIES - 1; i >= 0 && max_nb; i--) { sprintf(dirname_key, VTK_KW_DIR_REGISTRY_PATHNAME_KEYNAME_PATTERN, i); sprintf(label_key, VTK_KW_DIR_REGISTRY_LABEL_KEYNAME_PATTERN, i); if (registryhelper->ReadValue(reg_key, dirname_key, dirname) && strlen(dirname) >= 1) { if (vtksys::SystemTools::FileIsDirectory(dirname)) { if (!registryhelper->ReadValue(reg_key, label_key, label)) { *label = '\0'; } this->AddFavoriteDirectoryToFrame(dirname, label); max_nb--; } } } registryhelper->Close(); registryhelper->Delete(); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::RestoreFavoriteDirectoriesFromSystemRegistry() { #ifdef _WIN32 if(!this->UseSystemDefaultPlaces) { return; } char buff[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; vtksys_stl::string placekey = VTK_KW_WIN32_REGIRSTRY_PLACES_BAR_KEY; bool userdefined = false; char place[10]; vtksys_stl::string value, placename; // If this system key exists, read from it and // add them to the favorite dir entries. vtkKWWin32RegistryHelper* registryhelper = vtkKWWin32RegistryHelper::New(); if (registryhelper && registryhelper->OpenInternal(placekey.c_str(), 0)) { // Windows only allow five entries under this key for(int i = VTK_KW_WIN32_REGIRSTRY_NUM_PLACES - 1; i >= 0; i--) { sprintf(place, "Place%d", i); placename = place; if (registryhelper->ReadValueInternal(placename.c_str(), buff)) { value = buff; if (vtksys::SystemTools::FileIsDirectory(value.c_str())) { this->AddFavoriteDirectoryToFrame( value.c_str(), vtksys::SystemTools::GetFilenameName(value).c_str()); userdefined = true; } else { int csidl = -1; sscanf(value.c_str(), "%d", &csidl); if (csidl >= 0 && csidl <= 0x003d) { if (this->AddSpecialFavoriteFolder(csidl)) { userdefined=true; } } //end if csidl }//end else } //end if readvalue }//end for registryhelper->Close(); }//end if open registryhelper->Delete(); #endif } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::WriteFavoriteDirectoriesToSystemRegistry() { #ifdef _WIN32 if(!this->UseSystemDefaultPlaces) { return; } int num_dir = (int)this->Internals->FavoriteDirectories.size(); if (num_dir <= 0) { return; } char buff[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; vtksys_stl::string placekey = VTK_KW_WIN32_REGIRSTRY_PLACES_BAR_KEY; bool userdefined = false; char place[10]; vtksys_stl::string value, placename; // If this system key exists, read from it and // add them to the favorite dir entries. vtkKWWin32RegistryHelper* registryhelper = vtkKWWin32RegistryHelper::New(); if (registryhelper && registryhelper->OpenInternal(placekey.c_str(), 1)) { vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator end = this->Internals->FavoriteDirectories.end(); int found=0; for(int i=0; it != end && i < VTK_KW_WIN32_REGIRSTRY_NUM_PLACES; i++, it++) { found = 0; for(int j = 0; j < VTK_KW_WIN32_REGIRSTRY_NUM_PLACES; j++) { sprintf(place, "Place%d", j); placename = place; if (registryhelper->ReadValueInternal( placename.c_str(), buff)) { value = buff; if (vtksys::SystemTools::FileIsDirectory(value.c_str())) { if (it != end && KWFileBrowser_ComparePath( value.c_str(), (*it)->Path.c_str())) { found=true; break; } } else { int csidl = -1; sscanf(value.c_str(), "%d", &csidl); if (csidl >=0 && csidl <=0x003d) { // Get the path to these folders LPITEMIDLIST pidl; HRESULT hr = SHGetSpecialFolderLocation( NULL, csidl, &pidl); if (SUCCEEDED(hr)) { // Convert the item ID list's binary // representation into a file system path char szPath[_MAX_PATH]; if (SHGetPathFromIDList(pidl, szPath)) { if (it != end && KWFileBrowser_ComparePath( szPath, (*it)->Path.c_str())) { found=true; break; } } }//end if succeed } //end if csidl }//end else } //end if readvalue }//end for j sprintf(place, "Place%d", i); placename=place; if (found) { if (vtksys::SystemTools::FileIsDirectory(value.c_str())) { // Only Windows path should be used here; otherwise, // other applications, such as Notepad, won't recognize the path registryhelper->SetValueInternal(placename.c_str(), vtksys::SystemTools::ConvertToOutputPath( value.c_str()).c_str()); } else { int csidl = -1; sscanf(value.c_str(), "%d", &csidl); if (csidl >=0 && csidl <=0x003d) { registryhelper->SetValueInternal(placename.c_str(), &csidl); } } } else { // Only Windows path should be used here; otherwise, // other applications, such as Notepad, won't recognize the path registryhelper->SetValueInternal(placename.c_str(), vtksys::SystemTools::ConvertToOutputPath( (*it)->Path.c_str()).c_str()); } }//end for it, i registryhelper->Close(); }//end if open registryhelper->Delete(); #endif } //---------------------------------------------------------------------------- int vtkKWFavoriteDirectoriesFrame::AddSpecialFavoriteFolder(int csidl) { #ifdef _WIN32 vtksys_stl::string name; switch (csidl) { case CSIDL_DESKTOP: name = "Desktop"; break; case CSIDL_PERSONAL: name = "My Documents"; break; case CSIDL_DRIVES: name = "My Computer"; break; case CSIDL_FAVORITES: name = "My Favorites"; break; default: name = "My Folder"; break; } // end switch // Get the path to these folders LPITEMIDLIST pidl; HRESULT hr = SHGetSpecialFolderLocation(NULL, csidl, &pidl); if (SUCCEEDED(hr)) { // Convert the item ID list's binary // representation into a file system path char szPath[_MAX_PATH]; if (SHGetPathFromIDList(pidl, szPath)) { this->AddFavoriteDirectoryToFrame(szPath, name.c_str()); return 1; } }//end if succeed #endif return 0; } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->ContainerFrame); this->PropagateEnableState(this->Toolbar); this->PropagateEnableState(this->AddFavoriteDirectoryButton); if (this->ContainerFrame->GetFrame()) { int nb_children = this->ContainerFrame->GetFrame()->GetNumberOfChildren(); for(int index = 0; index < nb_children; index++) { this->ContainerFrame->GetFrame()->GetNthChild(index)->SetEnabled( this->GetEnabled()); } } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::PruneFavoriteDirectoriesInRegistry() { while (this->Internals->FavoriteDirectories.size() > (size_t)this->MaximumNumberOfFavoriteDirectoriesInRegistry) { this->RemoveFavoriteDirectory( this->Internals->FavoriteDirectories.back()->Path.c_str()); this->Internals->FavoriteDirectories.pop_back(); } } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::SetMaximumNumberOfFavoriteDirectoriesInRegistry( int maxnum) { if (maxnum < VTK_KW_DIR_REGISTRY_MIN_ENTRIES) { maxnum = VTK_KW_DIR_REGISTRY_MIN_ENTRIES; } else if (maxnum > VTK_KW_DIR_REGISTRY_MAX_ENTRIES) { maxnum = VTK_KW_DIR_REGISTRY_MAX_ENTRIES; } if (this->MaximumNumberOfFavoriteDirectoriesInRegistry == maxnum) { return; } this->MaximumNumberOfFavoriteDirectoriesInRegistry = maxnum; this->PruneFavoriteDirectoriesInRegistry(); this->WriteFavoriteDirectoriesToRegistry(); this->Update(); this->Modified(); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::GetContainerFrameBackgroundColor( double *r, double *g, double *b) { this->ContainerFrame->GetBackgroundColor(r, g, b); } //---------------------------------------------------------------------------- double* vtkKWFavoriteDirectoriesFrame::GetContainerFrameBackgroundColor() { return this->ContainerFrame->GetBackgroundColor(); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::SetContainerFrameBackgroundColor( double r, double g, double b) { this->ContainerFrame->SetBackgroundColor(r, g, b); } //---------------------------------------------------------------------------- void vtkKWFavoriteDirectoriesFrame::PrintSelf( ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "AddFavoriteDirectoryCommand: " << (this->AddFavoriteDirectoryCommand?this->AddFavoriteDirectoryCommand:"none") << endl; os << indent << "FavoriteDirectorySelectedCommand: " << (this->FavoriteDirectorySelectedCommand?this->FavoriteDirectorySelectedCommand:"none") << endl; os << indent << "RegistryKey: " << (this->RegistryKey?this->RegistryKey:"none") << endl; os << indent << "MaximumNumberOfFavoriteDirectoriesInRegistry: " << this->MaximumNumberOfFavoriteDirectoriesInRegistry << endl; vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator it = this->Internals->FavoriteDirectories.begin(); vtkKWFavoriteDirectoriesFrameInternals::FavoriteDirectoryEntryIterator end = this->Internals->FavoriteDirectories.end(); for (; it != end; ++it) { os << indent << "FavoriteDirectory: " << ((*it)->Path.c_str()?(*it)->Path.c_str():"none") << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWMenuButton.h0000644000175000017500000003111711171737553020336 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWMenuButton.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWMenuButton - an option menu widget // .SECTION Description // A widget that looks like a button but when pressed provides a list // of options that the user can select. #ifndef __vtkKWMenuButton_h #define __vtkKWMenuButton_h #include "vtkKWCoreWidget.h" class vtkKWMenu; class vtkKWIcon; class vtkKWMenuButtonInternals; class KWWidgets_EXPORT vtkKWMenuButton : public vtkKWCoreWidget { public: static vtkKWMenuButton* New(); vtkTypeRevisionMacro(vtkKWMenuButton,vtkKWCoreWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the current entry of this option menu. // This can be an image name if any entry in the menu uses an image // instead of a label. virtual const char *GetValue(); virtual void SetValue(const char *name); // Description: // Set/Get the current entry to the previous or next entry. // and call the corresponding callback if any. // WARNING: this does not support multiple menu levels (i.e. cascade) virtual void NextValue(); virtual void PreviousValue(); // Description: // Get the menu object vtkGetObjectMacro(Menu, vtkKWMenu); // Description // Set the indicator On/Off. To be called after creation. virtual void SetIndicatorVisibility(int ind); virtual int GetIndicatorVisibility(); vtkBooleanMacro(IndicatorVisibility, int); // Description: // Set the button width (in chars if text, in pixels if image). virtual void SetWidth(int width); virtual int GetWidth(); // Description: // Set/Get the maximum width *in characters* of the option menu label. // This does not modify the internal value, this is only meant for display // purposes: the option menu button can therefore be automatically // shrinked, while the menu associated to it will display all entries // correctly. // Set width to 0 (default) to prevent auto-cropping. virtual void SetMaximumLabelWidth(int); vtkGetMacro(MaximumLabelWidth, int); // Description: // Adjust the label width automatically to fit in the menu button. // This does not modify the internal value, this is only meant for display // purposes: the option menu button can therefore be automatically // shrinked, while the menu associated to it will display all entries // correctly. Overrides MaximumLabelWidth. virtual void SetAdjustLabelWidthToWidgetSize(int); vtkGetMacro(AdjustLabelWidthToWidgetSize, int); vtkBooleanMacro(AdjustLabelWidthToWidgetSize, int); // Description: // Set/Get the background color of the widget. virtual void GetBackgroundColor(double *r, double *g, double *b); virtual double* GetBackgroundColor(); virtual void SetBackgroundColor(double r, double g, double b); virtual void SetBackgroundColor(double rgb[3]) { this->SetBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget. virtual void GetForegroundColor(double *r, double *g, double *b); virtual double* GetForegroundColor(); virtual void SetForegroundColor(double r, double g, double b); virtual void SetForegroundColor(double rgb[3]) { this->SetForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the highlight thickness, a non-negative value indicating the // width of the highlight rectangle to draw around the outside of the // widget when it has the input focus. virtual void SetHighlightThickness(int); virtual int GetHighlightThickness(); // Description: // Set/Get the active background color of the widget. An element // (a widget or portion of a widget) is active if the mouse cursor is // positioned over the element and pressing a mouse button will cause some // action to occur. virtual void GetActiveBackgroundColor(double *r, double *g, double *b); virtual double* GetActiveBackgroundColor(); virtual void SetActiveBackgroundColor(double r, double g, double b); virtual void SetActiveBackgroundColor(double rgb[3]) { this->SetActiveBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the active foreground color of the widget. An element // (a widget or portion of a widget) is active if the mouse cursor is // positioned over the element and pressing a mouse button will cause some // action to occur. virtual void GetActiveForegroundColor(double *r, double *g, double *b); virtual double* GetActiveForegroundColor(); virtual void SetActiveForegroundColor(double r, double g, double b); virtual void SetActiveForegroundColor(double rgb[3]) { this->SetActiveForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget when it is disabled. virtual void GetDisabledForegroundColor(double *r, double *g, double *b); virtual double* GetDisabledForegroundColor(); virtual void SetDisabledForegroundColor(double r, double g, double b); virtual void SetDisabledForegroundColor(double rgb[3]) { this->SetDisabledForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the border width, a non-negative value indicating the width of // the 3-D border to draw around the outside of the widget (if such a border // is being drawn; the Relief option typically determines this). virtual void SetBorderWidth(int); virtual int GetBorderWidth(); // Description: // Set/Get the 3-D effect desired for the widget. // The value indicates how the interior of the widget should appear // relative to its exterior. // Valid constants can be found in vtkKWOptions::ReliefType. virtual void SetRelief(int); virtual int GetRelief(); virtual void SetReliefToRaised(); virtual void SetReliefToSunken(); virtual void SetReliefToFlat(); virtual void SetReliefToRidge(); virtual void SetReliefToSolid(); virtual void SetReliefToGroove(); // Description: // Specifies the font to use when drawing text inside the widget. // You can use predefined font names (e.g. 'system'), or you can specify // a set of font attributes with a platform-independent name, for example, // 'times 12 bold'. In this example, the font is specified with a three // element list: the first element is the font family, the second is the // size, the third is a list of style parameters (normal, bold, roman, // italic, underline, overstrike). Example: 'times 12 {bold italic}'. // The Times, Courier and Helvetica font families are guaranteed to exist // and will be matched to the corresponding (closest) font on your system. // If you are familiar with the X font names specification, you can also // describe the font that way (say, '*times-medium-r-*-*-12*'). virtual void SetFont(const char *font); virtual const char* GetFont(); // Description: // Set/Get the padding that will be applied around each widget (in pixels). // Specifies a non-negative value indicating how much extra space to request // for the widget in the X and Y-direction. When computing how large a // window it needs, the widget will add this amount to the width it would // normally need (as determined by the width of the things displayed // in the widget); if the geometry manager can satisfy this request, the // widget will end up with extra internal space around what it displays // inside. virtual void SetPadX(int); virtual int GetPadX(); virtual void SetPadY(int); virtual int GetPadY(); // Description: // Set/Get the anchoring. // Specifies how the information in a widget (e.g. text or a bitmap) is to // be displayed in the widget. // Valid constants can be found in vtkKWOptions::AnchorType. virtual void SetAnchor(int); virtual int GetAnchor(); virtual void SetAnchorToNorth(); virtual void SetAnchorToNorthEast(); virtual void SetAnchorToEast(); virtual void SetAnchorToSouthEast(); virtual void SetAnchorToSouth(); virtual void SetAnchorToSouthWest(); virtual void SetAnchorToWest(); virtual void SetAnchorToNorthWest(); virtual void SetAnchorToCenter(); // Description: // Specifies an image to display in the widget. Typically, if the image // is specified then it overrides other options that specify a bitmap or // textual value to display in the widget. Invoke vtkKWWidget's // SetConfigurationOption("-image", imagename) to use a specific // pre-existing Tk image, or call one of the following functions. // The SetImageToPredefinedIcon method accepts an index to one of the // predefined icon listed in vtkKWIcon. // The SetImageToPixels method sets the image using pixel data. It expects // a pointer to the pixels and the structure of the image, i.e. its width, // height and the pixel_size (how many bytes per pixel, say 3 for RGB, or // 1 for grayscale). If buffer_length = 0, it is computed automatically // from the previous parameters. If it is not, it will most likely indicate // that the buffer has been encoded using base64 and/or zlib. // If pixel_size > 3 (i.e. RGBA), the image is blend the with background // color of the widget. // Check the SetCompoundMode method if you want to display both the // image and the label at the same time. virtual void SetImageToIcon(vtkKWIcon *icon); virtual void SetImageToPredefinedIcon(int icon_index); virtual void SetImageToPixels( const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length = 0); // Description: // Specifies if the widget should display text and bitmaps/images at the // same time, and if so, where the bitmap/image should be placed relative // to the text. // Valid constants can be found in vtkKWOptions::CompoundModeType. // The (default) value CompoundModeNone specifies that the bitmap or image // should (if defined) be displayed instead of the text. virtual void SetCompoundMode(int); virtual int GetCompoundMode(); virtual void SetCompoundModeToNone(); virtual void SetCompoundModeToLeft(); virtual void SetCompoundModeToCenter(); virtual void SetCompoundModeToRight(); virtual void SetCompoundModeToTop(); virtual void SetCompoundModeToBottom(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void TracedVariableChangedCallback( const char *, const char *, const char *); virtual void ConfigureCallback(); virtual void UpdateMenuButtonLabelCallback(); // Description: // Add all the default observers needed by that object, or remove // all the observers that were added through AddCallbackCommandObserver. // Subclasses can override these methods to add/remove their own default // observers, but should call the superclass too. virtual void AddCallbackCommandObservers(); virtual void RemoveCallbackCommandObservers(); protected: vtkKWMenuButton(); ~vtkKWMenuButton(); // Description: // Create the widget. virtual void CreateWidget(); vtkGetStringMacro(CurrentValue); vtkSetStringMacro(CurrentValue); char *CurrentValue; vtkKWMenu *Menu; int MaximumLabelWidth; int AdjustLabelWidthToWidgetSize; virtual void UpdateMenuButtonLabel(); virtual const char* UpdateMenuButtonLabelFromMenu( const char *varname, const char *value, vtkKWMenu *menu); virtual void ScheduleUpdateMenuButtonLabel(); // Description: // Processes the events that are passed through CallbackCommand (or others). // Subclasses can oberride this method to process their own events, but // should call the superclass too. virtual void ProcessCallbackCommandEvents( vtkObject *caller, unsigned long event, void *calldata); // Description: // Update bindings virtual void UpdateBindings(); // PIMPL Encapsulation for STL containers //BTX vtkKWMenuButtonInternals *Internals; //ETX private: vtkKWMenuButton(const vtkKWMenuButton&); // Not implemented void operator=(const vtkKWMenuButton&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWStateMachineTransition.cxx0000644000175000017500000001127410526410341023215 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWStateMachineTransition.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWStateMachineTransition.h" #include "vtkObjectFactory.h" #include "vtkCommand.h" #include "vtkKWStateMachineState.h" #include "vtkKWStateMachineInput.h" vtkCxxSetObjectMacro(vtkKWStateMachineTransition,OriginState,vtkKWStateMachineState); vtkCxxSetObjectMacro(vtkKWStateMachineTransition,Input,vtkKWStateMachineInput); vtkCxxSetObjectMacro(vtkKWStateMachineTransition,DestinationState,vtkKWStateMachineState); //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWStateMachineTransition); vtkCxxRevisionMacro(vtkKWStateMachineTransition, "$Revision: 1.2 $"); vtkIdType vtkKWStateMachineTransition::IdCounter = 1; //---------------------------------------------------------------------------- vtkKWStateMachineTransition::vtkKWStateMachineTransition() { this->Id = vtkKWStateMachineTransition::IdCounter++; this->OriginState = NULL; this->Input = NULL; this->DestinationState = NULL; this->EndCommand = NULL; this->StartCommand = NULL; } //---------------------------------------------------------------------------- vtkKWStateMachineTransition::~vtkKWStateMachineTransition() { this->SetOriginState(NULL); this->SetInput(NULL); this->SetDestinationState(NULL); if (this->EndCommand) { delete [] this->EndCommand; this->EndCommand = NULL; } if (this->StartCommand) { delete [] this->StartCommand; this->StartCommand = NULL; } } //---------------------------------------------------------------------------- int vtkKWStateMachineTransition::IsComplete() { return (this->OriginState && this->Input && this->DestinationState); } //---------------------------------------------------------------------------- void vtkKWStateMachineTransition::End() { this->InvokeEndCommand(); this->InvokeEvent(vtkKWStateMachineTransition::EndEvent); } //---------------------------------------------------------------------------- void vtkKWStateMachineTransition::SetEndCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->EndCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWStateMachineTransition::InvokeEndCommand() { if (this->HasEndCommand()) { this->InvokeObjectMethodCommand(this->EndCommand); } } //---------------------------------------------------------------------------- int vtkKWStateMachineTransition::HasEndCommand() { return this->EndCommand && *this->EndCommand; } //---------------------------------------------------------------------------- void vtkKWStateMachineTransition::Start() { this->InvokeStartCommand(); this->InvokeEvent(vtkKWStateMachineTransition::StartEvent); } //---------------------------------------------------------------------------- void vtkKWStateMachineTransition::SetStartCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->StartCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWStateMachineTransition::InvokeStartCommand() { if (this->HasStartCommand()) { this->InvokeObjectMethodCommand(this->StartCommand); } } //---------------------------------------------------------------------------- int vtkKWStateMachineTransition::HasStartCommand() { return this->StartCommand && *this->StartCommand; } //---------------------------------------------------------------------------- void vtkKWStateMachineTransition::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Id: " << this->Id << endl; os << indent << "OriginState: "; if (this->OriginState) { os << endl; this->OriginState->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "Input: "; if (this->Input) { os << endl; this->Input->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "DestinationState: "; if (this->DestinationState) { os << endl; this->DestinationState->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWTopLevel.cxx0000644000175000017500000004743511417616120020342 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTopLevel.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWTopLevel.h" #include "vtkKWOptions.h" #include "vtkKWApplication.h" #include "vtkObjectFactory.h" #include "vtkKWTkUtilities.h" #include "vtkKWMenu.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWTopLevel ); vtkCxxRevisionMacro(vtkKWTopLevel, "$Revision: 1.39 $"); //---------------------------------------------------------------------------- vtkKWTopLevel::vtkKWTopLevel() { this->Title = NULL; this->WindowClass = NULL; this->MasterWindow = NULL; this->Menu = NULL; this->HideDecoration = 0; this->Modal = 0; this->DisplayPosition = vtkKWTopLevel::DisplayPositionMasterWindowCenterFirst; } //---------------------------------------------------------------------------- vtkKWTopLevel::~vtkKWTopLevel() { this->SetTitle(NULL); this->SetMasterWindow(NULL); this->SetWindowClass(0); if (this->Menu) { this->Menu->Delete(); this->Menu = NULL; } } //---------------------------------------------------------------------------- vtkKWApplication* vtkKWTopLevel::GetApplication() { if (!this->Superclass::GetApplication() && this->MasterWindow && this->MasterWindow->GetApplication()) { this->SetApplication(this->MasterWindow->GetApplication()); } return this->Superclass::GetApplication(); } //---------------------------------------------------------------------------- void vtkKWTopLevel::CreateWidget() { vtksys_stl::string opts; if (this->GetWindowClass()) { opts += " -class {"; opts += this->GetWindowClass(); opts += "} "; } else if (this->GetMasterWindow()) { vtkKWTopLevel *master_top = vtkKWTopLevel::SafeDownCast(this->GetMasterWindow()); if (master_top && master_top->GetWindowClass()) { opts += " -class {"; opts += master_top->GetWindowClass(); opts += "} "; } } opts += " -highlightthickness 0"; // Call the superclass to set the appropriate flags then create manually if (!vtkKWWidget::CreateSpecificTkWidget(this, "toplevel", opts.c_str())) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } this->PostCreate(); } //---------------------------------------------------------------------------- void vtkKWTopLevel::PostCreate() { if (!this->IsCreated()) { return; } this->Withdraw(); this->Script("wm protocol %s WM_DELETE_WINDOW {%s Withdraw}", this->GetWidgetName(), this->GetTclName()); const char *title = this->GetTitle(); if (!title && this->GetApplication()) { title = this->GetApplication()->GetPrettyName(); } if (title) { this->Script("wm title %s {%s}", this->GetWidgetName(), title); } if (this->GetMasterWindow()) { if (!this->GetMasterWindow()->IsCreated()) { vtkWarningMacro("The toplevel is assigned a MasterWindow that has not " "been created yet. Ignoring master/slave request."); } else { this->Script("wm transient %s [winfo toplevel %s]", this->GetWidgetName(), this->GetMasterWindow()->GetWidgetName()); } } if (this->HideDecoration) { this->Script("wm overrideredirect %s %d", this->GetWidgetName(), this->HideDecoration ? 1 : 0); } } //---------------------------------------------------------------------------- void vtkKWTopLevel::Display() { if (!this->IsCreated()) { return; } // Position the toplevel. int x, y; if (this->DisplayPosition != vtkKWTopLevel::DisplayPositionDefault && this->ComputeDisplayPosition(&x, &y)) { this->SetPosition(x, y); } this->DeIconify(); this->Raise(); this->Focus(); this->InvokeEvent(vtkKWTopLevel::DisplayEvent); if (this->GetMasterWindow()) { this->GetMasterWindow()->InvokeEvent( vtkKWTopLevel::SlaveDisplayEvent, this); } if (this->Modal) { this->Grab(); } } //---------------------------------------------------------------------------- void vtkKWTopLevel::Withdraw() { vtkKWTkUtilities::WithdrawTopLevel(this); if (this->Modal) { this->ReleaseGrab(); } this->InvokeEvent(vtkKWTopLevel::WithdrawEvent); if (this->GetMasterWindow()) { this->GetMasterWindow()->InvokeEvent( vtkKWTopLevel::SlaveWithdrawEvent, this); } } //---------------------------------------------------------------------------- int vtkKWTopLevel::ComputeDisplayPosition(int *x, int *y) { if (!this->IsCreated() || this->DisplayPosition == vtkKWTopLevel::DisplayPositionDefault) { return 0; } int display_pos = this->DisplayPosition; int width = this->GetWidth(); int reqwidth = this->GetRequestedWidth(); int height = this->GetHeight(); int reqheight = this->GetRequestedHeight(); int minwidth, minheight; this->GetMinimumSize(&minwidth, &minheight); // If we requested to center only the first time we display the toplevel, // check its current size. If it is down to a single pixel width or height, // then it has never been mapped, and we can try to center it. Otherwise just // use the current position if (display_pos == vtkKWTopLevel::DisplayPositionMasterWindowCenterFirst || display_pos == vtkKWTopLevel::DisplayPositionScreenCenterFirst) { if (width == 1 || height == 1 || reqwidth == 1 || reqheight == 1) { if (display_pos == vtkKWTopLevel::DisplayPositionMasterWindowCenterFirst) { display_pos = vtkKWTopLevel::DisplayPositionMasterWindowCenter; } else { display_pos = vtkKWTopLevel::DisplayPositionScreenCenter; } } else { return 0; } } // Try to use the proper width if (reqwidth > width) { width = reqwidth; } if (minwidth > width) { width = minwidth; } if (reqheight > height) { height = reqheight; } if (minheight > height) { height = minheight; } // Display at pointer, or center if (display_pos == vtkKWTopLevel::DisplayPositionPointer) { vtkKWTkUtilities::GetMousePointerCoordinates( this->GetApplication()->GetMainInterp(), ".", x, y); } else if (display_pos == vtkKWTopLevel::DisplayPositionMasterWindowCenter || display_pos == vtkKWTopLevel::DisplayPositionScreenCenter) { vtkKWTopLevel *master = vtkKWTopLevel::SafeDownCast(this->GetMasterWindow()); if (master && display_pos == vtkKWTopLevel::DisplayPositionMasterWindowCenter) { int master_width, master_height; master->GetSize(&master_width, &master_height); master->GetPosition(x, y); *x += master_width / 2; *y += master_height / 2; } else { int screen_width, screen_height; vtkKWTkUtilities::GetScreenSize( this->GetApplication()->GetMainInterp(), ".", &screen_width, &screen_height); *x = screen_width / 2; *y = screen_height / 2; } } // That call is not necessary since it has been added to both // GetRequestedWidth and GetRequestedHeight. If it is removed from them // for performance reasons (I doubt it), uncomment that line. // The call to 'update' enable the geometry manager to compute the layout // of the widget behind the scene, and return proper values. // this->Script("update idletasks"); if (*x > width / 2) { *x -= width / 2; } if (*y > height / 2) { *y -= height / 2; } return 1; } //---------------------------------------------------------------------------- void vtkKWTopLevel::DeIconify() { if (this->IsCreated()) { this->Script("wm deiconify %s", this->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetMasterWindow(vtkKWWidget* win) { if (this->MasterWindow == win || win == this) { return; } this->MasterWindow = win; this->Modified(); if (!this->GetApplication() && win->GetApplication()) { this->SetApplication(win->GetApplication()); } if (this->IsCreated() && this->GetMasterWindow()) { if (!this->GetMasterWindow()->IsCreated()) { vtkWarningMacro("The toplevel is assigned a MasterWindow that has not " "been created yet. Ignoring master/slave request."); } else { this->Script("wm transient %s [winfo toplevel %s]", this->GetWidgetName(), this->GetMasterWindow()->GetWidgetName()); } } } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetHideDecoration(int arg) { if (this->HideDecoration == arg) { return; } this->HideDecoration = arg; this->Modified(); if (this->IsCreated()) { this->Script("wm overrideredirect %s %d", this->GetWidgetName(), this->HideDecoration ? 1 : 0); } } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetTitle(const char* _arg) { if (this->Title == NULL && _arg == NULL) { return; } if (this->Title && _arg && (!strcmp(this->Title, _arg))) { return; } if (this->Title) { delete [] this->Title; } if (_arg) { this->Title = new char[strlen(_arg) + 1]; strcpy(this->Title, _arg); } else { this->Title = NULL; } this->Modified(); if (this->Title && this->IsCreated()) { this->Script("wm title %s {%s}", this->GetWidgetName(), this->Title); } } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetTitleToTopLevelTitle(vtkKWWidget *widget) { if (widget && widget->IsCreated()) { this->SetTitle( this->Script("wm title [winfo toplevel %s]", widget->GetWidgetName())); } } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetWidth() { if (!this->IsCreated()) { return 0; } return atoi(this->Script("winfo width %s", this->GetWidgetName())); } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetHeight() { if (!this->IsCreated()) { return 0; } return atoi(this->Script("winfo height %s", this->GetWidgetName())); } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetRequestedWidth() { if (!this->IsCreated()) { return 0; } // The call to 'update' enable the geometry manager to compute the layout // of the widget behind the scene, and return proper values. this->GetApplication()->ProcessIdleTasks(); return atoi(this->Script("winfo reqwidth %s", this->GetWidgetName())); } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetRequestedHeight() { if (!this->IsCreated()) { return 0; } // The call to 'update' enable the geometry manager to compute the layout // of the widget behind the scene, and return proper values. this->GetApplication()->ProcessIdleTasks(); return atoi(this->Script("winfo reqheight %s", this->GetWidgetName())); } //---------------------------------------------------------------------------- int vtkKWTopLevel::SetPosition(int x, int y) { if (!this->IsCreated()) { return 0; } this->Script("wm geometry %s +%d+%d", this->GetWidgetName(), x, y); return 1; } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetPosition(int *x, int *y) { return vtkKWTkUtilities::GetGeometry(this, NULL, NULL, x, y); } //---------------------------------------------------------------------------- int vtkKWTopLevel::SetSize(int w, int h) { if (!this->IsCreated()) { return 0; } this->Script("wm geometry %s %dx%d", this->GetWidgetName(), w, h); return 1; } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetSize(int *w, int *h) { if (!w || !h) { return 0; } *w = this->GetWidth(); *h = this->GetHeight(); return 1; //return vtkKWTkUtilities::GetGeometry(this, w, h, NULL, NULL); } //---------------------------------------------------------------------------- int vtkKWTopLevel::SetMinimumSize(int w, int h) { if (!this->IsCreated()) { return 0; } this->Script("wm minsize %s %d %d", this->GetWidgetName(), w, h); return 1; } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetMinimumSize(int *w, int *h) { if (!this->IsCreated() || !w || !h) { return 0; } return sscanf(this->Script("wm minsize %s", this->GetWidgetName()), "%d %d", w, h) == 2 ? 1 : 0; } //---------------------------------------------------------------------------- int vtkKWTopLevel::SetGeometry(const char *geometry) { if (!this->IsCreated() || !geometry) { return 0; } this->Script("wm geometry %s {%s}", this->GetWidgetName(), geometry); return 1; } //---------------------------------------------------------------------------- const char* vtkKWTopLevel::GetGeometry() { if (!this->IsCreated()) { return NULL; } return this->Script("wm geometry %s", this->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWTopLevel::Maximize() { #if defined(_WIN32) if (this->IsCreated()) { this->Script("wm state %s zoomed", this->GetWidgetName()); } #endif } //---------------------------------------------------------------------------- vtkKWMenu *vtkKWTopLevel::GetMenu() { if (!this->Menu) { this->Menu = vtkKWMenu::New(); } if (!this->Menu->IsCreated() && this->IsCreated()) { this->Menu->SetParent(this); this->Menu->SetTearOff(0); this->Menu->Create(); this->SetConfigurationOption("-menu", this->Menu->GetWidgetName()); } return this->Menu; } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetDeleteWindowProtocolCommand( vtkObject *object, const char *method) { if (this->IsCreated()) { char *command = NULL; this->SetObjectMethodCommand(&command, object, method); this->Script("wm protocol %s WM_DELETE_WINDOW {%s}", this->GetWidgetName(), command); delete [] command; } } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetIconName(const char *name) { if (this->IsCreated()) { this->Script("wm iconname %s {%s}", this->GetWidgetName(), name ? name : NULL); } } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetResizable(int w, int h) { if (this->IsCreated()) { this->Script("wm resizable %s %d %d", this->GetWidgetName(), w, h); } } //---------------------------------------------------------------------------- void vtkKWTopLevel::GetBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWTopLevel::GetBackgroundColor() { return this->GetConfigurationOptionAsColor("-background"); } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetHighlightThickness(int width) { this->SetConfigurationOptionAsInt("-highlightthickness", width); } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetHighlightThickness() { return this->GetConfigurationOptionAsInt("-highlightthickness"); } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetBorderWidth(int width) { this->SetConfigurationOptionAsInt("-bd", width); } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetBorderWidth() { return this->GetConfigurationOptionAsInt("-bd"); } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetRelief(int relief) { this->SetConfigurationOption( "-relief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWTopLevel::SetReliefToRaised() { this->SetRelief(vtkKWOptions::ReliefRaised); }; void vtkKWTopLevel::SetReliefToSunken() { this->SetRelief(vtkKWOptions::ReliefSunken); }; void vtkKWTopLevel::SetReliefToFlat() { this->SetRelief(vtkKWOptions::ReliefFlat); }; void vtkKWTopLevel::SetReliefToRidge() { this->SetRelief(vtkKWOptions::ReliefRidge); }; void vtkKWTopLevel::SetReliefToSolid() { this->SetRelief(vtkKWOptions::ReliefSolid); }; void vtkKWTopLevel::SetReliefToGroove() { this->SetRelief(vtkKWOptions::ReliefGroove); }; //---------------------------------------------------------------------------- int vtkKWTopLevel::GetRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-relief")); } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetPadX(int arg) { this->SetConfigurationOptionAsInt("-padx", arg); } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetPadX() { return this->GetConfigurationOptionAsInt("-padx"); } //---------------------------------------------------------------------------- void vtkKWTopLevel::SetPadY(int arg) { this->SetConfigurationOptionAsInt("-pady", arg); } //---------------------------------------------------------------------------- int vtkKWTopLevel::GetPadY() { return this->GetConfigurationOptionAsInt("-pady"); } //---------------------------------------------------------------------------- vtkKWTclInteractor* vtkKWTopLevel::GetTclInteractor() { if (this->GetApplication()) { return this->GetApplication()->GetTclInteractor(); } return NULL; } //---------------------------------------------------------------------------- void vtkKWTopLevel::DisplayTclInteractor() { if (this->GetApplication()) { this->GetApplication()->DisplayTclInteractor(this); } } //---------------------------------------------------------------------------- void vtkKWTopLevel::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->Menu); } //---------------------------------------------------------------------------- void vtkKWTopLevel::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Title: "; if (this->GetTitle()) { os << this->GetTitle() << endl; } else { os << "None" << endl; } os << indent << "WindowClass: "; if (this->GetWindowClass()) { os << this->GetWindowClass() << endl; } else { os << "None" << endl; } os << indent << "MasterWindow: " << this->GetMasterWindow() << endl; os << indent << "HideDecoration: " << (this->HideDecoration ? "On" : "Off" ) << endl; os << indent << "Modal: " << this->GetModal() << endl; os << indent << "DisplayPosition: " << this->GetDisplayPosition() << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWWidgetsVersion.cxx0000644000175000017500000000173310600762077021561 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetsVersion.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWWidgetsVersion.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkCxxRevisionMacro(vtkKWWidgetsVersion, "$Revision: 1.2 $"); vtkStandardNewMacro(vtkKWWidgetsVersion); //---------------------------------------------------------------------------- void vtkKWWidgetsVersion::PrintSelf( ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWLogDialog.h0000644000175000017500000000427411101670531020064 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWLogDialog.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWLogDialog - a log dialog. // .SECTION Description // This widget can be used to display various types of records/events in the // form of a multicolumn log. Each record is timestamped automatically, and /// the interface allow the user to sort the list by time, type, or // description. // This dialog is a standalone toplevel, but uses a vtkKWLogWidget internally. // The vtkKWLogWidget class can be inserted in any widget hierarchy. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWLogWidget #ifndef __vtkKWLogDialog_h #define __vtkKWLogDialog_h #include "vtkKWMessageDialog.h" class vtkKWApplication; class vtkKWLogWidget; class vtkKWPushButton; class KWWidgets_EXPORT vtkKWLogDialog : public vtkKWMessageDialog { public: static vtkKWLogDialog* New(); vtkTypeRevisionMacro(vtkKWLogDialog,vtkKWMessageDialog); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the internal log widget so that its API will be exposed directly vtkGetObjectMacro(LogWidget, vtkKWLogWidget); protected: vtkKWLogDialog(); ~vtkKWLogDialog(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Member variables vtkKWLogWidget* LogWidget; private: vtkKWLogDialog(const vtkKWLogDialog&); // Not implemented void operator=(const vtkKWLogDialog&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWDirectoryExplorer.h0000644000175000017500000004104710732267117021722 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWDirectoryExplorer.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWDirectoryExplorer - a widget for exploring directories // .SECTION Description // This class contains a hierarchy structure to explore directories of a // file systems. It also includes a toolbar, which offers Back/Forward // browsing of visited directories and functions to Create/Delete directories. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWFileBrowserDialog vtkKWFileBrowserWidget #ifndef __vtkKWDirectoryExplorer_h #define __vtkKWDirectoryExplorer_h #include "vtkKWCompositeWidget.h" class vtkKWIcon; class vtkKWToolbar; class vtkKWPushButton; class vtkKWTreeWithScrollbars; class vtkKWPushButtonWithMenu; class vtkKWMenu; class vtkKWDirectoryExplorerInternals; class KWWidgets_EXPORT vtkKWDirectoryExplorer : public vtkKWCompositeWidget { public: static vtkKWDirectoryExplorer* New(); vtkTypeRevisionMacro(vtkKWDirectoryExplorer,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Open a directory given the full path. // Return 1 on success, 0 otherwise virtual int OpenDirectory(const char* path); // Description: // Rename a directory name, given the current and new name // of the directory. // Return 1 on success, 0 otherwise virtual int RenameDirectory(const char* currentname, const char* newname); // Description: // Remove/delete a directory. // Return 1 on success, 0 otherwise virtual int DeleteDirectory(const char* dirname); // Description: // Set/Get the selection mode // Valid constants can be found in vtkKWOptions::SelectionModeType. virtual void SetSelectionMode(int); virtual void SetSelectionModeToSingle(); virtual void SetSelectionModeToMultiple(); // Description: // Return if one (or more) directory is/are selected. virtual int HasSelection(); // Description: // Get/Set the selected director(ies). virtual const char *GetSelectedDirectory() {return GetNthSelectedDirectory(0);} virtual int GetNumberOfSelectedDirectories(); virtual const char *GetNthSelectedDirectory(int i); virtual void SelectDirectory(const char*); virtual void DeselectDirectory(const char*); virtual void ClearSelection(); // Description: // Set/Get the maximum number of directories that will be stored // in back/forward history list. virtual void SetMaximumNumberOfDirectoriesInHistory(int); vtkGetMacro(MaximumNumberOfDirectoriesInHistory, int); // Description: // Set/Get the selection background and foreground colors. virtual void GetSelectionBackgroundColor(double *r, double *g, double *b); virtual double* GetSelectionBackgroundColor(); virtual void SetSelectionBackgroundColor(double r, double g, double b); virtual void SetSelectionBackgroundColor(double rgb[3]) { this->SetSelectionBackgroundColor(rgb[0], rgb[1], rgb[2]); }; virtual void GetSelectionForegroundColor(double *r, double *g, double *b); virtual double* GetSelectionForegroundColor(); virtual void SetSelectionForegroundColor(double r, double g, double b); virtual void SetSelectionForegroundColor(double rgb[3]) { this->SetSelectionForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Convenience method to Set/Get the width (in chars) and height (in lines) // of the tree widget. virtual void SetTreeWidth(int); virtual int GetTreeWidth(); virtual void SetTreeHeight(int); virtual int GetTreeHeight(); // Description: // Convenience method to Set/Get the tree background color. virtual void GetTreeBackgroundColor(double *r, double *g, double *b); virtual double* GetTreeBackgroundColor(); virtual void SetTreeBackgroundColor(double r, double g, double b); virtual void SetTreeBackgroundColor(double rgb[3]) { this->SetTreeBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Specifies selection-related commands to associate with the widget. // DirectorySelected is called whenever the selection is changed or cleared. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // - DirectorySelected is passed the first selected directory (const char *). // - DirectoryOpened and DirectoryClosed are passed the directory being // opened or closed (const char *). // - DirectoryAdded and DirectoryDeleted are passed the directory that was // added or removed (const char *). // - DirectoryRenamed is passed the preview and new name (path) of the // directory that was renamed (const char *, const char *). virtual void SetDirectorySelectedCommand(vtkObject *obj, const char *method); virtual void SetDirectoryOpenedCommand(vtkObject *obj, const char *method); virtual void SetDirectoryClosedCommand(vtkObject *obj, const char *method); virtual void SetDirectoryCreatedCommand(vtkObject *obj, const char *method); virtual void SetDirectoryDeletedCommand(vtkObject *obj, const char *method); virtual void SetDirectoryRenamedCommand(vtkObject *obj, const char *method); // Description: // Events are passed the same parameters as the commands, if any. //BTX enum { DirectorySelectedEvent = 10000, DirectoryOpenedEvent, DirectoryClosedEvent, DirectoryCreatedEvent, DirectoryDeletedEvent }; //ETX // Description: // Set focus to the directory widget component of this widget. virtual void Focus(); virtual int HasFocus(); // Description: // Get the toolbar object. vtkGetObjectMacro(Toolbar, vtkKWToolbar); // Description: // Get the button objects. // DO NOT modify the callbacks, these accessors are provided to change // the button icons, for example. vtkGetObjectMacro(CreateFolderButton, vtkKWPushButton); vtkGetObjectMacro(BackButton, vtkKWPushButtonWithMenu); vtkGetObjectMacro(ForwardButton, vtkKWPushButtonWithMenu); vtkGetObjectMacro(UpButton, vtkKWPushButton); // Description: // Add event binding to the internal component widget // for the directory hierarchy, so that these events will be // invoked directly from the directory component of this widget. virtual void AddBindingToInternalWidget( const char* event, vtkObject *obj, const char* method); // Description: // Callback, do NOT use. // When the dropdown menu button of the Back/Forward buttons // is clicked, navigate to the corresponding directory is the history list. // 'node' is a pointer to the unique directory node string, // 'offsetFromCurrentIndex' is the offset from current directory index in // history list. virtual void OpenDirectoryNodeCallback( const char* node, int offsetFromCurrentIndex); // Description: // Callback, do NOT use. // When the node selection is changed in the directory tree, the // corresponding directory is refreshed, loading any new files or // directories underneath it. virtual void SingleClickOnNodeCallback(const char* node); // Description: // Callback, do NOT use. // Right-click to popup context menu. virtual void RightClickCallback( int x, int y, const char* node); // Description: // Callback, do NOT use. // Rename directory node from right-click context menu. virtual int RenameCallback(); // Description: // Callback, do NOT use. // Launch native explorer from right-click context menu. virtual void RightClickExploreCallback(const char*); // Description: // Callback, do NOT use. // When the Navigation keys (Up/Down, Home/End, // Prior(PageUp)/Next(PageDown)) are pressed. This is used to setup // logic to update the new selected node after the KeyPress events. virtual void TreeKeyNavigationCallback(); // Description: // Callback, do NOT use. // When a node is opened in the directory tree, the corresponding // directory is refreshed, loading new files and directories. virtual void DirectoryOpenedCallback(const char* node); // Description: // Callback, do NOT use. // When a node selection is changed in the directory tree. virtual void DirectorySelectedCallback(); // Description: // Callback, do NOT use. // When a node is closed in the directory tree. // Also need refreshing the contents of the corresponding directory. virtual void DirectoryClosedCallback(const char* node); // Description: // Callback, do NOT use. // When the "Create New Folder" button is clicked, a dialog is displayed // prompting the user for the name of the new directory. If the user inputs // a valid dir name, create the new directory, add it to the dir tree, and // select the node. virtual void CreateNewFolderCallback(); // Description: // Callback, do NOT use. // When the "Back to previous directory" button is clicked, navigate // to the previously visited directory. A history of visited directories // is saved in memory. virtual void BackToPreviousDirectoryCallback(); // Description: // Callback, do NOT use. // When the "Go to next directory" button is clicked, navigate // to next directory in the history list. virtual void ForwardToNextDirectoryCallback(); // Description: // Callback, do NOT use. // When the "Go up one directory" button is clicked, navigate // to the parent directory of the currently selected directory. virtual void GoUpDirectoryCallback(); // Description: // Callback, do NOT use. // When the 'Delete' key is pressed, remove the selected item from the dir // tree/file list. virtual int RemoveSelectedNodeCallback(); // Description: // Callback, do NOT use. virtual void LoadRootDirectoryCallback(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object // is updated and propagated to its internal parts/subwidgets. // This will, for example, enable/disable parts of the widget UI, // enable/disable the visibility of 3D widgets, etc. virtual void UpdateEnableState(); virtual void Update(); // Description: // Given the prefix of a sub-folder name of the current selected directory, // this function will make the corresponding child node for this // sub-folder visible in the window. virtual void ScrollToDirectory(const char* prefix); protected: vtkKWDirectoryExplorer(); ~vtkKWDirectoryExplorer(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Load root directory. For Win32, this will load the drives; // for *nix, this will load root "/" directory virtual void LoadRootDirectory(); // Description: // Close all the nodes up to root level: drives for Win32; '/' for *nix virtual void BackToRoot(); // Description: // When the node selection is changed in the directory tree, the // corresponding directory is refreshed, loading any new files or // directories underneath it. virtual void SelectDirectoryNode(const char* node, int opennode = 1); // Description: // If the directory is already loaded in the tree, navigate to // and reload this input directory; if not, this function will // call OpenDirectory(path) to open this directory. // 'node' is a pointer to the node string (can be NULL), 'path' a pointer // to the absolute path to the directory. // Return the node associated with this directory. virtual const char* ReloadDirectory(const char* node, const char* path); // Description: // Reload a directory node given the parent node, and the fullpath. // This is used to open the sub directory node of a parent node. // 'select' is a flag to indicate whether to select this sub node after // opening it. // Return the node opened. virtual const char* ReloadDirectory(const char* parentnode, const char* dirname, int select); // Description: // Open a subdirectory of a parent tree node. // 'parentnode' is the parent node of this directory, 'fullname' is the full // path name of this sub-directory, 'select' a flag to indicate whether to // select this sub node after opening it. virtual void OpenSubDirectory(const char* parentnode, const char* fullname, int select = 1); // Description: // This is the main funtion used to find all the directories and // adding all the corresponding node to the dir tree. virtual void OpenDirectoryNode(const char* node, int select = 1, int opennode = 1); // Description: // Open the node, including all its parent nodes. virtual void OpenWholeTree(const char* node); // Description: // Calling OpenDirectoryNode after centain logic to determine // whether to open the whole tree. virtual void ReloadDirectoryNode(const char* node); // Description: // This is the actual funtion adding all the nodes to the tree, // called from OpenDirectoryNode. virtual void UpdateDirectoryNode(const char* node); // Description: // Add a node to the dir tree. virtual void AddDirectoryNode( const char* parentnode, const char* node, const char* text, const char* fullname, vtkKWIcon *nodeicon); // Description: // Get one node from a multiple selection of nodes. An // error will be generated if the index is out of range. const char *GetNthSelectedNode(int i); // Description: // Update the directory history list given the most recent node virtual void UpdateMostRecentDirectoryHistory(const char* node); // Description: // Update directory history list according to the // MaximumNumberOfDirectoriesInHistory virtual void PruneMostRecentDirectoriesInHistory(); // Description: // Remove a directory node from the most recent history list virtual void RemoveDirectoryFromHistory(const char* node); // Description: // Populate the context menu. virtual void PopulateContextMenu(vtkKWMenu *menu, const char*); // Description: // Check if the node is one of the selected nodes. int IsNodeSelected(const char* node); // Description: // Open the directory. // -dirname, the directory that is going to be opened // -select, is the flag to whether select this directory // return a node for this directory const char* OpenDirectoryInternal(const char* dirname, int select); // Description: // Commands char *DirectorySelectedCommand; char *DirectoryOpenedCommand; char *DirectoryClosedCommand; char *DirectoryCreatedCommand; char *DirectoryDeletedCommand; char *DirectoryRenamedCommand; // Description: // Invoke Commands virtual void InvokeDirectorySelectedCommand(const char* path); virtual void InvokeDirectoryOpenedCommand(const char* path); virtual void InvokeDirectoryClosedCommand(const char* path); virtual void InvokeDirectoryCreatedCommand(const char* path); virtual void InvokeDirectoryDeletedCommand(const char* path); virtual void InvokeDirectoryRenamedCommand( const char* oldname, const char* newname); // Description: // Internal PIMPL class for STL purposes. vtkKWDirectoryExplorerInternals *Internals; // Description: // GUI vtkKWToolbar *Toolbar; vtkKWTreeWithScrollbars *DirectoryTree; vtkKWPushButton *CreateFolderButton; vtkKWPushButtonWithMenu *BackButton; vtkKWPushButtonWithMenu *ForwardButton; vtkKWPushButton *UpButton; vtkKWMenu *ContextMenu; // Description: // Member variables int MaximumNumberOfDirectoriesInHistory; private: static vtkIdType IdCounter; vtkKWDirectoryExplorer(const vtkKWDirectoryExplorer&); // Not implemented void operator=(const vtkKWDirectoryExplorer&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWColorPickerWidget.cxx0000644000175000017500000020346611220763055022170 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWColorPickerWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWColorPickerWidget.h" #include "vtkColorTransferFunction.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkKWApplication.h" #include "vtkKWColorPresetSelector.h" #include "vtkKWColorSpectrumWidget.h" #include "vtkKWColorSwatchesWidget.h" #include "vtkKWColorTransferFunctionEditor.h" #include "vtkKWEntry.h" #include "vtkKWEntryWithLabel.h" #include "vtkKWEvent.h" #include "vtkKWFrame.h" #include "vtkKWIcon.h" #include "vtkKWLabel.h" #include "vtkKWLabelSet.h" #include "vtkKWLabelWithLabel.h" #include "vtkKWNotebook.h" #include "vtkKWPushButton.h" #include "vtkKWRadioButton.h" #include #include #define VTK_KW_COLOR_PICKER_WIDGET_SPECTRUM_TAG 0 #define VTK_KW_COLOR_PICKER_WIDGET_COLOR_SWATCHES_TAG 1 #define VTK_KW_COLOR_PICKER_WIDGET_FAVORITES_TAG 2 #define VTK_KW_COLOR_PICKER_WIDGET_HISTORY_TAG 3 //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWColorPickerWidget ); vtkCxxRevisionMacro(vtkKWColorPickerWidget, "$Revision: 1.21 $"); //---------------------------------------------------------------------------- class vtkKWColorPickerWidgetInternals { public: vtksys_stl::string ScheduleUpdateInfoLabelTimerId; }; //---------------------------------------------------------------------------- vtkKWColorPickerWidget::vtkKWColorPickerWidget() { this->Internals = new vtkKWColorPickerWidgetInternals; this->ColorSpectrumVisibility = 1; this->ColorSwatchesVisibility = 1; this->FavoritesVisibility = 1; this->HistoryVisibility = 1; this->CompactMode = 0; this->EventCallData = NULL; this->SlidersFrame = NULL; this->RGBSlidersFrame = NULL; this->HSVSlidersFrame = NULL; int i; for (i = 0; i < 3; i++) { this->RGBSliders[i] = NULL; this->HSVSliders[i] = NULL; } for (i = 0; i < 6; i++) { this->FixedAxisRadioButton[i] = NULL; this->SliderUnitLabel[i] = NULL; } this->Notebook = NULL; this->HexadecimalColorEntry = NULL; this->ColorSpectrumWidget = NULL; this->FavoritesColorPresetSelector = vtkKWColorPresetSelector::New(); this->HistoryColorPresetSelector = vtkKWColorPresetSelector::New(); this->ColorSwatchesWidget = NULL; this->ColorsFrame = NULL; this->ColorsLabelSet = NULL; this->ColorsNameLabelSet = NULL; this->InfoLabel = NULL; this->CompactModeButton = NULL; this->InternalCurrentColorAsRGB[0] = -1; /* unitialized */ this->InternalCurrentColorAsRGB[1] = -1; this->InternalCurrentColorAsRGB[2] = -1; this->InternalCurrentColorAsHSV[0] = -1; this->InternalCurrentColorAsHSV[1] = -1; this->InternalCurrentColorAsHSV[2] = -1; this->SetCurrentColorAsHSV(0.5, 1.0, 1.0); this->InternalNewColorAsRGB[0] = -1; /* unitialized */ this->InternalNewColorAsRGB[1] = -1; this->InternalNewColorAsRGB[2] = -1; this->InternalNewColorAsHSV[0] = -1; this->InternalNewColorAsHSV[1] = -1; this->InternalNewColorAsHSV[2] = -1; } //---------------------------------------------------------------------------- vtkKWColorPickerWidget::~vtkKWColorPickerWidget() { if (this->SlidersFrame) { this->SlidersFrame->Delete(); this->SlidersFrame = NULL; } if (this->ColorsFrame) { this->ColorsFrame->Delete(); this->ColorsFrame = NULL; } if (this->ColorsLabelSet) { this->ColorsLabelSet->Delete(); this->ColorsLabelSet = NULL; } if (this->ColorsNameLabelSet) { this->ColorsNameLabelSet->Delete(); this->ColorsNameLabelSet = NULL; } int i; for (i = 0; i < 6; i++) { this->FixedAxisRadioButton[i]->Delete(); this->FixedAxisRadioButton[i] = NULL; this->SliderUnitLabel[i]->Delete(); this->SliderUnitLabel[i] = NULL; } if (this->RGBSlidersFrame) { this->RGBSlidersFrame->Delete(); this->RGBSlidersFrame = NULL; } if (this->HSVSlidersFrame) { this->HSVSlidersFrame->Delete(); this->HSVSlidersFrame = NULL; } for (i = 0; i < 3; i++) { if (this->RGBSliders[i]) { this->RGBSliders[i]->Delete(); this->RGBSliders[i] = NULL; } if (this->HSVSliders[i]) { this->HSVSliders[i]->Delete(); this->HSVSliders[i] = NULL; } } if (this->Notebook) { this->Notebook->Delete(); this->Notebook = NULL; } if (this->HexadecimalColorEntry) { this->HexadecimalColorEntry->Delete(); this->HexadecimalColorEntry = NULL; } if (this->InfoLabel) { this->InfoLabel->Delete(); this->InfoLabel = NULL; } if (this->CompactModeButton) { this->CompactModeButton->Delete(); this->CompactModeButton = NULL; } if (this->ColorSpectrumWidget) { this->ColorSpectrumWidget->Delete(); this->ColorSpectrumWidget = NULL; } if (this->FavoritesColorPresetSelector) { this->FavoritesColorPresetSelector->Delete(); this->FavoritesColorPresetSelector = NULL; } if (this->HistoryColorPresetSelector) { this->HistoryColorPresetSelector->Delete(); this->HistoryColorPresetSelector = NULL; } if (this->ColorSwatchesWidget) { this->ColorSwatchesWidget->Delete(); this->ColorSwatchesWidget = NULL; } delete this->Internals; this->Internals = NULL; } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); vtksys_ios::ostringstream tk_cmd; int i, page_id; vtkKWIcon *icon = vtkKWIcon::New(); // -------------------------------------------------------------- if (this->InternalNewColorAsRGB[0] == -1 || this->InternalNewColorAsRGB[1] == -1 || this->InternalNewColorAsRGB[2] == -1 || this->InternalNewColorAsHSV[0] == -1 || this->InternalNewColorAsHSV[1] == -1 || this->InternalNewColorAsHSV[2] == -1) { this->SetNewColorAsHSV(this->GetCurrentColorAsHSV()); } // -------------------------------------------------------------- // Notebook if (!this->Notebook) { this->Notebook = vtkKWNotebook::New(); } this->Notebook->SetParent(this); this->Notebook->Create(); this->Notebook->AlwaysShowTabsOn(); this->Notebook->ShowIconsOn(); this->Notebook->SetSelectedPageTabPadding(2); this->AddCallbackCommandObserver( this->Notebook, vtkKWEvent::NotebookRaisePageEvent); // -------------------------------------------------------------- // Spectrum icon->SetImage(vtkKWIcon::IconHSVDiagram); page_id = this->Notebook->AddPage( NULL, "Spectrum", icon, VTK_KW_COLOR_PICKER_WIDGET_SPECTRUM_TAG); this->Notebook->SetPageVisibility( page_id, this->ColorSpectrumVisibility); if (!this->ColorSpectrumWidget) { this->ColorSpectrumWidget = vtkKWColorSpectrumWidget::New(); } this->ColorSpectrumWidget->SetParent( this->Notebook->GetFrame(page_id)); this->ColorSpectrumWidget->FixedAxisSelectorVisibilityOff(); this->ColorSpectrumWidget->Create(); this->ColorSpectrumWidget->SetBorderWidth(2); this->ColorSpectrumWidget->SetReliefToSunken(); this->AddCallbackCommandObserver( this->ColorSpectrumWidget, vtkKWColorSpectrumWidget::ColorChangedEvent); this->AddCallbackCommandObserver( this->ColorSpectrumWidget, vtkKWColorSpectrumWidget::ColorChangingEvent); tk_cmd << "pack " << this->ColorSpectrumWidget->GetWidgetName() << " -side left -anchor nw -expand y -fill both -padx 2 -pady 2" << endl; // -------------------------------------------------------------- // Color swatches icon->SetImage(vtkKWIcon::IconSilkColorSwatch); page_id = this->Notebook->AddPage( NULL, "Color Swatches", icon, VTK_KW_COLOR_PICKER_WIDGET_COLOR_SWATCHES_TAG); this->Notebook->SetPageVisibility(page_id, this->ColorSwatchesVisibility); // -------------------------------------------------------------- // Favorites presets icon->SetImage(vtkKWIcon::IconFavorites); page_id = this->Notebook->AddPage( NULL, "Favorites", icon, VTK_KW_COLOR_PICKER_WIDGET_FAVORITES_TAG); this->Notebook->SetPageVisibility(page_id, this->FavoritesVisibility); this->CreateFavoritesColorPresetSelector(); // -------------------------------------------------------------- // History icon->SetImage(vtkKWIcon::IconTime); page_id = this->Notebook->AddPage( NULL, "History", icon, VTK_KW_COLOR_PICKER_WIDGET_HISTORY_TAG); this->Notebook->SetPageVisibility(page_id, this->HistoryVisibility); this->HistoryColorPresetSelector->SetPresetApplyCommand( this, "HistoryColorPresetApplyCallback "); this->CreateHistoryColorPresetSelector(); this->CreateColorSwatchesWidget(); // need to be here // -------------------------------------------------------------- // Sliders frame if (!this->SlidersFrame) { this->SlidersFrame = vtkKWFrame::New(); } this->SlidersFrame->SetParent(this); this->SlidersFrame->Create(); // -------------------------------------------------------------- // Colors if (!this->ColorsFrame) { this->ColorsFrame = vtkKWFrame::New(); } this->ColorsFrame->SetParent(this->SlidersFrame); this->ColorsFrame->Create(); if (!this->ColorsNameLabelSet) { this->ColorsNameLabelSet = vtkKWLabelSet::New(); } this->ColorsNameLabelSet->SetParent(this->ColorsFrame); this->ColorsNameLabelSet->Create(); this->ColorsNameLabelSet->PackHorizontallyOn(); if (!this->ColorsLabelSet) { this->ColorsLabelSet = vtkKWLabelSet::New(); } this->ColorsLabelSet->SetParent(this->ColorsFrame); this->ColorsLabelSet->Create(); this->ColorsLabelSet->PackHorizontallyOn(); this->ColorsLabelSet->SetBorderWidth(2); this->ColorsLabelSet->SetReliefToSunken(); vtkKWLabel *label = NULL; for (i = 0; i <= 1; i++) { label = this->ColorsNameLabelSet->AddWidget(i); label = this->ColorsLabelSet->AddWidget(i); label->SetBorderWidth(0); } this->ColorsNameLabelSet->GetWidget(0)->SetText("new"); this->ColorsNameLabelSet->GetWidget(1)->SetText("current"); this->ColorsLabelSet->GetWidget(1)->SetBinding( "", this, "CurrentColorCallback"); // -------------------------------------------------------------- // Hexadecimal Color if (!this->HexadecimalColorEntry) { this->HexadecimalColorEntry = vtkKWEntryWithLabel::New(); } this->HexadecimalColorEntry->SetParent(this->ColorsFrame); this->HexadecimalColorEntry->SetLabelText("#"); this->HexadecimalColorEntry->Create(); vtkKWEntry *entry = this->HexadecimalColorEntry->GetWidget(); entry->SetWidth(7); entry->SetRestrictValueToHexadecimal(); entry->SetCommand(this, "HexadecimalColorEntryCallback"); // -------------------------------------------------------------- // RGB sliders frame vtkKWFrame *rgb_frame; if (!this->RGBSlidersFrame) { this->RGBSlidersFrame = vtkKWFrame::New(); } this->RGBSlidersFrame->SetParent(this->SlidersFrame); this->RGBSlidersFrame->Create(); this->RGBSlidersFrame->SetBorderWidth(0); this->RGBSlidersFrame->SetReliefToGroove(); rgb_frame = this->RGBSlidersFrame; // -------------------------------------------------------------- // HSV sliders frame vtkKWFrame *hsv_frame; if (!this->HSVSlidersFrame) { this->HSVSlidersFrame = vtkKWFrame::New(); } this->HSVSlidersFrame->SetParent(this->SlidersFrame); this->HSVSlidersFrame->Create(); this->HSVSlidersFrame->SetBorderWidth( this->RGBSlidersFrame->GetBorderWidth()); this->HSVSlidersFrame->SetRelief(this->RGBSlidersFrame->GetRelief()); hsv_frame = this->HSVSlidersFrame; // -------------------------------------------------------------- // Info label if (!this->InfoLabel) { this->InfoLabel = vtkKWLabelWithLabel::New(); } this->InfoLabel->SetParent(this->SlidersFrame); this->InfoLabel->Create(); this->InfoLabel->LabelVisibilityOff(); this->InfoLabel->ExpandWidgetOn(); this->InfoLabel->GetLabel()->SetImageToPredefinedIcon( vtkKWIcon::IconSilkHelp); label = this->InfoLabel->GetWidget(); label->AdjustWrapLengthToWidthOn(); // Can't decrease the font on Win32 for now, it's flickering :( double fr, fg, fb, fh, fs, fv; label->GetForegroundColor(&fr, &fg, &fb); vtkMath::RGBToHSV(fr, fg, fb, &fh, &fs, &fv); double br, bg, bb, bh, bs, bv; label->GetBackgroundColor(&br, &bg, &bb); vtkMath::RGBToHSV(br, bg, bb, &bh, &bs, &bv); fv = 0.7 * fv + 0.3 * bv; vtkMath::HSVToRGB(fh, fs, fv, &fr, &fg, &fb); label->SetForegroundColor(fr, fg, fb); // -------------------------------------------------------------- // Compact mode if (!this->CompactModeButton) { this->CompactModeButton = vtkKWPushButton::New(); } this->CompactModeButton->SetParent(this); this->CompactModeButton->Create(); this->CompactModeButton->SetBorderWidth(0); this->CompactModeButton->SetCommand(this, "ToggleCompactMode"); this->CompactModeButton->SetImageToPredefinedIcon( vtkKWIcon::IconSilkBulletToggleMinus); this->CompactModeButton->SetBalloonHelpString( "Toggle the color picker layout between full mode and compact mode"); // Pack tk_cmd << "grid " << this->ColorsFrame->GetWidgetName() << " -row 0 -column 0 -sticky {} -padx 0 -pady 0" << endl; tk_cmd << "grid " << this->RGBSlidersFrame->GetWidgetName() << " -row 1 -column 0 -sticky {} -padx 0 -pady 2" << endl; tk_cmd << "grid " << this->HSVSlidersFrame->GetWidgetName() << " -row 2 -column 0 -sticky {} -padx 0 -pady 2" << endl; tk_cmd << "grid rowconfigure " << this->InfoLabel->GetParent()->GetWidgetName() << " 3 -weight 1" << endl; // -------------------------------------------------------------- // Fixed axis selector const int choices[6] = { vtkKWColorSpectrumWidget::FixedAxisR, vtkKWColorSpectrumWidget::FixedAxisG, vtkKWColorSpectrumWidget::FixedAxisB, vtkKWColorSpectrumWidget::FixedAxisH, vtkKWColorSpectrumWidget::FixedAxisS, vtkKWColorSpectrumWidget::FixedAxisV }; char command[128]; for (i = 0; i < 6; i++) { if (!this->FixedAxisRadioButton[i]) { this->FixedAxisRadioButton[i] = vtkKWRadioButton::New(); } if (!this->SliderUnitLabel[i]) { this->SliderUnitLabel[i] = vtkKWLabel::New(); } if (i < 3) { this->FixedAxisRadioButton[i]->SetParent(rgb_frame); this->SliderUnitLabel[i]->SetParent(rgb_frame); } else { this->FixedAxisRadioButton[i]->SetParent(hsv_frame); this->SliderUnitLabel[i]->SetParent(hsv_frame); } this->FixedAxisRadioButton[i]->Create(); this->FixedAxisRadioButton[i]->SetHighlightThickness(0); this->FixedAxisRadioButton[i]->SetBorderWidth(0); this->FixedAxisRadioButton[i]->SetPadX(0); this->FixedAxisRadioButton[i]->SetValueAsInt(choices[i]); this->FixedAxisRadioButton[i]->SetConfigurationOptionAsInt( "-takefocus", 0); if (i > 0) { this->FixedAxisRadioButton[i]->SetVariableName( this->FixedAxisRadioButton[0]->GetVariableName()); } sprintf(command, "SetFixedAxis %d", choices[i]); this->FixedAxisRadioButton[i]->SetCommand( this->ColorSpectrumWidget, command); this->SliderUnitLabel[i]->Create(); this->SliderUnitLabel[i]->SetWidth(1); } this->FixedAxisRadioButton[0]->SetVariableValueAsInt( this->ColorSpectrumWidget->GetFixedAxis()); // -------------------------------------------------------------- // RGB sliders const char *rgb_label[3] = {"R:", "G:", "B:"}; const char *rgb_unit[3] = {" ", " ", " "}; for (i = 0; i < 3; i++) { if (!this->RGBSliders[i]) { this->RGBSliders[i] = vtkKWColorTransferFunctionEditor::New(); } this->RGBSliders[i]->SetParent(rgb_frame); this->RGBSliders[i]->ExpandCanvasWidthOff(); this->RGBSliders[i]->LabelVisibilityOn(); this->RGBSliders[i]->SetLabelText(rgb_label[i]); this->RGBSliders[i]->SetLabelPositionToLeft(); this->RGBSliders[i]->ParameterRangeLabelVisibilityOff(); this->RGBSliders[i]->ParameterEntryVisibilityOn(); this->RGBSliders[i]->PointEntriesVisibilityOn(); this->RGBSliders[i]->SetPointEntriesPositionToRight(); this->RGBSliders[i]->MidPointEntryVisibilityOff(); this->RGBSliders[i]->SharpnessEntryVisibilityOff(); this->RGBSliders[i]->SetParameterEntryFormat("%3.f"); this->RGBSliders[i]->PointIndexVisibilityOff(); this->RGBSliders[i]->SelectedPointIndexVisibilityOff(); this->RGBSliders[i]->SetSelectedPointRadius(1.0); this->RGBSliders[i]->SetSelectedPointColor( this->RGBSliders[i]->GetPointColor()); this->RGBSliders[i]->DisableAddAndRemoveOn(); this->RGBSliders[i]->LockPointsValueOn(); this->RGBSliders[i]->EnableDirectMoveOn(); this->RGBSliders[i]->ComputePointColorFromValueOff(); this->RGBSliders[i]->SetPointPositionInValueRangeToBottom(); this->RGBSliders[i]->SetPointStyle( vtkKWParameterValueFunctionEditor::PointStyleCursorUp); this->RGBSliders[i]->FunctionLineVisibilityOff(); this->RGBSliders[i]->SetPointMarginToCanvas( vtkKWParameterValueFunctionEditor::PointMarginHorizontalSides | vtkKWParameterValueFunctionEditor::PointMarginVerticalSides); this->RGBSliders[i]->ParameterRangeVisibilityOff(); this->RGBSliders[i]->ValueRangeVisibilityOff(); this->RGBSliders[i]->ValueRangeLabelVisibilityOff(); this->RGBSliders[i]->ValueEntriesVisibilityOff(); this->RGBSliders[i]->ColorSpaceOptionMenuVisibilityOff(); this->RGBSliders[i]->ColorRampVisibilityOn(); this->RGBSliders[i]->SetColorRampPositionToCanvas(); this->RGBSliders[i]->CanvasOutlineVisibilityOff(); this->RGBSliders[i]->CanvasBackgroundVisibilityOff(); this->RGBSliders[i]->ChangeMouseCursorOff(); this->RGBSliders[i]->Create(); this->RGBSliders[i]->GetParameterEntry()->LabelVisibilityOff(); this->RGBSliders[i]->GetParameterEntry()->GetWidget()->SetWidth(4); this->RGBSliders[i]->SetColorRampOutlineStyle( vtkKWColorTransferFunctionEditor::ColorRampOutlineStyleSunken); if (this->RGBSliders[i]->GetLabelVisibility()) { this->RGBSliders[i]->GetLabel()->SetWidth(2); } this->AddCallbackCommandObserver( this->RGBSliders[i], vtkKWParameterValueFunctionEditor::FunctionChangingEvent); this->AddCallbackCommandObserver( this->RGBSliders[i], vtkKWParameterValueFunctionEditor::FunctionChangedEvent); this->SliderUnitLabel[i]->SetText(rgb_unit[i]); tk_cmd << "grid " << this->FixedAxisRadioButton[i]->GetWidgetName() << " -pady 1 -sticky nws -column 0 -row " << i << endl; tk_cmd << "grid " << this->RGBSliders[i]->GetWidgetName() << " -pady 1 -sticky nws -column 1 -row " << i << endl; tk_cmd << "grid " << this->SliderUnitLabel[i]->GetWidgetName() << " -pady 1 -sticky nws -column 2 -row " << i << endl; } tk_cmd << "grid columnconfigure " << this->SliderUnitLabel[0]->GetParent()->GetWidgetName() << " 0 -uniform label" << endl; tk_cmd << "grid columnconfigure " << this->SliderUnitLabel[0]->GetParent()->GetWidgetName() << " 2 -uniform units" << endl; double r, g, b, s = 0.3, v = 1.0; vtkMath::HSVToRGB(0, s, v, &r, &g, &b); // this->RGBSliders[0]->GetLabel()->SetBackgroundColor(r, g, b); this->RGBSliders[0]->GetParameterEntry()->GetWidget()->SetBackgroundColor( r, g, b); vtkMath::HSVToRGB(0.333, s, v, &r, &g, &b); // this->RGBSliders[1]->GetLabel()->SetBackgroundColor(r, g, b); this->RGBSliders[1]->GetParameterEntry()->GetWidget()->SetBackgroundColor( r, g, b); vtkMath::HSVToRGB(0.666, s, v, &r, &g, &b); // this->RGBSliders[2]->GetLabel()->SetBackgroundColor(r, g, b); this->RGBSliders[2]->GetParameterEntry()->GetWidget()->SetBackgroundColor( r, g, b); // -------------------------------------------------------------- // HSV sliders const char *hsv_label[3] = {"H:", "S:", "V:"}; const char *hsv_unit[3] = {"°", "%", "%"}; for (i = 0; i < 3; i++) { if (!this->HSVSliders[i]) { this->HSVSliders[i] = vtkKWColorTransferFunctionEditor::New(); } this->HSVSliders[i]->SetParent(hsv_frame); this->HSVSliders[i]->SetExpandCanvasWidth( this->RGBSliders[i]->GetExpandCanvasWidth()); this->HSVSliders[i]->SetLabelVisibility( this->RGBSliders[i]->GetLabelVisibility()); this->HSVSliders[i]->SetLabelText(hsv_label[i]); this->HSVSliders[i]->SetLabelPosition( this->RGBSliders[i]->GetLabelPosition()); this->HSVSliders[i]->SetParameterRangeLabelVisibility( this->RGBSliders[i]->GetParameterRangeLabelVisibility()); this->HSVSliders[i]->SetParameterEntryVisibility( this->RGBSliders[i]->GetParameterEntryVisibility()); this->HSVSliders[i]->SetPointEntriesPosition( this->RGBSliders[i]->GetPointEntriesPosition()); this->HSVSliders[i]->SetPointEntriesVisibility( this->RGBSliders[i]->GetPointEntriesVisibility()); this->HSVSliders[i]->SetMidPointEntryVisibility( this->RGBSliders[i]->GetMidPointEntryVisibility()); this->HSVSliders[i]->SetSharpnessEntryVisibility( this->RGBSliders[i]->GetSharpnessEntryVisibility()); this->HSVSliders[i]->SetParameterEntryFormat( this->RGBSliders[i]->GetParameterEntryFormat()); this->HSVSliders[i]->SetPointIndexVisibility( this->RGBSliders[i]->GetPointIndexVisibility()); this->HSVSliders[i]->SetSelectedPointIndexVisibility( this->RGBSliders[i]->GetSelectedPointIndexVisibility()); this->HSVSliders[i]->SetSelectedPointRadius( this->RGBSliders[i]->GetSelectedPointRadius()); this->HSVSliders[i]->SetSelectedPointColor( this->RGBSliders[i]->GetSelectedPointColor()); this->HSVSliders[i]->SetDisableAddAndRemove( this->RGBSliders[i]->GetDisableAddAndRemove()); this->HSVSliders[i]->SetLockPointsValue( this->RGBSliders[i]->GetLockPointsValue()); this->HSVSliders[i]->SetEnableDirectMove( this->RGBSliders[i]->GetEnableDirectMove()); this->HSVSliders[i]->SetComputePointColorFromValue( this->RGBSliders[i]->GetComputePointColorFromValue()); this->HSVSliders[i]->SetPointPositionInValueRange( this->RGBSliders[i]->GetPointPositionInValueRange()); this->HSVSliders[i]->SetPointStyle( this->RGBSliders[i]->GetPointStyle()); this->HSVSliders[i]->SetFunctionLineVisibility( this->RGBSliders[i]->GetFunctionLineVisibility()); this->HSVSliders[i]->SetPointMarginToCanvas( this->RGBSliders[i]->GetPointMarginToCanvas()); this->HSVSliders[i]->SetParameterRangeVisibility( this->RGBSliders[i]->GetParameterRangeVisibility()); this->HSVSliders[i]->SetValueRangeVisibility( this->RGBSliders[i]->GetValueRangeVisibility()); this->HSVSliders[i]->SetValueRangeLabelVisibility( this->RGBSliders[i]->GetValueRangeLabelVisibility()); this->HSVSliders[i]->SetValueEntriesVisibility( this->RGBSliders[i]->GetValueEntriesVisibility()); this->HSVSliders[i]->SetColorSpaceOptionMenuVisibility( this->RGBSliders[i]->GetColorSpaceOptionMenuVisibility()); this->HSVSliders[i]->SetColorRampVisibility( this->RGBSliders[i]->GetColorRampVisibility()); this->HSVSliders[i]->SetColorRampPosition( this->RGBSliders[i]->GetColorRampPosition()); this->HSVSliders[i]->SetCanvasOutlineVisibility( this->RGBSliders[i]->GetCanvasOutlineVisibility()); this->HSVSliders[i]->SetCanvasBackgroundVisibility( this->RGBSliders[i]->GetCanvasBackgroundVisibility()); this->HSVSliders[i]->SetChangeMouseCursor( this->RGBSliders[i]->GetChangeMouseCursor()); this->HSVSliders[i]->Create(); this->HSVSliders[i]->GetParameterEntry()->SetLabelVisibility( this->RGBSliders[i]->GetParameterEntry()->GetLabelVisibility()); this->HSVSliders[i]->GetParameterEntry()->GetWidget()->SetWidth( this->RGBSliders[i]->GetParameterEntry()->GetWidget()->GetWidth()); this->HSVSliders[i]->SetColorRampOutlineStyle( this->RGBSliders[i]->GetColorRampOutlineStyle()); if (this->HSVSliders[i]->GetLabelVisibility()) { this->HSVSliders[i]->GetLabel()->SetWidth( this->RGBSliders[i]->GetLabel()->GetWidth()); } this->AddCallbackCommandObserver( this->HSVSliders[i], vtkKWParameterValueFunctionEditor::FunctionChangingEvent); this->AddCallbackCommandObserver( this->HSVSliders[i], vtkKWParameterValueFunctionEditor::FunctionChangedEvent); this->SliderUnitLabel[3 + i]->SetText(hsv_unit[i]); tk_cmd << "grid " << this->FixedAxisRadioButton[3 + i]->GetWidgetName() << " -pady 1 -sticky nws -column 0 -row " << i << endl; tk_cmd << "grid " << this->HSVSliders[i]->GetWidgetName() << " -pady 1 -sticky nws -column 1 -row " << i << endl; tk_cmd << "grid " << this->SliderUnitLabel[3 + i]->GetWidgetName() << " -pady 1 -sticky nws -column 2 -row " << i << endl; } tk_cmd << "grid columnconfigure " << this->SliderUnitLabel[3]->GetParent()->GetWidgetName() << " 0 -uniform label" << endl; tk_cmd << "grid columnconfigure " << this->SliderUnitLabel[3]->GetParent()->GetWidgetName() << " 2 -uniform units" << endl; // -------------------------------------------------------------- icon->Delete(); this->Script(tk_cmd.str().c_str()); // Update this->ColorSpectrumWidget->SetColorAsHSV(this->InternalNewColorAsHSV); this->UpdateSlidersRGB(this->InternalNewColorAsRGB); this->UpdateSlidersHSV(this->InternalNewColorAsHSV); this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(0), this->InternalNewColorAsRGB); this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(1), this->InternalCurrentColorAsRGB); this->UpdateHexadecimalColorEntry(this->InternalNewColorAsRGB); this->UpdateInfoLabel(); this->Pack(); // This helps top levels that would embed a color picker widget. // (see vtkKWColorPickerDialog). Each time the dialog is brought back // to screen, make sure the label is updated immediately. this->AddBinding("", this, "UpdateInfoLabelCallback"); this->AdjustToCompactMode(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::CreateColorSwatchesWidget() { if (!this->IsCreated()) { return; } if (!this->ColorSwatchesWidget) { this->ColorSwatchesWidget = vtkKWColorSwatchesWidget::New(); } if (this->ColorSwatchesWidget->IsCreated()) { return; } this->ColorSwatchesWidget->SetParent( this->Notebook->GetFrame(NULL, VTK_KW_COLOR_PICKER_WIDGET_COLOR_SWATCHES_TAG)); this->ColorSwatchesWidget->Create(); this->ColorSwatchesWidget->AddDefaultCollections(); this->ColorSwatchesWidget->SetSwatchSelectedCommand( this, "SwatchSelectedCallback"); this->ColorSwatchesWidget->GetSwatchesColorPresetSelector()->SetListWidth( this->FavoritesColorPresetSelector->GetListWidth()); this->ColorSwatchesWidget->GetSwatchesColorPresetSelector()->SetListHeight( this->FavoritesColorPresetSelector->GetListHeight()); this->Script( "pack %s -side left -anchor nw -expand y -fill both -padx 2 -pady 2", this->ColorSwatchesWidget->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::CreateFavoritesColorPresetSelector() { if (!this->IsCreated()) { return; } if (!this->FavoritesColorPresetSelector) { this->FavoritesColorPresetSelector = vtkKWColorPresetSelector::New(); } if (this->FavoritesColorPresetSelector->IsCreated()) { return; } this->FavoritesColorPresetSelector->SetParent( this->Notebook->GetFrame(NULL, VTK_KW_COLOR_PICKER_WIDGET_FAVORITES_TAG)); this->FavoritesColorPresetSelector->Create(); this->FavoritesColorPresetSelector->SetPresetAddCommand( this, "FavoritesColorPresetAddCallback"); this->FavoritesColorPresetSelector->SetPresetUpdateCommand( this, "FavoritesColorPresetUpdateCallback"); this->FavoritesColorPresetSelector->SetPresetApplyCommand( this, "FavoritesColorPresetApplyCallback "); this->FavoritesColorPresetSelector->SetMaximumNumberOfPresets(64); this->FavoritesColorPresetSelector->SetListWidth(15); this->FavoritesColorPresetSelector->SetListHeight(4); this->Script("pack %s -side left -anchor nw -expand y -fill both", this->FavoritesColorPresetSelector->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::CreateHistoryColorPresetSelector() { if (!this->IsCreated()) { return; } if (!this->HistoryColorPresetSelector) { this->HistoryColorPresetSelector = vtkKWColorPresetSelector::New(); } if (this->HistoryColorPresetSelector->IsCreated()) { return; } this->HistoryColorPresetSelector->SetParent( this->Notebook->GetFrame(NULL, VTK_KW_COLOR_PICKER_WIDGET_HISTORY_TAG)); this->HistoryColorPresetSelector->Create(); this->HistoryColorPresetSelector->SetPresetApplyCommand( this, "HistoryColorPresetApplyCallback "); this->HistoryColorPresetSelector->SetMaximumNumberOfPresets(32); this->HistoryColorPresetSelector->SetListWidth( this->FavoritesColorPresetSelector->GetListWidth()); this->HistoryColorPresetSelector->SetListHeight( this->FavoritesColorPresetSelector->GetListHeight()); this->Script("pack %s -side left -anchor nw -expand y -fill both", this->HistoryColorPresetSelector->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::Pack() { if (!this->IsCreated()) { return; } this->UnpackChildren(); vtksys_ios::ostringstream tk_cmd; tk_cmd << "pack " << this->SlidersFrame->GetWidgetName() << " -padx 2 -pady 2 -side left -anchor nw -expand n -fill y" << endl; if (this->ColorSpectrumVisibility || this->ColorSwatchesVisibility || this->FavoritesVisibility || this->HistoryVisibility) { tk_cmd << "pack " << this->Notebook->GetWidgetName() << " -padx 2 -pady 2 -side left -anchor nw -expand n -fill none" << endl; } this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::AdjustToCompactMode() { int i; int base_size; vtksys_ios::ostringstream tk_cmd; // Compact mode if (this->CompactMode) { base_size = 128; this->ColorSwatchesWidget->SetSwatchSize(9); this->ColorSwatchesWidget->SetMaximumNumberOfSwatchesPerRow(12); this->ColorSwatchesWidget->SetSwatchesPadding(1); for (i = 0; i <= 1; i++) { vtkKWLabel *label = this->ColorsLabelSet->GetWidget(i); label->SetWidth(7); label->SetHeight(1); } this->CompactModeButton->SetImageToPredefinedIcon( vtkKWIcon::IconSilkBulletTogglePlus); tk_cmd << "grid forget " << this->ColorsNameLabelSet->GetWidgetName() << endl; tk_cmd << "grid " << this->HexadecimalColorEntry->GetWidgetName() << " -row 1 -column 0 -sticky {w} -pady 0 -padx 2" << endl; tk_cmd << "grid forget " << this->InfoLabel->GetWidgetName() << endl; } // Full mode else { base_size = 256; this->ColorSwatchesWidget->SetSwatchSize(16); this->ColorSwatchesWidget->SetMaximumNumberOfSwatchesPerRow(13); this->ColorSwatchesWidget->SetSwatchesPadding(2); for (i = 0; i <= 1; i++) { vtkKWLabel *label = this->ColorsLabelSet->GetWidget(i); label->SetWidth(10); label->SetHeight(3); } this->CompactModeButton->SetImageToPredefinedIcon( vtkKWIcon::IconSilkBulletToggleMinus); tk_cmd << "grid " << this->ColorsNameLabelSet->GetWidgetName() << " -row 0 -column 1 -sticky {ew} -pady 0" << endl; tk_cmd << "grid " << this->HexadecimalColorEntry->GetWidgetName() << " -row 2 -column 1 -sticky {w} -pady 3 -padx 5" << endl; tk_cmd << "grid " << this->InfoLabel->GetWidgetName() << " -row 3 -column 0 -sticky ews -padx 6 -pady 0" << endl; } this->Notebook->SetMinimumWidth(base_size + 12); this->Notebook->SetMinimumHeight(base_size + 39); this->ColorSpectrumWidget->SetCanvasSize(base_size); for (i = 0; i < 3; i++) { this->RGBSliders[i]->SetCanvasWidth(base_size); this->RGBSliders[i]->SetCanvasHeight(18); this->RGBSliders[i]->SetColorRampHeight(14); this->HSVSliders[i]->SetCanvasWidth( this->RGBSliders[i]->GetCanvasWidth()); this->HSVSliders[i]->SetCanvasHeight( this->RGBSliders[i]->GetCanvasHeight()); this->HSVSliders[i]->SetColorRampHeight( this->RGBSliders[i]->GetColorRampHeight()); } tk_cmd << "grid " << this->ColorsLabelSet->GetWidgetName() << " -row 1 -column 1 -sticky {ew} -pady 0" << endl; tk_cmd << "place " << this->CompactModeButton->GetWidgetName() << " -anchor nw -x 0 -y 0" << endl; this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetInternalNewColorAsRGB(double rgb[3]) { this->SetInternalNewColorAsRGB(rgb[0], rgb[1], rgb[2]); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetInternalNewColorAsRGB( double r, double g, double b) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&r, range); vtkMath::ClampValue(&g, range); vtkMath::ClampValue(&b, range); if (r == this->InternalNewColorAsRGB[0] && g == this->InternalNewColorAsRGB[1] && b == this->InternalNewColorAsRGB[2]) { return; } this->InternalNewColorAsRGB[0] = r; this->InternalNewColorAsRGB[1] = g; this->InternalNewColorAsRGB[2] = b; this->Modified(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetNewColorAsRGB(double r, double g, double b) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&r, range); vtkMath::ClampValue(&g, range); vtkMath::ClampValue(&b, range); double current_rgb[3]; this->GetNewColorAsRGB(current_rgb); if (r == current_rgb[0] && g == current_rgb[1] && b == current_rgb[2]) { return; } this->Modified(); this->SetInternalNewColorAsRGB(r, g, b); double h, s, v; vtkMath::RGBToHSV(r, g, b, &h, &s, &v); this->SetInternalNewColorAsHSV(h, s, v); // Update UI (with RGB in mind) if (this->ColorsLabelSet) { this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(0), this->InternalNewColorAsRGB); } this->UpdateSlidersRGB(this->InternalNewColorAsRGB); if (this->ColorSpectrumWidget) { this->ColorSpectrumWidget->SetColorAsRGB(this->InternalNewColorAsRGB); } this->UpdateHexadecimalColorEntry(this->InternalNewColorAsRGB); this->UpdateSlidersHSV(this->InternalNewColorAsHSV); this->ScheduleUpdateInfoLabel(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetNewColorAsRGB(double rgb[3]) { this->SetNewColorAsRGB(rgb[0], rgb[1], rgb[2]); } //---------------------------------------------------------------------------- double* vtkKWColorPickerWidget::GetNewColorAsRGB() { return this->GetInternalNewColorAsRGB(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::GetNewColorAsRGB( double &_arg1, double &_arg2, double &_arg3) { this->GetInternalNewColorAsRGB(_arg1, _arg2, _arg3); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::GetNewColorAsRGB(double _arg[3]) { this->GetNewColorAsRGB(_arg[0], _arg[1], _arg[2]); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetInternalNewColorAsHSV(double hsv[3]) { this->SetInternalNewColorAsHSV(hsv[0], hsv[1], hsv[2]); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetInternalNewColorAsHSV( double h, double s, double v) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&h, range); vtkMath::ClampValue(&s, range); vtkMath::ClampValue(&v, range); if (h == this->InternalNewColorAsHSV[0] && s == this->InternalNewColorAsHSV[1] && v == this->InternalNewColorAsHSV[2]) { return; } this->InternalNewColorAsHSV[0] = h; this->InternalNewColorAsHSV[1] = s; this->InternalNewColorAsHSV[2] = v; this->Modified(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetNewColorAsHSV(double h, double s, double v) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&h, range); vtkMath::ClampValue(&s, range); vtkMath::ClampValue(&v, range); double current_hsv[3]; this->GetNewColorAsHSV(current_hsv); if (h == current_hsv[0] && s == current_hsv[1] && v == current_hsv[2]) { return; } this->Modified(); this->SetInternalNewColorAsHSV(h, s, v); double r, g, b; vtkMath::HSVToRGB(h, s, v, &r, &g, &b); this->SetInternalNewColorAsRGB(r, g, b); // Update UI (with HSV in mind) if (this->ColorsLabelSet) { this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(0), this->InternalNewColorAsRGB); } this->UpdateSlidersRGB(this->InternalNewColorAsRGB); this->UpdateHexadecimalColorEntry(this->InternalNewColorAsRGB); if (this->ColorSpectrumWidget) { this->ColorSpectrumWidget->SetColorAsHSV(this->InternalNewColorAsHSV); } this->UpdateSlidersHSV(this->InternalNewColorAsHSV); this->ScheduleUpdateInfoLabel(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetNewColorAsHSV(double hsv[3]) { this->SetNewColorAsHSV(hsv[0], hsv[1], hsv[2]); } //---------------------------------------------------------------------------- double* vtkKWColorPickerWidget::GetNewColorAsHSV() { return this->GetInternalNewColorAsHSV(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::GetNewColorAsHSV( double &_arg1, double &_arg2, double &_arg3) { this->GetInternalNewColorAsHSV(_arg1, _arg2, _arg3); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::GetNewColorAsHSV(double _arg[3]) { this->GetNewColorAsHSV(_arg[0], _arg[1], _arg[2]); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetInternalCurrentColorAsRGB(double rgb[3]) { this->SetInternalCurrentColorAsRGB(rgb[0], rgb[1], rgb[2]); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetInternalCurrentColorAsRGB( double r, double g, double b) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&r, range); vtkMath::ClampValue(&g, range); vtkMath::ClampValue(&b, range); if (r == this->InternalCurrentColorAsRGB[0] && g == this->InternalCurrentColorAsRGB[1] && b == this->InternalCurrentColorAsRGB[2]) { return; } this->InternalCurrentColorAsRGB[0] = r; this->InternalCurrentColorAsRGB[1] = g; this->InternalCurrentColorAsRGB[2] = b; this->Modified(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetCurrentColorAsRGB(double r, double g, double b) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&r, range); vtkMath::ClampValue(&g, range); vtkMath::ClampValue(&b, range); double current_rgb[3]; this->GetCurrentColorAsRGB(current_rgb); if (r == current_rgb[0] && g == current_rgb[1] && b == current_rgb[2]) { return; } this->Modified(); this->SetInternalCurrentColorAsRGB(r, g, b); double h, s, v; vtkMath::RGBToHSV(r, g, b, &h, &s, &v); this->SetInternalCurrentColorAsHSV(h, s, v); // Update UI (with RGB in mind) if (this->ColorsLabelSet) { this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(1), this->InternalCurrentColorAsRGB); } this->ScheduleUpdateInfoLabel(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetCurrentColorAsRGB(double rgb[3]) { this->SetCurrentColorAsRGB(rgb[0], rgb[1], rgb[2]); } //---------------------------------------------------------------------------- double* vtkKWColorPickerWidget::GetCurrentColorAsRGB() { return this->GetInternalCurrentColorAsRGB(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::GetCurrentColorAsRGB( double &_arg1, double &_arg2, double &_arg3) { this->GetInternalCurrentColorAsRGB(_arg1, _arg2, _arg3); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::GetCurrentColorAsRGB(double _arg[3]) { this->GetCurrentColorAsRGB(_arg[0], _arg[1], _arg[2]); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetInternalCurrentColorAsHSV(double hsv[3]) { this->SetInternalCurrentColorAsHSV(hsv[0], hsv[1], hsv[2]); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetInternalCurrentColorAsHSV( double h, double s, double v) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&h, range); vtkMath::ClampValue(&s, range); vtkMath::ClampValue(&v, range); if (h == this->InternalCurrentColorAsHSV[0] && s == this->InternalCurrentColorAsHSV[1] && v == this->InternalCurrentColorAsHSV[2]) { return; } this->InternalCurrentColorAsHSV[0] = h; this->InternalCurrentColorAsHSV[1] = s; this->InternalCurrentColorAsHSV[2] = v; this->Modified(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetCurrentColorAsHSV(double h, double s, double v) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&h, range); vtkMath::ClampValue(&s, range); vtkMath::ClampValue(&v, range); double current_hsv[3]; this->GetCurrentColorAsHSV(current_hsv); if (h == current_hsv[0] && s == current_hsv[1] && v == current_hsv[2]) { return; } this->Modified(); this->SetInternalCurrentColorAsHSV(h, s, v); double r, g, b; vtkMath::HSVToRGB(h, s, v, &r, &g, &b); this->SetInternalCurrentColorAsRGB(r, g, b); // Update UI (with HSV in mind) if (this->ColorsLabelSet) { this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(1), this->InternalCurrentColorAsRGB); } this->ScheduleUpdateInfoLabel(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetCurrentColorAsHSV(double hsv[3]) { this->SetCurrentColorAsHSV(hsv[0], hsv[1], hsv[2]); } //---------------------------------------------------------------------------- double* vtkKWColorPickerWidget::GetCurrentColorAsHSV() { return this->GetInternalCurrentColorAsHSV(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::GetCurrentColorAsHSV( double &_arg1, double &_arg2, double &_arg3) { this->GetInternalCurrentColorAsHSV(_arg1, _arg2, _arg3); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::GetCurrentColorAsHSV(double _arg[3]) { this->GetCurrentColorAsHSV(_arg[0], _arg[1], _arg[2]); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::UpdateSlidersRGB(double rgb[3]) { int i; // RGB sliders for (i = 0; i < 3; i++) { if (this->RGBSliders[i]) { vtkColorTransferFunction *sliderfunc = this->RGBSliders[i]->GetColorTransferFunction(); int was_created = 0; if (!sliderfunc) { sliderfunc = vtkColorTransferFunction::New(); was_created = 1; } sliderfunc->RemoveAllPoints(); sliderfunc->AddRGBPoint(rgb[i], 1.0, 1.0, 1.0); this->RGBSliders[i]->SetColorTransferFunction(sliderfunc); this->RGBSliders[i]->SelectFirstPoint(); if (was_created) { sliderfunc->Delete(); } vtkColorTransferFunction *rampfunc = this->RGBSliders[i]->GetColorRampTransferFunction(); was_created = 0; if (!rampfunc) { rampfunc = vtkColorTransferFunction::New(); was_created = 1; } rampfunc->RemoveAllPoints(); rampfunc->AddRGBSegment( 0.0, (i == 0 ? 0.0 : rgb[0]), (i == 1 ? 0.0 : rgb[1]), (i == 2 ? 0.0 : rgb[2]), 1.0, (i == 0 ? 1.0 : rgb[0]), (i == 1 ? 1.0 : rgb[1]), (i == 2 ? 1.0 : rgb[2]) ); this->RGBSliders[i]->SetColorRampTransferFunction(rampfunc); if (was_created) { rampfunc->Delete(); } this->RGBSliders[i]->SetWholeParameterRange(0.0, 1.0); this->RGBSliders[i]->SetVisibleParameterRange( this->RGBSliders[i]->GetWholeParameterRange()); this->RGBSliders[i]->SetDisplayedWholeParameterRange(0.0, 255.0); this->RGBSliders[i]->Update(); } } } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::NewColorChanging() { this->InvokeEvent( vtkKWColorPickerWidget::NewColorChangingEvent, this->EventCallData); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::NewColorChanged() { this->InvokeEvent( vtkKWColorPickerWidget::NewColorChangedEvent, this->EventCallData); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::RGBSlidersChangingCallback() { double new_color_rgb[3]; int i; for (i = 0; i < 3; i++) { if (this->RGBSliders[i]) { vtkColorTransferFunction *sliderfunc = this->RGBSliders[i]->GetColorTransferFunction(); if (sliderfunc) { new_color_rgb[i] = *sliderfunc->GetDataPointer(); } } } if (new_color_rgb[0] == this->InternalNewColorAsRGB[0] && new_color_rgb[1] == this->InternalNewColorAsRGB[1] && new_color_rgb[2] == this->InternalNewColorAsRGB[2]) { return; } this->SetInternalNewColorAsRGB(new_color_rgb); double new_color_hsv[3]; vtkMath::RGBToHSV(new_color_rgb, new_color_hsv); this->SetInternalNewColorAsHSV(new_color_hsv); // Update UI (with RGB in mind) if (this->ColorsLabelSet) { this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(0), this->InternalNewColorAsRGB); } if (this->ColorSpectrumWidget) { this->ColorSpectrumWidget->SetColorAsRGB(this->InternalNewColorAsRGB); } this->UpdateHexadecimalColorEntry(this->InternalNewColorAsRGB); this->UpdateSlidersHSV(this->InternalNewColorAsHSV); this->ScheduleUpdateInfoLabel(); this->NewColorChanging(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::UpdateSlidersHSV(double hsv[3]) { int i; // HSV sliders for (i = 0; i < 3; i++) { if (this->HSVSliders[i]) { vtkColorTransferFunction *sliderfunc = this->HSVSliders[i]->GetColorTransferFunction(); int was_created = 0; if (!sliderfunc) { sliderfunc = vtkColorTransferFunction::New(); was_created = 1; } sliderfunc->RemoveAllPoints(); sliderfunc->AddHSVPoint(hsv[i], 1.0, 1.0, 1.0); this->HSVSliders[i]->SetColorTransferFunction(sliderfunc); this->HSVSliders[i]->SelectFirstPoint(); if (was_created) { sliderfunc->Delete(); } vtkColorTransferFunction *rampfunc = this->HSVSliders[i]->GetColorRampTransferFunction(); was_created = 0; if (!rampfunc) { rampfunc = vtkColorTransferFunction::New(); rampfunc->SetColorSpaceToHSV(); was_created = 1; } rampfunc->RemoveAllPoints(); if (i == 0) { rampfunc->AddHSVPoint(0.0, 0.0, 1.0, 1.0); rampfunc->AddHSVPoint(0.5, 0.5, 1.0, 1.0); rampfunc->AddHSVPoint(1.0, 0.999, 1.0, 1.0); } else { rampfunc->AddHSVSegment( 0.0, (i == 0 ? 0.0 : hsv[0]), (i == 1 ? 0.0 : hsv[1]), (i == 2 ? 0.0 : hsv[2]), 1.0, (i == 0 ? 1.0 : hsv[0]), (i == 1 ? 1.0 : hsv[1]), (i == 2 ? 1.0 : hsv[2]) ); } this->HSVSliders[i]->SetColorRampTransferFunction(rampfunc); if (was_created) { rampfunc->Delete(); } this->HSVSliders[i]->SetWholeParameterRange(0.0, 1.0); this->HSVSliders[i]->SetVisibleParameterRange( this->HSVSliders[i]->GetWholeParameterRange()); this->HSVSliders[i]->SetDisplayedWholeParameterRange( 0.0, (i == 0 ? 360.0 : 100.0)); this->HSVSliders[i]->Update(); } } } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::HSVSlidersChangingCallback() { double new_color_hsv[3]; int i; for (i = 0; i < 3; i++) { if (this->HSVSliders[i]) { vtkColorTransferFunction *sliderfunc = this->HSVSliders[i]->GetColorTransferFunction(); if (sliderfunc) { new_color_hsv[i] = *sliderfunc->GetDataPointer(); } } } if (new_color_hsv[0] == this->InternalNewColorAsHSV[0] && new_color_hsv[1] == this->InternalNewColorAsHSV[1] && new_color_hsv[2] == this->InternalNewColorAsHSV[2]) { return; } this->SetInternalNewColorAsHSV(new_color_hsv); double new_color_rgb[3]; vtkMath::HSVToRGB(new_color_hsv, new_color_rgb); this->SetInternalNewColorAsRGB(new_color_rgb); // Update UI (with HSV in mind) if (this->ColorsLabelSet) { this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(0), this->InternalNewColorAsRGB); } this->UpdateSlidersRGB(this->InternalNewColorAsRGB); this->UpdateHexadecimalColorEntry(this->InternalNewColorAsRGB); if (this->ColorSpectrumWidget) { this->ColorSpectrumWidget->SetColorAsHSV(this->InternalNewColorAsHSV); } this->ScheduleUpdateInfoLabel(); this->NewColorChanging(); } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::UpdateColorLabel(vtkKWLabel *label, double rgb[3]) { if (label) { label->SetBackgroundColor(rgb); double hsv[3]; vtkMath::RGBToHSV(rgb, hsv); static char buffer[128]; sprintf( buffer, "#%02x%02x%02x\nRGB: [%1.2f, %1.2f, %1.2f]\nHSV: [%1.2f, %1.2f, %1.2f]", vtkMath::Round(rgb[0] * 255.0), vtkMath::Round(rgb[1] * 255.0), vtkMath::Round(rgb[2] * 255.0), rgb[0], rgb[1], rgb[2], hsv[0], hsv[1], hsv[2]); label->SetBalloonHelpString(buffer); } } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::UpdateHexadecimalColorEntry(double rgb[3]) { if (this->HexadecimalColorEntry) { this->HexadecimalColorEntry->GetWidget()->SetHexadecimalValueAsRGB( vtkMath::Round(rgb[0] * 255.0), vtkMath::Round(rgb[1] * 255.0), vtkMath::Round(rgb[2] * 255.0)); } } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::UpdateInfoLabel() { if (!this->InfoLabel || !this->InfoLabel->IsCreated()) { return; } if (this->ColorSpectrumWidget && this->ColorSpectrumWidget->IsMapped() && this->ColorSpectrumWidget->GetFixedAxis() == vtkKWColorSpectrumWidget::FixedAxisV && this->InternalNewColorAsHSV[2] == 0.0) { this->InfoLabel->LabelVisibilityOn(); this->InfoLabel->GetWidget()->SetText( "The spectrum widget on the right will appear black when interpolating " "Hue (H) and Saturation (S) over Value (V) = 0." ); return; } this->InfoLabel->GetWidget()->SetText(NULL); this->InfoLabel->LabelVisibilityOff(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::ScheduleUpdateInfoLabel() { // Already scheduled if (this->Internals->ScheduleUpdateInfoLabelTimerId.size() || !this->IsCreated()) { return; } this->Internals->ScheduleUpdateInfoLabelTimerId = this->Script( "after 500 {catch {%s UpdateInfoLabelCallback}}", this->GetTclName()); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::UpdateInfoLabelCallback() { if (!this->GetApplication() || this->GetApplication()->GetInExit() || !this->IsAlive()) { return; } this->UpdateInfoLabel(); this->Internals->ScheduleUpdateInfoLabelTimerId = ""; } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::HexadecimalColorEntryCallback(const char*) { if (this->HexadecimalColorEntry) { int r, g, b; this->HexadecimalColorEntry->GetWidget()->GetHexadecimalValueAsRGB( r, g, b); if (r >= 0 && g >= 0 && b >= 0) { this->SetNewColorAsRGB( (double)r / 255.0, (double)g / 255.0, (double)b / 255.0); } } } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::FavoritesColorPresetApplyCallback(int id) { if (this->FavoritesColorPresetSelector && this->FavoritesColorPresetSelector->HasPreset(id)) { double r, g, b, old_r, old_g, old_b, new_r, new_g, new_b; this->FavoritesColorPresetSelector->GetPresetColorAsRGB(id, r, g, b); this->GetNewColorAsRGB(old_r, old_g, old_b); this->SetNewColorAsRGB(r, g, b); this->GetNewColorAsRGB(new_r, new_g, new_b); if (old_r != new_r || old_g != new_g || old_b != new_b) { this->NewColorChanged(); } } } //--------------------------------------------------------------------------- int vtkKWColorPickerWidget::FavoritesColorPresetAddCallback() { if (!this->FavoritesColorPresetSelector) { return -1; } int id = this->FavoritesColorPresetSelector->InsertPreset( this->FavoritesColorPresetSelector->GetIdOfNthPreset(0)); this->FavoritesColorPresetUpdateCallback(id); this->FavoritesColorPresetSelector->SelectPreset(id); return id; } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::FavoritesColorPresetUpdateCallback(int id) { if (!this->FavoritesColorPresetSelector) { return; } double r, g, b; this->GetNewColorAsRGB(r, g, b); this->FavoritesColorPresetSelector->SetPresetColorAsRGB(id, r, g, b); // If the comment was already in RGB hexadecimal form, or never set, // update it if (!this->FavoritesColorPresetSelector->GetPresetComment(id) || this->FavoritesColorPresetSelector->HasPresetCommentAsHexadecimalRGB(id)) { this->FavoritesColorPresetSelector->SetPresetCommentAsHexadecimalRGB(id); } } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::HistoryColorPresetApplyCallback(int id) { if (this->HistoryColorPresetSelector && this->HistoryColorPresetSelector->HasPreset(id)) { double r, g, b, old_r, old_g, old_b, new_r, new_g, new_b; this->HistoryColorPresetSelector->GetPresetColorAsRGB(id, r, g, b); this->GetNewColorAsRGB(old_r, old_g, old_b); this->SetNewColorAsRGB(r, g, b); this->GetNewColorAsRGB(new_r, new_g, new_b); if (old_r != new_r || old_g != new_g || old_b != new_b) { this->NewColorChanged(); } } } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::SwatchSelectedCallback( double r, double g, double b) { double old_r, old_g, old_b, new_r, new_g, new_b; this->GetNewColorAsRGB(old_r, old_g, old_b); this->SetNewColorAsRGB(r, g, b); this->GetNewColorAsRGB(new_r, new_g, new_b); if (old_r != new_r || old_g != new_g || old_b != new_b) { this->NewColorChanged(); } } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::CurrentColorCallback() { if (!this->ColorsLabelSet) { return; } double r, g, b, old_r, old_g, old_b, new_r, new_g, new_b; this->ColorsLabelSet->GetWidget(1)->GetBackgroundColor(&r, &g, &b); this->GetNewColorAsRGB(old_r, old_g, old_b); this->SetNewColorAsRGB(r, g, b); this->GetNewColorAsRGB(new_r, new_g, new_b); if (old_r != new_r || old_g != new_g || old_b != new_b) { this->NewColorChanged(); } } //--------------------------------------------------------------------------- void vtkKWColorPickerWidget::ColorSpectrumChangingCallback() { if (!this->ColorSpectrumWidget) { return; } double r, g, b; double h, s, v; switch (this->ColorSpectrumWidget->GetFixedAxis()) { case vtkKWColorSpectrumWidget::FixedAxisR: case vtkKWColorSpectrumWidget::FixedAxisG: case vtkKWColorSpectrumWidget::FixedAxisB: this->ColorSpectrumWidget->GetColorAsRGB(r, g, b); if (r == this->InternalNewColorAsRGB[0] && g == this->InternalNewColorAsRGB[1] && b == this->InternalNewColorAsRGB[2]) { return; } this->SetInternalNewColorAsRGB(r, g, b); vtkMath::RGBToHSV(r, g, b, &h, &s, &v); this->SetInternalNewColorAsHSV(h, s, v); // Update UI (with RGB in mind) if (this->ColorsLabelSet) { this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(0), this->InternalNewColorAsRGB); } this->UpdateSlidersRGB(this->InternalNewColorAsRGB); this->UpdateHexadecimalColorEntry(this->InternalNewColorAsRGB); this->UpdateSlidersHSV(this->InternalNewColorAsHSV); this->ScheduleUpdateInfoLabel(); this->NewColorChanging(); break; case vtkKWColorSpectrumWidget::FixedAxisH: case vtkKWColorSpectrumWidget::FixedAxisS: case vtkKWColorSpectrumWidget::FixedAxisV: this->ColorSpectrumWidget->GetColorAsHSV(h, s, v); if (h == this->InternalNewColorAsHSV[0] && s == this->InternalNewColorAsHSV[1] && v == this->InternalNewColorAsHSV[2]) { return; } this->SetInternalNewColorAsHSV(h, s, v); vtkMath::HSVToRGB(h, s, v, &r, &g, &b); this->SetInternalNewColorAsRGB(r, g, b); // Update UI (with HSV in mind) if (this->ColorsLabelSet) { this->UpdateColorLabel( this->ColorsLabelSet->GetWidget(0), this->InternalNewColorAsRGB); } this->UpdateSlidersRGB(this->InternalNewColorAsRGB); this->UpdateHexadecimalColorEntry(this->InternalNewColorAsRGB); this->UpdateSlidersHSV(this->InternalNewColorAsHSV); this->ScheduleUpdateInfoLabel(); this->NewColorChanging(); break; } } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetColorSpectrumVisibility(int arg) { if (this->ColorSpectrumVisibility == arg) { return; } this->ColorSpectrumVisibility = arg; this->Modified(); if (this->Notebook) { this->Notebook->SetPageVisibility( NULL, VTK_KW_COLOR_PICKER_WIDGET_SPECTRUM_TAG, this->ColorSpectrumVisibility); } this->Pack(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetColorSwatchesVisibility(int arg) { if (this->ColorSwatchesVisibility == arg) { return; } this->ColorSwatchesVisibility = arg; this->Modified(); if (this->Notebook) { this->Notebook->SetPageVisibility( NULL, VTK_KW_COLOR_PICKER_WIDGET_COLOR_SWATCHES_TAG, this->ColorSwatchesVisibility); } this->Pack(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetFavoritesVisibility(int arg) { if (this->FavoritesVisibility == arg) { return; } this->FavoritesVisibility = arg; this->Modified(); if (this->Notebook) { this->Notebook->SetPageVisibility( NULL, VTK_KW_COLOR_PICKER_WIDGET_FAVORITES_TAG, this->FavoritesVisibility); } this->Pack(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetHistoryVisibility(int arg) { if (this->HistoryVisibility == arg) { return; } this->HistoryVisibility = arg; this->Modified(); if (this->Notebook) { this->Notebook->SetPageVisibility( NULL, VTK_KW_COLOR_PICKER_WIDGET_HISTORY_TAG, this->HistoryVisibility); } this->Pack(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::SetCompactMode(int arg) { if (this->CompactMode == arg) { return; } this->CompactMode = arg; this->Modified(); this->InvokeEvent( vtkKWColorPickerWidget::CompactModeChangedEvent, this->EventCallData); this->AdjustToCompactMode(); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::ToggleCompactMode() { this->SetCompactMode(this->CompactMode ? 0 : 1); } //---------------------------------------------------------------------------- vtkKWColorPresetSelector* vtkKWColorPickerWidget::GetFavoritesColorPresetSelector() { return this->FavoritesColorPresetSelector; } //---------------------------------------------------------------------------- vtkKWColorPresetSelector* vtkKWColorPickerWidget::GetHistoryColorPresetSelector() { return this->HistoryColorPresetSelector; } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::ProcessCallbackCommandEvents(vtkObject *caller, unsigned long event, void *calldata) { const char **cargs = (const char**)calldata; int tag; if (caller == this->Notebook) { switch (event) { case vtkKWEvent::NotebookRaisePageEvent: tag = (atoi)(cargs[1]); if (tag == VTK_KW_COLOR_PICKER_WIDGET_FAVORITES_TAG) { this->CreateFavoritesColorPresetSelector(); } else if (tag == VTK_KW_COLOR_PICKER_WIDGET_HISTORY_TAG) { this->CreateHistoryColorPresetSelector(); } this->ScheduleUpdateInfoLabel(); break; } } if (caller == this->ColorSpectrumWidget) { switch (event) { case vtkKWColorSpectrumWidget::ColorChangingEvent: this->ColorSpectrumChangingCallback(); break; case vtkKWColorSpectrumWidget::ColorChangedEvent: this->NewColorChanged(); break; } } if (caller == this->RGBSliders[0] || caller == this->RGBSliders[1] || caller == this->RGBSliders[2]) { switch (event) { case vtkKWParameterValueFunctionEditor::FunctionChangingEvent: this->RGBSlidersChangingCallback(); break; case vtkKWParameterValueFunctionEditor::FunctionChangedEvent: this->NewColorChanged(); break; } } if (caller == this->HSVSliders[0] || caller == this->HSVSliders[1] || caller == this->HSVSliders[2]) { switch (event) { case vtkKWParameterValueFunctionEditor::FunctionChangingEvent: this->HSVSlidersChangingCallback(); break; case vtkKWParameterValueFunctionEditor::FunctionChangedEvent: this->NewColorChanged(); break; } } this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->SlidersFrame); this->PropagateEnableState(this->RGBSlidersFrame); this->PropagateEnableState(this->HSVSlidersFrame); int i; for (i = 0; i < 3; i++) { this->PropagateEnableState(this->RGBSliders[i]); this->PropagateEnableState(this->HSVSliders[i]); } for (i = 0; i < 6; i++) { this->PropagateEnableState(this->FixedAxisRadioButton[i]); this->PropagateEnableState(this->SliderUnitLabel[i]); } this->PropagateEnableState(this->Notebook); this->PropagateEnableState(this->HexadecimalColorEntry); this->PropagateEnableState(this->ColorSpectrumWidget); this->PropagateEnableState(this->ColorSwatchesWidget); this->PropagateEnableState(this->FavoritesColorPresetSelector); this->PropagateEnableState(this->HistoryColorPresetSelector); this->PropagateEnableState(this->ColorsFrame); this->PropagateEnableState(this->ColorsLabelSet); this->PropagateEnableState(this->ColorsNameLabelSet); this->PropagateEnableState(this->InfoLabel); this->PropagateEnableState(this->CompactModeButton); } //---------------------------------------------------------------------------- void vtkKWColorPickerWidget::PrintSelf(ostream& os, vtkIndent indent) { os << indent << "ColorSpectrumVisibility: " << (this->ColorSpectrumVisibility ? "On" : "Off") << endl; os << indent << "ColorSwatchesVisibility: " << (this->ColorSwatchesVisibility ? "On" : "Off") << endl; os << indent << "FavoritesVisibility: " << (this->FavoritesVisibility ? "On" : "Off") << endl; os << indent << "HistoryVisibility: " << (this->HistoryVisibility ? "On" : "Off") << endl; this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWColorPickerDialog.h0000644000175000017500000000541011171417722021560 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWColorPickerDialog.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWColorPickerDialog - a color picker dialog. // .SECTION Description // A widget that can be used to pick a color. // This dialog is just a small standalone toplevel that embeds a // vtkKWColorPickerWidget. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWColorPickerWidget #ifndef __vtkKWColorPickerDialog_h #define __vtkKWColorPickerDialog_h #include "vtkKWDialog.h" class vtkKWApplication; class vtkKWColorPickerWidget; class vtkKWPushButton; class KWWidgets_EXPORT vtkKWColorPickerDialog : public vtkKWDialog { public: static vtkKWColorPickerDialog* New(); vtkTypeRevisionMacro(vtkKWColorPickerDialog,vtkKWDialog); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the internal color picker widget vtkGetObjectMacro(ColorPickerWidget, vtkKWColorPickerWidget); // Description: // Callback. Confirm the action and close this dialog virtual void OK(); // Description: // Display the dialog. virtual void Display(); // Description: // Update the "enable" state of the object and its internal parts. virtual void UpdateEnableState(); protected: vtkKWColorPickerDialog(); ~vtkKWColorPickerDialog(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Member variables vtkKWColorPickerWidget* ColorPickerWidget; vtkKWPushButton* OKButton; vtkKWPushButton* CancelButton; // Description: // Processes the events that are passed through CallbackCommand (or others). // Subclasses can oberride this method to process their own events, but // should call the superclass too. virtual void ProcessCallbackCommandEvents( vtkObject *caller, unsigned long event, void *calldata); // Description: // Update Size virtual void UpdateSize(); private: vtkKWColorPickerDialog(const vtkKWColorPickerDialog&); // Not implemented void operator=(const vtkKWColorPickerDialog&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWUserInterfacePanel.h0000644000175000017500000001672711131233223021744 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWUserInterfacePanel.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWUserInterfacePanel - a user interface panel. // .SECTION Description // This class is used to abstract the way an interface "panel" can be // subdivided into "pages" (i.e. "sections"). It allows specific GUI parts of // an application to be encapsulated inside independent panels. Panels are // then associated to a user interface manager (see vtkKWUserInterfaceManager) // which is responsible for grouping them inside a widget and handling user // interaction so that panels and their pages can be selected in more or less // fancy ways. If the user interface manager uses a notebook under the hood, // then this class is likely to receive a notebook's page when it will request // for a page from the manager. If the manager chooses for a flat GUI, then // this class is likely to receive a simple frame that will be stacked by the // manager on top of other pages. // This class is not a widget, it can not be mapped, the manager is the // place where a concrete widget is set and used as the root of all panels (see // vtkKWUserInterfaceManagerNotebook for example). What you need to do // is to set the UserInterfaceManager's Ivar to a manager, and the rest should // be taken care of (i.e. the panel is automatically added to the manager, // and if the panel is not created the first time one if its pages is shown or // raised, the panel's Create() method is automatically called by the manager, // allowing the creation of the panel to be delayed until it is really needed). // You should not use the manager's API to add the panel, add or raise pages, // etc, just use this panel's API and calls will be propagated to the // right manager with the proper arguments). // .SECTION See Also // vtkKWUserInterfaceManager vtkKWUserInterfaceManagerNotebook #ifndef __vtkKWUserInterfacePanel_h #define __vtkKWUserInterfacePanel_h #include "vtkKWObject.h" class vtkKWIcon; class vtkKWUserInterfaceManager; class vtkKWWidget; class KWWidgets_EXPORT vtkKWUserInterfacePanel : public vtkKWObject { public: static vtkKWUserInterfacePanel* New(); vtkTypeRevisionMacro(vtkKWUserInterfacePanel,vtkKWObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set the user interface manager. This automatically adds the // panel to the manager. If you want to remove this panel from the manager, // set the manager to NULL (it is done automatically by the destructor), // or call RemovePanel from the manager so that you can add it back later. // Note that ownership is transferred to the manager by incrementing // (and decrementing later on) the ref count of the panel in // vtkKWUserInterfaceManager's AddPanel and RemovePanel methods. virtual void SetUserInterfaceManager(vtkKWUserInterfaceManager*); vtkGetObjectMacro(UserInterfaceManager, vtkKWUserInterfaceManager); // Description: // Set the panel name. Can be used to add the panel to a menu, etc. vtkGetStringMacro(Name); vtkSetStringMacro(Name); // Description: // Create the interface objects. Note that if the panel is not created // the first time one if its pages is shown or raised, this method is // automatically called by the manager, allowing the creation of the // panel to be delayed until it is really needed. In the same way, if // the user interface manager has not been created at this point, it // is automatically created now (see vtkKWUserInterfaceManager::Create()). virtual void Create(); virtual int IsCreated(); // Description: // Enable/Disable this panel. This should propagate SetEnabled() calls to the // internal widgets. virtual void SetEnabled(int); vtkBooleanMacro(Enabled, int); vtkGetMacro(Enabled, int); // Description: // Add/remove a page to/from the panel (this will, in turn, instructs the // manager to reserve or remove a page for this given panel). // balloon specifies the balloon help for that page, icon is an optional // icon in case it is supported by the manager later on. // Return a unique positive ID for the page that was reserved/removed, // or < 0 on error. virtual int AddPage(const char *title, const char *balloon = 0, vtkKWIcon *icon = 0); virtual int RemovePage(const char *title); // Description: // Set a page's title, balloon help and icon. virtual void SetPageTitle(int id, const char *title); virtual void SetPageBalloonHelpString(int id, const char *str); virtual void SetPageIcon(int id, vtkKWIcon *icon); virtual void SetPageIconToPredefinedIcon(int id, int icon_index); // Description: // Retrieve the widget corresponding to a given page added to the panel. // This can be done through the unique page ID, or using the page title. // The user UI components should be inserted into this widget. // Return NULL on error. virtual vtkKWWidget *GetPageWidget(int id); virtual vtkKWWidget *GetPageWidget(const char *title); // Description: // Retrieve the parent widget of the pages associated to the panel. It is // the unique widget that is common to all pages in the chain of parents. virtual vtkKWWidget *GetPagesParentWidget(); // Description: // Raise a page added to the panel. This can be done through the unique // page ID, or using the page title. Note that if the panel has not been // created at this point, the manager will call the panel's Create() // method automatically, allowing the creation of the panel to be delayed // until it is really needed. virtual void RaisePage(int id); virtual void RaisePage(const char *title); // Description: // Show a panel. It will make sure the pages added to this panel are shown. // Note that if the panel has not been created at this point, the manager // will call the panel's Create() method automatically, allowing the // creation of the panel to be delayed until it is really needed. // Raise() behaves like Show(), but it will also instruct the manager to // bring up the first page of the panel to the front. // IsVisible() will check if the pages of this panel are visible/shown. // Return 1 on success, 0 on error. virtual int Show(); virtual int Raise(); virtual int IsVisible(); // Description: // Refresh the interface. virtual void Update(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState() {}; protected: vtkKWUserInterfacePanel(); ~vtkKWUserInterfacePanel(); vtkKWUserInterfaceManager *UserInterfaceManager; char *Name; private: int Enabled; int PanelIsCreated; vtkKWUserInterfacePanel(const vtkKWUserInterfacePanel&); // Not implemented void operator=(const vtkKWUserInterfacePanel&); // Not Implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWCompositeWidget.cxx0000644000175000017500000000251210424463536021711 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWCompositeWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWCompositeWidget.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWCompositeWidget ); vtkCxxRevisionMacro(vtkKWCompositeWidget, "$Revision: 1.5 $"); //---------------------------------------------------------------------------- void vtkKWCompositeWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); } //---------------------------------------------------------------------------- void vtkKWCompositeWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWMatrixWidget.h0000644000175000017500000001307210540353637020642 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWMatrixWidget.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWMatrixWidget - matrix widget // .SECTION Description // vtkKWMatrixWidget is a widget containing entries that help view and // edit a matrix. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. #ifndef __vtkKWMatrixWidget_h #define __vtkKWMatrixWidget_h #include "vtkKWCompositeWidget.h" class vtkKWEntrySet; class KWWidgets_EXPORT vtkKWMatrixWidget : public vtkKWCompositeWidget { public: static vtkKWMatrixWidget* New(); vtkTypeRevisionMacro(vtkKWMatrixWidget,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the matrix size. Default to 1x1. virtual void SetNumberOfColumns(int col); vtkGetMacro(NumberOfColumns, int); virtual void SetNumberOfRows(int col); vtkGetMacro(NumberOfRows, int); // Description: // Set/Get the value of a given element. virtual void SetElementValue(int row, int col, const char *val); virtual const char* GetElementValue(int row, int col); virtual void SetElementValueAsInt(int row, int col, int val); virtual int GetElementValueAsInt(int row, int col); virtual void SetElementValueAsDouble(int row, int col, double val); virtual double GetElementValueAsDouble(int row, int col); // Description: // The width is the number of charaters each element can fit. virtual void SetElementWidth(int width); vtkGetMacro(ElementWidth, int); // Description: // Set/Get readonly flag. This flags makes each element read only. virtual void SetReadOnly(int); vtkBooleanMacro(ReadOnly, int); vtkGetMacro(ReadOnly, int); // Description: // Restrict the value of an element to a given type // (integer, double, or no restriction). //BTX enum { RestrictNone = 0, RestrictInteger, RestrictDouble }; //ETX vtkGetMacro(RestrictElementValue, int); virtual void SetRestrictElementValue(int); virtual void SetRestrictElementValueToInteger(); virtual void SetRestrictElementValueToDouble(); virtual void SetRestrictElementValueToNone(); // Description: // Specifies a command to be invoked when the value of an element in the // matrix has changed. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the element location, i.e. its row and column indices: int, int // - the element's new value: const char* virtual void SetElementChangedCommand(vtkObject *object, const char *method); // Description: // Events. The ElementChangedEvent is triggered when the value of an // element in the matrix has changed. // The following parameters are also passed as client data: // - the element location, i.e. its row and column indices: int, int // - the element's new value: const char* // Note that given the heterogeneous nature of types passed as client data, // you should treat it as an array of void*[3], each one a pointer to // the parameter (i.e., &int, &int, &const char*). //BTX enum { ElementChangedEvent = 10000 }; //ETX // Description: // Specify when ElementChangedCommand should be invoked. Default to losing // focus and return key in the entry. //BTX enum { TriggerOnFocusOut = 1, TriggerOnReturnKey = 2, TriggerOnAnyChange = 4 }; //ETX vtkGetMacro(ElementChangedCommandTrigger, int); virtual void SetElementChangedCommandTrigger(int); virtual void SetElementChangedCommandTriggerToReturnKeyAndFocusOut(); virtual void SetElementChangedCommandTriggerToAnyChange(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. virtual void ElementChangedCallback(int id, const char *value); protected: vtkKWMatrixWidget(); virtual ~vtkKWMatrixWidget(); int NumberOfColumns; int NumberOfRows; int ElementWidth; int ReadOnly; int RestrictElementValue; int ElementChangedCommandTrigger; // Description: // Create the widget. virtual void CreateWidget(); virtual void UpdateWidget(); vtkKWEntrySet *EntrySet; char *ElementChangedCommand; void InvokeElementChangedCommand(int row, int col, const char *value); private: vtkKWMatrixWidget(const vtkKWMatrixWidget&); // Not implemented void operator=(const vtkKWMatrixWidget&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWMaterialPropertyWidget.h0000644000175000017500000002106410424463536022702 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWMaterialPropertyWidget.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWMaterialPropertyWidget - widget to control the material property of a volume // .SECTION Description #ifndef __vtkKWMaterialPropertyWidget_h #define __vtkKWMaterialPropertyWidget_h #include "vtkKWCompositeWidget.h" class vtkKWFrame; class vtkKWLabel; class vtkKWFrameWithLabel; class vtkKWLabelWithLabel; class vtkKWPushButtonSetWithLabel; class vtkKWPopupButtonWithLabel; class vtkKWPushButton; class vtkKWScaleWithEntry; class vtkKWMaterialPropertyWidgetInternals; class KWWidgets_EXPORT vtkKWMaterialPropertyWidget : public vtkKWCompositeWidget { public: vtkTypeRevisionMacro(vtkKWMaterialPropertyWidget, vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Display the UI as a popup (default is off). The pushbutton will display // a representation of the current properties. // This has to be called before Create(). vtkSetMacro(PopupMode, int); vtkGetMacro(PopupMode, int); vtkBooleanMacro(PopupMode, int); vtkGetObjectMacro(PopupButton, vtkKWPopupButtonWithLabel); // Description: // Refresh the interface given the value extracted from the current widget. virtual void Update(); // Description: // Update the preview according to current settings virtual void UpdatePreview(); // Description: // Set/Get the size of the preview, presets and popup preview images virtual void SetPreviewSize(int); virtual void SetPresetSize(int); virtual void SetPopupPreviewSize(int); vtkGetMacro(PreviewSize, int); vtkGetMacro(PresetSize, int); vtkGetMacro(PopupPreviewSize, int); // Description: // Set/Get the grid opacity in the preview/presets virtual void SetGridOpacity(double); vtkGetMacro(GridOpacity, double); // Description: // Set/Get the color of the preview/presets. vtkGetVector3Macro(MaterialColor, double); void SetMaterialColor(double r, double g, double b); void SetMaterialColor(double color[3]) { this->SetMaterialColor(color[0], color[1], color[2]); } // Description: // Set/Get the lighting parameters visibility. // If set to Off, none of the ambient, diffuse, specular (etc.) scales // will be displayed. virtual void SetLightingParametersVisibility(int); vtkBooleanMacro(LightingParametersVisibility, int); vtkGetMacro(LightingParametersVisibility, int); // Description: // Set/Get the event invoked when the property is changed/changing. // Defaults to vtkKWEvent::MaterialPropertyChanged/ingEvent, this default // is likely to change in subclasses to reflect what kind of property // is changed (vtkKWEvent::VolumeMaterialPropertyChangedEvent for example). vtkSetMacro(PropertyChangedEvent, int); vtkGetMacro(PropertyChangedEvent, int); vtkSetMacro(PropertyChangingEvent, int); vtkGetMacro(PropertyChangingEvent, int); // Description: // Specifies commands to associate with the widget. // 'PropertyChangedCommand' is invoked when the property has // changed (i.e. at the end of the user interaction). // 'PropertyChangingCommand' is invoked when the selected color is // changing (i.e. during the user interaction). // The need for a '...ChangedCommand' and '...ChangingCommand' can be // explained as follows: the former can be used to be notified about any // changes made to this widget *after* the corresponding user interaction has // been performed (say, after releasing the mouse button that was dragging // a slider, or after clicking on a checkbutton). The later can be set // *additionally* to be notified about the intermediate changes that // occur *during* the corresponding user interaction (say, *while* dragging // a slider). While setting '...ChangedCommand' is enough to be notified // about any changes, setting '...ChangingCommand' is an application-specific // choice that is likely to depend on how fast you want (or can) answer to // rapid changes occuring during a user interaction, if any. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetPropertyChangedCommand( vtkObject *object, const char *method); virtual void SetPropertyChangingCommand( vtkObject *object, const char *method); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void PropertyChangingCallback(double value); virtual void PropertyChangedCallback(double value); virtual void PresetMaterialCallback(int preset_idx); protected: vtkKWMaterialPropertyWidget(); ~vtkKWMaterialPropertyWidget(); // Description: // Create the widget. virtual void CreateWidget(); int PopupMode; int PreviewSize; int PresetSize; int PopupPreviewSize; double GridOpacity; int LightingParametersVisibility; double MaterialColor[3]; // Description: // Events int PropertyChangedEvent; int PropertyChangingEvent; // Description: // Commands char *PropertyChangedCommand; char *PropertyChangingCommand; virtual void InvokePropertyChangedCommand(); virtual void InvokePropertyChangingCommand(); // Presets //BTX class Preset { public: double Ambient; double Diffuse; double Specular; double SpecularPower; char *HelpString; Preset() { this->HelpString = 0; }; }; // PIMPL Encapsulation for STL containers vtkKWMaterialPropertyWidgetInternals *Internals; friend class vtkKWMaterialPropertyWidgetInternals; //ETX // UI vtkKWPopupButtonWithLabel *PopupButton; vtkKWFrameWithLabel *MaterialPropertiesFrame; vtkKWFrame *ControlFrame; vtkKWFrame *LightingFrame; vtkKWScaleWithEntry *AmbientScale; vtkKWScaleWithEntry *DiffuseScale; vtkKWScaleWithEntry *SpecularScale; vtkKWScaleWithEntry *SpecularPowerScale; vtkKWFrame *PresetsFrame; vtkKWLabelWithLabel *PreviewLabel; vtkKWPushButtonSetWithLabel *PresetPushButtonSet; // Description: // Pack virtual void Pack(); // Description: // Create a preview image given some material properties virtual void CreateImage(unsigned char *data, double ambient, double diffuse, double specular, double specular_power, int size); // Description: // Send an event representing the state of the widget virtual void SendStateEvent(int event); // Description: // Add default presets virtual void AddDefaultPresets(); // Description: // Create the presets virtual void CreatePresets(); // Description: // Update the popup preview according to current settings virtual void UpdatePopupPreview(); // Description: // Update the property from the interface values or a preset // Return 1 if the property was modified, 0 otherwise virtual int UpdatePropertyFromInterface() = 0; virtual int UpdatePropertyFromPreset(const Preset *preset) = 0; // Description: // Update the scales from a preset virtual int UpdateScalesFromPreset(const Preset *preset); virtual void UpdateScales(double ambient, double diffuse, double specular, double specular_power); // Description: // Return 1 if the controls should be enabled. virtual int AreControlsEnabled() { return 1; }; private: vtkKWMaterialPropertyWidget(const vtkKWMaterialPropertyWidget&); //Not implemented void operator=(const vtkKWMaterialPropertyWidget&); //Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWProgressGauge.h0000644000175000017500000001070711035305260020776 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWProgressGauge.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWProgressGauge - a horizontal progress bar widget // .SECTION Description // A simple widget used for displaying a progress bar with a percent value // text in the center of the widget. #ifndef __vtkKWProgressGauge_h #define __vtkKWProgressGauge_h #include "vtkKWCompositeWidget.h" class vtkKWCanvas; class vtkKWProgressGaugeInternals; class KWWidgets_EXPORT vtkKWProgressGauge : public vtkKWCompositeWidget { public: static vtkKWProgressGauge* New(); vtkTypeRevisionMacro(vtkKWProgressGauge,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the percentage displayed for the primary progress gauge. // This number is clamped between 0.0 and 100.0. // Note: setting the progress to zero resets the gauge to its nominal // blank appearance. virtual void SetValue(double value); virtual double GetValue(); // Description: // Set/Get the percentage displayed for the primary (ranked 0) and // the secondary progress gauges. If rank = 0, calling this method is // the same as calling the SetValue method. // This number is clamped between 0.0 and 100.0. // Note: setting the progress to zero resets the gauge to its nominal // blank appearance. // All progress gauges are stacked vertically on top of each other, with the // lower rank at the top by default (this can be changed with // the SetPrimaryGaugePosition method). Space for the primary gauge // (ranked 0) is always allocated. It is not for secondary gauges which // value is 0.0 unless a higher rank gauge is != 0.0. virtual void SetNthValue(int rank, double value); virtual double GetNthValue(int rank); // Description: // Set/Get the width and height of the widget. // The height parameter is ignored if ExpandHeight is set to On. virtual void SetWidth(int width); vtkGetMacro(Width, int); virtual void SetHeight(int height); vtkGetMacro(Height, int); // Description: // Set/Get if the height of the gauge should be automatically adjusted // to fill the available vertical space. The widget should be packed // accordingly to expand automatically. Check MinimumHeight too. vtkBooleanMacro(ExpandHeight, int); virtual void SetExpandHeight(int); vtkGetMacro(ExpandHeight, int); // Description: // Set/Get the minimum height of the widget. // This value is ignored if ExpandHeight is set to Off. If set to On, // the height computed from the available vertical space will not be any // smaller than this minimum height. virtual void SetMinimumHeight(int height); vtkGetMacro(MinimumHeight, int); // Description: // Set/Get the color of the progress bar, the default is blue. virtual void SetBarColor(double r, double g, double b); virtual void SetBarColor(double rgb[3]) { this->SetBarColor(rgb[0], rgb[1], rgb[2]); } vtkGetVectorMacro(BarColor,double,3); // Description: // Set/Get the position of the primary gauge (rank 0). // If on top, higher rank are stacked below. If at the bottom, higher rank // are stacked on top. //BTX enum { GaugePositionTop = 0, GaugePositionBottom }; //ETX virtual void SetPrimaryGaugePosition(int); vtkGetMacro(PrimaryGaugePosition, int); virtual void SetPrimaryGaugePositionToTop(); virtual void SetPrimaryGaugePositionToBottom(); // Description: // Callbacks. Internal, do not use. virtual void ConfigureCallback(); protected: vtkKWProgressGauge(); ~vtkKWProgressGauge(); // Description: // Create the widget. virtual void CreateWidget(); virtual void Redraw(); int Width; int Height; int MinimumHeight; double BarColor[3]; double Value; int ExpandHeight; int PrimaryGaugePosition; vtkKWCanvas *Canvas; // PIMPL Encapsulation for STL containers //BTX vtkKWProgressGaugeInternals *Internals; //ETX private: vtkKWProgressGauge(const vtkKWProgressGauge&); // Not implemented void operator=(const vtkKWProgressGauge&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWSeparator.h0000644000175000017500000000407710424463540020173 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWSeparator.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWSeparator - a separator widget. // .SECTION Description // A simple separator widget that can be used to separate widgets // using a simple horizontal or vertical line. // .SECTION See Also // vtkKWFrame #ifndef __vtkKWSeparator_h #define __vtkKWSeparator_h #include "vtkKWFrame.h" class KWWidgets_EXPORT vtkKWSeparator : public vtkKWFrame { public: static vtkKWSeparator* New(); vtkTypeRevisionMacro(vtkKWSeparator, vtkKWFrame); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the orientation of the separator. //BTX enum { OrientationHorizontal = 0, OrientationVertical = 1 }; //ETX virtual void SetOrientation(int); vtkGetMacro(Orientation, int); virtual void SetOrientationToHorizontal() { this->SetOrientation(vtkKWSeparator::OrientationHorizontal); }; virtual void SetOrientationToVertical() { this->SetOrientation(vtkKWSeparator::OrientationVertical); }; // Description: // Set/Get the thickness of the separator. // Do not use the superclass's SetWidth and SetHeight method to set the // thickness. virtual void SetThickness(int); vtkGetMacro(Thickness, int); protected: vtkKWSeparator(); ~vtkKWSeparator() {}; // Description: // Create the widget. virtual void CreateWidget(); int Orientation; int Thickness; // Description: // Update the aspect of the widget virtual void UpdateAspect(); private: vtkKWSeparator(const vtkKWSeparator&); // Not implemented void operator=(const vtkKWSeparator&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWScrollbar.cxx0000644000175000017500000001616710750726354020543 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWScrollbar.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWScrollbar.h" #include "vtkKWOptions.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWScrollbar); vtkCxxRevisionMacro(vtkKWScrollbar, "$Revision: 1.13 $"); //---------------------------------------------------------------------------- void vtkKWScrollbar::CreateWidget() { // Call the superclass to set the appropriate flags then create manually const char *options = #ifdef _WIN32 "-highlightthickness 0 -bd 2"; #else "-highlightthickness 0 -width 13 -bd 2"; #endif if (!vtkKWWidget::CreateSpecificTkWidget(this, "scrollbar", options)) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetOrientation(int orientation) { this->SetConfigurationOption( "-orient", vtkKWOptions::GetOrientationAsTkOptionValue(orientation)); } void vtkKWScrollbar::SetOrientationToHorizontal() { this->SetOrientation(vtkKWOptions::OrientationHorizontal); }; void vtkKWScrollbar::SetOrientationToVertical() { this->SetOrientation(vtkKWOptions::OrientationVertical); }; //---------------------------------------------------------------------------- int vtkKWScrollbar::GetOrientation() { return vtkKWOptions::GetOrientationFromTkOptionValue( this->GetConfigurationOption("-orient")); } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetCommand(vtkObject *object, const char *method) { if (this->IsCreated()) { char *command = NULL; this->SetObjectMethodCommand(&command, object, method); this->SetConfigurationOption("-command", command); delete [] command; } } //---------------------------------------------------------------------------- void vtkKWScrollbar::GetBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWScrollbar::GetBackgroundColor() { return this->GetConfigurationOptionAsColor("-background"); } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- void vtkKWScrollbar::GetForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWScrollbar::GetForegroundColor() { #ifdef _WIN32 return NULL; #else return this->GetConfigurationOptionAsColor("-foreground"); #endif } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetForegroundColor(double r, double g, double b) { #ifdef _WIN32 (void)r; (void)g; (void)b; #else this->SetConfigurationOptionAsColor("-foreground", r, g, b); #endif } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetHighlightThickness(int width) { this->SetConfigurationOptionAsInt("-highlightthickness", width); } //---------------------------------------------------------------------------- int vtkKWScrollbar::GetHighlightThickness() { return this->GetConfigurationOptionAsInt("-highlightthickness"); } //---------------------------------------------------------------------------- void vtkKWScrollbar::GetActiveBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWScrollbar::GetActiveBackgroundColor() { return this->GetConfigurationOptionAsColor("-activebackground"); } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetActiveBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetBorderWidth(int width) { this->SetConfigurationOptionAsInt("-bd", width); } //---------------------------------------------------------------------------- int vtkKWScrollbar::GetBorderWidth() { return this->GetConfigurationOptionAsInt("-bd"); } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetWidth(int width) { this->SetConfigurationOptionAsInt("-width", width); } //---------------------------------------------------------------------------- int vtkKWScrollbar::GetWidth() { return this->GetConfigurationOptionAsInt("-width"); } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetRelief(int relief) { this->SetConfigurationOption( "-relief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWScrollbar::SetReliefToRaised() { this->SetRelief(vtkKWOptions::ReliefRaised); }; void vtkKWScrollbar::SetReliefToSunken() { this->SetRelief(vtkKWOptions::ReliefSunken); }; void vtkKWScrollbar::SetReliefToFlat() { this->SetRelief(vtkKWOptions::ReliefFlat); }; void vtkKWScrollbar::SetReliefToRidge() { this->SetRelief(vtkKWOptions::ReliefRidge); }; void vtkKWScrollbar::SetReliefToSolid() { this->SetRelief(vtkKWOptions::ReliefSolid); }; void vtkKWScrollbar::SetReliefToGroove() { this->SetRelief(vtkKWOptions::ReliefGroove); }; //---------------------------------------------------------------------------- int vtkKWScrollbar::GetRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-relief")); } //---------------------------------------------------------------------------- void vtkKWScrollbar::GetTroughColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-troughcolor", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWScrollbar::GetTroughColor() { return this->GetConfigurationOptionAsColor("-troughcolor"); } //---------------------------------------------------------------------------- void vtkKWScrollbar::SetTroughColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-troughcolor", r, g, b); } //---------------------------------------------------------------------------- void vtkKWScrollbar::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWLanguage.h0000644000175000017500000001627710422255217017761 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWLanguage.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWLanguage - language support. // .SECTION Description // vtkKWLanguage provides methods to refer to common languages, as well // as set the current language. #ifndef __vtkKWLanguage_h #define __vtkKWLanguage_h #include "vtkObject.h" #include "vtkKWWidgets.h" // Needed for export symbols directives class KWWidgets_EXPORT vtkKWLanguage : public vtkObject { public: static vtkKWLanguage* New(); vtkTypeRevisionMacro(vtkKWLanguage,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // List of languages IDs. //BTX enum { ABKHAZIAN = 0, AFAR, AFRIKAANS, ALBANIAN, AMHARIC, ARABIC, ARABIC_ALGERIA, ARABIC_BAHRAIN, ARABIC_EGYPT, ARABIC_IRAQ, ARABIC_JORDAN, ARABIC_KUWAIT, ARABIC_LEBANON, ARABIC_LIBYA, ARABIC_MOROCCO, ARABIC_OMAN, ARABIC_QATAR, ARABIC_SAUDI_ARABIA, ARABIC_SUDAN, ARABIC_SYRIA, ARABIC_TUNISIA, ARABIC_UAE, ARABIC_YEMEN, ARMENIAN, ASSAMESE, AYMARA, AZERI, AZERI_CYRILLIC, AZERI_LATIN, BASHKIR, BASQUE, BELARUSIAN, BENGALI, BHUTANI, BIHARI, BISLAMA, BRETON, BULGARIAN, BURMESE, CAMBODIAN, CATALAN, CHINESE, CHINESE_SIMPLIFIED, CHINESE_TRADITIONAL, CHINESE_HONGKONG, CHINESE_MACAU, CHINESE_SINGAPORE, CHINESE_TAIWAN, CORSICAN, CROATIAN, CZECH, DANISH, DUTCH, DUTCH_BELGIAN, ENGLISH, ENGLISH_UK, ENGLISH_US, ENGLISH_AUSTRALIA, ENGLISH_BELIZE, ENGLISH_BOTSWANA, ENGLISH_CANADA, ENGLISH_CARIBBEAN, ENGLISH_DENMARK, ENGLISH_EIRE, ENGLISH_JAMAICA, ENGLISH_NEW_ZEALAND, ENGLISH_PHILIPPINES, ENGLISH_SOUTH_AFRICA, ENGLISH_TRINIDAD, ENGLISH_ZIMBABWE, ESPERANTO, ESTONIAN, FAEROESE, FARSI, FIJI, FINNISH, FRENCH, FRENCH_BELGIAN, FRENCH_CANADIAN, FRENCH_LUXEMBOURG, FRENCH_MONACO, FRENCH_SWISS, FRISIAN, GALICIAN, GEORGIAN, GERMAN, GERMAN_AUSTRIAN, GERMAN_BELGIUM, GERMAN_LIECHTENSTEIN, GERMAN_LUXEMBOURG, GERMAN_SWISS, GREEK, GREENLANDIC, GUARANI, GUJARATI, HAUSA, HEBREW, HINDI, HUNGARIAN, ICELANDIC, INDONESIAN, INTERLINGUA, INTERLINGUE, INUKTITUT, INUPIAK, IRISH, ITALIAN, ITALIAN_SWISS, JAPANESE, JAVANESE, KANNADA, KASHMIRI, KASHMIRI_INDIA, KAZAKH, KERNEWEK, KINYARWANDA, KIRGHIZ, KIRUNDI, KONKANI, KOREAN, KURDISH, LAOTHIAN, LATIN, LATVIAN, LINGALA, LITHUANIAN, MACEDONIAN, MALAGASY, MALAY, MALAYALAM, MALAY_BRUNEI_DARUSSALAM, MALAY_MALAYSIA, MALTESE, MANIPURI, MAORI, MARATHI, MOLDAVIAN, MONGOLIAN, NAURU, NEPALI, NEPALI_INDIA, NORWEGIAN_BOKMAL, NORWEGIAN_NYNORSK, OCCITAN, ORIYA, OROMO, PASHTO, POLISH, PORTUGUESE, PORTUGUESE_BRAZILIAN, PUNJABI, QUECHUA, RHAETO_ROMANCE, ROMANIAN, RUSSIAN, RUSSIAN_UKRAINE, SAMOAN, SANGHO, SANSKRIT, SCOTS_GAELIC, SERBIAN, SERBIAN_CYRILLIC, SERBIAN_LATIN, SERBO_CROATIAN, SESOTHO, SETSWANA, SHONA, SINDHI, SINHALESE, SISWATI, SLOVAK, SLOVENIAN, SOMALI, SPANISH, SPANISH_ARGENTINA, SPANISH_BOLIVIA, SPANISH_CHILE, SPANISH_COLOMBIA, SPANISH_COSTA_RICA, SPANISH_DOMINICAN_REPUBLIC, SPANISH_ECUADOR, SPANISH_EL_SALVADOR, SPANISH_GUATEMALA, SPANISH_HONDURAS, SPANISH_MEXICAN, SPANISH_MODERN, SPANISH_NICARAGUA, SPANISH_PANAMA, SPANISH_PARAGUAY, SPANISH_PERU, SPANISH_PUERTO_RICO, SPANISH_URUGUAY, SPANISH_US, SPANISH_VENEZUELA, SUNDANESE, SWAHILI, SWEDISH, SWEDISH_FINLAND, TAGALOG, TAJIK, TAMIL, TATAR, TELUGU, THAI, TIBETAN, TIGRINYA, TONGA, TSONGA, TURKISH, TURKMEN, TWI, UIGHUR, UKRAINIAN, URDU, URDU_INDIA, URDU_PAKISTAN, UZBEK, UZBEK_CYRILLIC, UZBEK_LATIN, VIETNAMESE, VOLAPUK, WELSH, WOLOF, XHOSA, YIDDISH, YORUBA, ZHUANG, ZULU, UNKNOWN // should be the last one }; //ETX // Description: // Set/Get the current language. Setting the language is done by setting // the LC_MESSAGES locale as well as setting the LC_MESSAGES environment // variable. On Windows platform where LC_MESSAGES is not supported, a // call to SetThreadLocale() will change the language accordingly. static void SetCurrentLanguage(int lang); static int GetCurrentLanguage(); // Description: // Get short English name of language (or NULL if unknown/error). static const char* GetLanguageName(int lang); // Description: // Get XPG syntax (language[_territory[.codeset]][@modifier]) from language. // Return XPG description on success, NULL on error or if there is // no known XPG syntax for this language ID. static const char* GetXPGFromLanguage(int lang); // Description: // Get language from XPG (language[_territory[.codeset]][@modifier]). // Return language ID on success, vtkKWLanguage::UNKNOWN on error or if // there is no known language ID for this XPG syntax. static int GetLanguageFromXPG(const char *xpg); // Description: // Get Win32 LANGID from language. // Return the output of MAKELANGID using the primary and secondary // language identifier corresponding to the language passed as parameter, // or MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) if no match was found. // (note that MAKELANGID returns a WORD, which is cast here to an int // for wrapping purposes). static int GetWin32LANGIDFromLanguage(int lang); // Description: // Get language from Win32 LANGID. // Return the language id matching the Win32 primary and secondary language // identifier that were output by MAKELANGID, or vtkKWLanguage::UNKNOWN on // error or if there is no known language ID for this LANGID. // (note that MAKELANGID returns a WORD, but it is accepted here as an int // for wrapping purposes). static int GetLanguageFromWin32LANGID(int win32langid); protected: vtkKWLanguage() {}; ~vtkKWLanguage() {}; // Description: // Get language from XPG (language[_territory[.codeset]][@modifier]). // Return language ID on success, vtkKWLanguage::UNKNOWN on error or if // there is no known language ID for this XPG syntax. // This is a stricter version GetLanguageFromXPG since it does not try // to find the language if the territory was missing. static int GetLanguageFromXPGStrict(const char *xpg); private: vtkKWLanguage(const vtkKWLanguage&); // Not implemented void operator=(const vtkKWLanguage&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWTextPropertyEditor.cxx0000644000175000017500000007651510661115510022446 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTextPropertyEditor.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWTextPropertyEditor.h" #include "vtkActor2D.h" #include "vtkKWChangeColorButton.h" #include "vtkKWCheckButton.h" #include "vtkKWCheckButtonSet.h" #include "vtkKWCheckButtonSetWithLabel.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWMenu.h" #include "vtkKWMenuButton.h" #include "vtkKWMenuButtonWithLabel.h" #include "vtkKWPushButton.h" #include "vtkKWPushButtonSet.h" #include "vtkKWPushButtonSetWithLabel.h" #include "vtkKWScaleWithEntry.h" #include "vtkKWTkUtilities.h" #include "vtkObjectFactory.h" #include "vtkProperty2D.h" #include "vtkTextProperty.h" #include #define VTK_KW_TEXT_PROP_BOLD_ID 0 #define VTK_KW_TEXT_PROP_ITALIC_ID 1 #define VTK_KW_TEXT_PROP_SHADOW_ID 2 #define VTK_KW_TEXT_PROP_COPY_ID 0 /* * This part was generated by ImageConvert from image: * bold.png (zlib, base64) */ #define image_bold_width 12 #define image_bold_height 16 #define image_bold_pixel_size 4 #define image_bold_length 152 static unsigned char image_bold[] = "eNr7//8/w38aYiBQAuI0IH4HxP+huByIZ0LFzkD56GA3knoYMEYzg5B6ZPF3NFCP7J40PO" "ph/gWx7wKxCxH+VULS846A+cgAOZxdSPAvepjiUn8Gh58Jhc8ZJH+hp4dVQNyBlh4EQYr/" "0zh9AgBC7tWi"; /* * This part was generated by ImageConvert from image: * italic.png (zlib, base64) */ #define image_italic_width 12 #define image_italic_height 16 #define image_italic_pixel_size 4 #define image_italic_length 140 static unsigned char image_italic[] = "eNr7//8/w38aYyzABYjvAjFIsgOIlQioB4HdUD1gQIT6d0A8k0j1LlC3hBKpvgOqXpBI9W" "eg7mcgQr0S1OxyItWnQdUrEal+FXI4EqH+HdS/xKgPRQ9HHOoFoWrOIKcBXOppiQHpUhBU"; /* * This part was generated by ImageConvert from image: * shadow.png (zlib, base64) */ #define image_shadow_width 12 #define image_shadow_height 16 #define image_shadow_pixel_size 4 #define image_shadow_length 384 static unsigned char image_shadow[] = "eNq10s8rRFEYxvFhRmZIzSATXSnNlR/JwsiMsiALyo+sxFqUmhVFdjaSBWv/go2VlY38Bf" "4DS6uJsrC8vk89i9PZO/Xpdmeec977vvdmWZbL/pnXOR58fcQN1nLBCvJHznShH8N4wz6q" "6EM+yL/gFgmaWMIFTl1jEqUgr7O//P8u5jCCA2xiQTWC/Dy+9Yh4Rl31Ucasz++N+t3Ah/" "f84EQZ7xlAd5RXT8t4wq/3XWMIRXQG+XHdYxAruMQn2tjBKApBXjPv8DxVfwZ3rnGFLT1T" "NE/NseLaBc/q1XNtIY3m+Y577OHYZ0z4Xr1PB3mdO4ZDnHlWZfe17R6SaD76Btb9vhruYR" "GrmIrer1bJ30OKmq+pf+vRPJT9A5tnxYs="; /* * This part was generated by ImageConvert from image: * copy.png (zlib, base64) */ #define image_copy_width 15 #define image_copy_height 16 #define image_copy_pixel_size 4 #define image_copy_length 124 static unsigned char image_copy[] = "eNqlkwkKACAIBHu6P9+CLjNlpYSlCKZJJAAFj2kFL1nWVpaPWLVSVrnGXtwwb+fFPdO89e" "5IeN/kmffsxfaQ997vz3nN7Bfrh3vj2XEvY1+9LPj4Rz+pVM55tQ=="; // ---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWTextPropertyEditor); vtkCxxRevisionMacro(vtkKWTextPropertyEditor, "$Revision: 1.23 $"); // ---------------------------------------------------------------------------- vtkKWTextPropertyEditor::vtkKWTextPropertyEditor() { this->TextProperty = NULL; this->Actor2D = NULL; this->LongFormat = 0; this->LabelOnTop = 1; this->LabelVisibility = 0; this->Label = vtkKWLabel::New(); this->ColorVisibility = 1; this->ChangeColorButton = vtkKWChangeColorButton::New(); this->FontFamilyVisibility = 1; this->FontFamilyOptionMenu = vtkKWMenuButtonWithLabel::New(); this->StylesVisibility = 1; this->StylesCheckButtonSet = vtkKWCheckButtonSetWithLabel::New(); this->OpacityVisibility = 1; this->OpacityScale = vtkKWScaleWithEntry::New(); this->ChangedCommand = NULL; this->ColorChangedCommand = NULL; this->CopyVisibility = 0; this->PushButtonSet = vtkKWPushButtonSetWithLabel::New(); } // ---------------------------------------------------------------------------- vtkKWTextPropertyEditor::~vtkKWTextPropertyEditor() { this->SetTextProperty(NULL); this->SetActor2D(NULL); if (this->ChangedCommand) { delete [] this->ChangedCommand; this->ChangedCommand = NULL; } if (this->ColorChangedCommand) { delete [] this->ColorChangedCommand; this->ColorChangedCommand = NULL; } if (this->Label) { this->Label->Delete(); this->Label = NULL; } if (this->ChangeColorButton) { this->ChangeColorButton->Delete(); this->ChangeColorButton = NULL; } if (this->FontFamilyOptionMenu) { this->FontFamilyOptionMenu->Delete(); this->FontFamilyOptionMenu = NULL; } if (this->StylesCheckButtonSet) { this->StylesCheckButtonSet->Delete(); this->StylesCheckButtonSet = NULL; } if (this->OpacityScale) { this->OpacityScale->Delete(); this->OpacityScale = NULL; } if (this->PushButtonSet) { this->PushButtonSet->Delete(); this->PushButtonSet = NULL; } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Label this->Label->SetParent(this); this->Label->Create(); // Color this->ChangeColorButton->SetParent(this); this->ChangeColorButton->LabelOutsideButtonOn(); this->ChangeColorButton->Create(); this->ChangeColorButton->SetCommand(this, "ChangeColorButtonCallback"); this->ChangeColorButton->SetBalloonHelpString( ks_("Text Property Editor|Select the text color.")); this->ChangeColorButton->SetDialogTitle( ks_("Text Property Editor|Text Color")); // Font Family this->FontFamilyOptionMenu->SetParent(this); this->FontFamilyOptionMenu->Create(); this->FontFamilyOptionMenu->ExpandWidgetOff(); this->FontFamilyOptionMenu->SetBalloonHelpString( ks_("Text Property Editor|Select the font.")); vtkKWMenuButton *menubutton = this->FontFamilyOptionMenu->GetWidget(); vtkKWMenu *menu = menubutton->GetMenu(); menubutton->SetWidth(7); menubutton->SetPadX(0); menubutton->SetPadY(2); menu->AddRadioButton(ks_("Font|Arial"), this, "FontFamilyCallback"); menu->AddRadioButton(ks_("Font|Courier"), this, "FontFamilyCallback"); menu->AddRadioButton(ks_("Font|Times"), this, "FontFamilyCallback"); // Styles (bold, italic, shadow) this->StylesCheckButtonSet->SetParent(this); this->StylesCheckButtonSet->Create(); this->StylesCheckButtonSet->SetBalloonHelpString( ks_("Text Property Editor|Select the font style.")); vtkKWCheckButtonSet *cbs = this->StylesCheckButtonSet->GetWidget(); cbs->PackHorizontallyOn(); vtkKWCheckButton *cb; cb = cbs->AddWidget(VTK_KW_TEXT_PROP_BOLD_ID); cb->SetCommand(this, "BoldCallback"); cb->SetBalloonHelpString(ks_("Text Property Editor|Select bold style.")); cb->IndicatorVisibilityOff(); cb->SetPadX(0); cb->SetPadY(0); cb->SetImageToPixels(image_bold, image_bold_width, image_bold_height, image_bold_pixel_size, image_bold_length); cb = cbs->AddWidget(VTK_KW_TEXT_PROP_ITALIC_ID); cb->SetCommand(this, "ItalicCallback"); cb->SetBalloonHelpString(ks_("Text Property Editor|Select italic style.")); cb->IndicatorVisibilityOff(); cb->SetPadX(0); cb->SetPadY(0); cb->SetImageToPixels(image_italic, image_italic_width, image_italic_height, image_italic_pixel_size, image_italic_length); cb = cbs->AddWidget(VTK_KW_TEXT_PROP_SHADOW_ID); cb->SetCommand(this, "ShadowCallback"); cb->SetBalloonHelpString(ks_("Text Property Editor|Select shadow style.")); cb->IndicatorVisibilityOff(); cb->SetPadX(0); cb->SetPadY(0); cb->SetImageToPixels(image_shadow, image_shadow_width, image_shadow_height, image_shadow_pixel_size, image_shadow_length); // Opacity this->OpacityScale->SetParent(this); this->OpacityScale->PopupModeOn(); this->OpacityScale->Create(); this->OpacityScale->SetResolution(0.01); this->OpacityScale->SetRange(0.0, 1.0); this->OpacityScale->SetLabelText(""); this->OpacityScale->SetEntryWidth(4); this->OpacityScale->SetCommand(this, "OpacityCallback"); this->OpacityScale->SetEndCommand(this, "OpacityEndCallback"); this->OpacityScale->SetEntryCommand(this, "OpacityEndCallback"); this->OpacityScale->SetBalloonHelpString( ks_("Text Property Editor|Select the text opacity.")); // Buttons this->PushButtonSet->SetParent(this); this->PushButtonSet->SetLabelPositionToLeft(); this->PushButtonSet->Create(); this->PushButtonSet->ExpandWidgetOff(); vtkKWPushButtonSet *pbs = this->PushButtonSet->GetWidget(); pbs->PackHorizontallyOn(); vtkKWPushButton *pb; // Buttons : copy button pb = pbs->AddWidget(VTK_KW_TEXT_PROP_COPY_ID); pb->SetImageToPixels(image_copy, image_copy_width, image_copy_height, image_copy_pixel_size, image_copy_length); // Pack this->Pack(); // Update this->UpdateInterface(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::Pack() { if (!this->IsCreated()) { return; } vtksys_ios::ostringstream tk_cmd; this->ChangeColorButton->UnpackSiblings(); if (this->LongFormat) { this->ChangeColorButton->GetLabel()->SetText( ks_("Text Property Editor|Color:")); this->ChangeColorButton->LabelVisibilityOn(); this->FontFamilyOptionMenu->GetWidget()->IndicatorVisibilityOn(); this->FontFamilyOptionMenu->GetLabel()->SetText( ks_("Text Property Editor|Font:")); this->FontFamilyOptionMenu->LabelVisibilityOn(); this->StylesCheckButtonSet->GetLabel()->SetText( ks_("Text Property Editor|Style:")); this->StylesCheckButtonSet->LabelVisibilityOn(); this->OpacityScale->SetLabelText( ks_("Text Property Editor|Opacity:")); this->PushButtonSet->GetLabel()->SetText( ks_("Text Property Editor|Functions:")); this->PushButtonSet->LabelVisibilityOn(); int row = 0, col = 0; tk_cmd << "grid " << this->Label->GetWidgetName() << " -sticky nsw -column " << col << " -row " << row << endl; if (this->LabelOnTop) { row++; } else { col = 1; } const char *options = " -sticky nsw -pady 1 -padx 10"; tk_cmd << "grid " << this->ChangeColorButton->GetWidgetName() << options << " -column " << col << " -row " << row++ << endl; tk_cmd << "grid " << this->FontFamilyOptionMenu->GetWidgetName() << options << " -column " << col << " -row " << row++ << endl; tk_cmd << "grid " << this->StylesCheckButtonSet->GetWidgetName() << options << " -column " << col << " -row " << row++ << endl; tk_cmd << "grid " << this->OpacityScale->GetWidgetName() << options << " -column " << col << " -row " << row++ << endl; tk_cmd << "grid " << this->PushButtonSet->GetWidgetName() << options << " -column " << col << " -row " << row++ << endl; } else { this->ChangeColorButton->LabelVisibilityOff(); this->FontFamilyOptionMenu->GetWidget()->IndicatorVisibilityOff(); this->FontFamilyOptionMenu->LabelVisibilityOff(); this->StylesCheckButtonSet->LabelVisibilityOff(); this->OpacityScale->SetLabelText(""); this->PushButtonSet->LabelVisibilityOff(); tk_cmd << "grid " << this->Label->GetWidgetName() << " " << this->ChangeColorButton->GetWidgetName() << " " << this->FontFamilyOptionMenu->GetWidgetName() << " " << this->StylesCheckButtonSet->GetWidgetName() << " " << this->OpacityScale->GetWidgetName() << " " << this->PushButtonSet->GetWidgetName() << " -row 0 -sticky news -padx 1" << endl; } this->Script(tk_cmd.str().c_str()); // Synchronize the label width to align everything if (this->LongFormat) { int nb = 0; const char *labels[10]; labels[nb++] = this->ChangeColorButton->GetLabel()->GetWidgetName(); labels[nb++] = this->FontFamilyOptionMenu->GetLabel()->GetWidgetName(); labels[nb++] = this->StylesCheckButtonSet->GetLabel()->GetWidgetName(); labels[nb++] = this->OpacityScale->GetLabel()->GetWidgetName(); labels[nb++] = this->PushButtonSet->GetLabel()->GetWidgetName(); vtkKWTkUtilities::SynchroniseLabelsMaximumWidth( this->GetApplication(), nb, labels, "-anchor w"); } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::Update() { this->UpdateInterface(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateInterface() { // Update enable state this->UpdateEnableState(); // Update all components this->UpdateLabel(); this->UpdateColorButton(); this->UpdateFontFamilyOptionMenu(); this->UpdateStylesCheckButtonSet(); this->UpdateOpacityScale(); this->UpdatePushButtonSet(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetTextProperty(vtkTextProperty *_arg) { if (this->TextProperty == _arg) { return; } this->TextProperty = _arg; if (this->TextProperty) { this->UpdateInterface(); } this->Modified(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetActor2D(vtkActor2D *_arg) { if (this->Actor2D == _arg) { return; } this->Actor2D = _arg; if (this->Actor2D) { this->UpdateInterface(); } this->Modified(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetLongFormat(int _arg) { if (this->LongFormat == _arg) { return; } this->LongFormat = _arg; this->Modified(); this->Pack(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetLabelVisibility(int _arg) { if (this->LabelVisibility == _arg) { return; } this->LabelVisibility = _arg; this->Modified(); this->UpdateLabel(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetLabelOnTop(int _arg) { if (this->LabelOnTop == _arg) { return; } this->LabelOnTop = _arg; this->Modified(); this->Pack(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateLabel() { if (this->IsCreated() && this->Label) { this->Script("grid %s %s", (this->LabelVisibility ? "" : "remove"), this->Label->GetWidgetName()); } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetColorVisibility(int _arg) { if (this->ColorVisibility == _arg) { return; } this->ColorVisibility = _arg; this->Modified(); this->UpdateColorButton(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetColor(double r, double g, double b) { double *rgb = this->GetColor(); if (rgb[0] == r && rgb[1] == g && rgb[2] == b) { return; } if (this->TextProperty) { this->TextProperty->SetColor(r, g, b); } else if (this->Actor2D && this->Actor2D->GetProperty()) { this->Actor2D->GetProperty()->SetColor(r, g, b); } this->UpdateColorButton(); this->InvokeColorChangedCommand(r, g, b); this->InvokeChangedCommand(); } // ---------------------------------------------------------------------------- double* vtkKWTextPropertyEditor::GetColor() { int use_actor_color = 0; if (!this->TextProperty) { use_actor_color = 1; } else { // This test is done to maintain backward compatibility (see // vtkOpenGL...TextMapper). The default vtkTextProperty color is // -1, -1, -1 so that the mappers know that they have to use // the actor's color instead. double *rgb = this->TextProperty->GetColor(); if (rgb[0] < 0.0 && rgb[1] < 0.0 && rgb[2] < 0.0) { use_actor_color = 1; } } if (use_actor_color && this->Actor2D && this->Actor2D->GetProperty()) { return this->Actor2D->GetProperty()->GetColor(); } else if (this->TextProperty) { return this->TextProperty->GetColor(); } return 0; } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateColorButton() { if (this->IsCreated() && this->ChangeColorButton) { if (this->GetColor()) { this->ChangeColorButton->SetColor(this->GetColor()); } this->Script("grid %s %s", (this->ColorVisibility ? "" : "remove"), this->ChangeColorButton->GetWidgetName()); } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::ChangeColorButtonCallback(double r, double g, double b) { this->SetColor(r, g, b); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetFontFamilyVisibility(int _arg) { if (this->FontFamilyVisibility == _arg) { return; } this->FontFamilyVisibility = _arg; this->Modified(); this->UpdateFontFamilyOptionMenu(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetFontFamily(int v) { if (this->TextProperty) { if (this->TextProperty->GetFontFamily() == v) { return; } this->TextProperty->SetFontFamily(v); } this->UpdateFontFamilyOptionMenu(); this->InvokeChangedCommand(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateFontFamilyOptionMenu() { if (this->IsCreated() && this->FontFamilyOptionMenu && this->TextProperty) { switch (this->TextProperty->GetFontFamily()) { case VTK_ARIAL: this->FontFamilyOptionMenu->GetWidget()->SetValue( ks_("Font|Arial")); break; case VTK_COURIER: this->FontFamilyOptionMenu->GetWidget()->SetValue( ks_("Font|Courier")); break; case VTK_TIMES: this->FontFamilyOptionMenu->GetWidget()->SetValue( ks_("Font|Times")); break; } this->Script("grid %s %s", (this->FontFamilyVisibility ? "" : "remove"), this->FontFamilyOptionMenu->GetWidgetName()); } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::FontFamilyCallback() { if (this->FontFamilyOptionMenu->IsCreated()) { const char *value = this->FontFamilyOptionMenu->GetWidget()->GetValue(); if (!strcmp(value, ks_("Font|Arial"))) { this->SetFontFamily(VTK_ARIAL); } else if (!strcmp(value, ks_("Font|Courier"))) { this->SetFontFamily(VTK_COURIER); } else if (!strcmp(value, ks_("Font|Times"))) { this->SetFontFamily(VTK_TIMES); } } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetStylesVisibility(int _arg) { if (this->StylesVisibility == _arg) { return; } this->StylesVisibility = _arg; this->Modified(); this->UpdateStylesCheckButtonSet(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateStylesCheckButtonSet() { if (this->IsCreated() && this->StylesCheckButtonSet) { this->Script("grid %s %s", (this->StylesVisibility ? "" : "remove"), this->StylesCheckButtonSet->GetWidgetName()); } this->UpdateBoldCheckButton(); this->UpdateItalicCheckButton(); this->UpdateShadowCheckButton(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetBold(int v) { if (this->TextProperty) { if (this->TextProperty->GetBold() == v) { return; } this->TextProperty->SetBold(v); } this->UpdateBoldCheckButton(); this->InvokeChangedCommand(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateBoldCheckButton() { if (this->IsCreated() && this->StylesCheckButtonSet && this->TextProperty) { this->StylesCheckButtonSet->GetWidget()->GetWidget(VTK_KW_TEXT_PROP_BOLD_ID)->SetSelectedState(this->TextProperty->GetBold()); } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::BoldCallback(int state) { this->SetBold(state); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetItalic(int v) { if (this->TextProperty) { if (this->TextProperty->GetItalic() == v) { return; } this->TextProperty->SetItalic(v); } this->UpdateItalicCheckButton(); this->InvokeChangedCommand(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateItalicCheckButton() { if (this->IsCreated() && this->StylesCheckButtonSet && this->TextProperty) { this->StylesCheckButtonSet->GetWidget()->GetWidget(VTK_KW_TEXT_PROP_ITALIC_ID)->SetSelectedState(this->TextProperty->GetItalic()); } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::ItalicCallback(int state) { this->SetItalic(state); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetShadow(int v) { if (this->TextProperty) { if (this->TextProperty->GetShadow() == v) { return; } this->TextProperty->SetShadow(v); } this->UpdateShadowCheckButton(); this->InvokeChangedCommand(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateShadowCheckButton() { if (this->IsCreated() && this->StylesCheckButtonSet && this->TextProperty) { this->StylesCheckButtonSet->GetWidget()->GetWidget(VTK_KW_TEXT_PROP_SHADOW_ID)->SetSelectedState(this->TextProperty->GetShadow()); } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::ShadowCallback(int state) { this->SetShadow(state); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetOpacityVisibility(int _arg) { if (this->OpacityVisibility == _arg) { return; } this->OpacityVisibility = _arg; this->Modified(); this->UpdateOpacityScale(); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetOpacity(float v) { if (this->GetOpacity() == v) { return; } if (this->TextProperty) { this->TextProperty->SetOpacity(v); } else if (this->Actor2D && this->Actor2D->GetProperty()) { this->Actor2D->GetProperty()->SetOpacity(v); } this->UpdateOpacityScale(); this->InvokeChangedCommand(); } // ---------------------------------------------------------------------------- float vtkKWTextPropertyEditor::GetOpacity() { int use_actor_opacity = 0; if (!this->TextProperty) { use_actor_opacity = 1; } else { // This test is done to maintain backward compatibility (see // vtkOpenGL...TextMapper). The default vtkTextProperty opacity is // -1 so that the mappers know that they have to use // the actor's opacity instead. if (this->TextProperty->GetOpacity() < 0.0) { use_actor_opacity = 1; } } if (use_actor_opacity && this->Actor2D && this->Actor2D->GetProperty()) { return this->Actor2D->GetProperty()->GetOpacity(); } else if (this->TextProperty) { return this->TextProperty->GetOpacity(); } return 0.0; } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateOpacityScale() { if (this->IsCreated() && this->OpacityScale && this->TextProperty) { this->OpacityScale->SetValue(this->GetOpacity()); this->Script("grid %s %s", (this->OpacityVisibility ? "" : "remove"), this->OpacityScale->GetWidgetName()); } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::OpacityCallback(double value) { this->SetOpacity(value); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::OpacityEndCallback(double value) { this->SetOpacity(value); } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetCopyVisibility(int _arg) { if (this->CopyVisibility == _arg) { return; } this->CopyVisibility = _arg; this->Modified(); this->UpdatePushButtonSet(); } // ---------------------------------------------------------------------------- vtkKWPushButton* vtkKWTextPropertyEditor::GetCopyButton() { if (this->IsCreated()) { return this->PushButtonSet->GetWidget()->GetWidget( VTK_KW_TEXT_PROP_COPY_ID); } return NULL; } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdatePushButtonSet() { if (this->IsCreated() && this->PushButtonSet) { this->PushButtonSet->GetWidget()->SetWidgetVisibility( VTK_KW_TEXT_PROP_COPY_ID, this->CopyVisibility); this->Script("grid %s %s", (this->PushButtonSet->GetWidget() ->GetNumberOfVisibleWidgets() ? "" : "remove"), this->PushButtonSet->GetWidgetName()); } } // ---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::CopyValuesFrom(vtkKWTextPropertyEditor *widget) { if (widget) { vtkTextProperty *tprop = widget->GetTextProperty(); if (tprop) { this->SetColor(widget->GetColor()); this->SetFontFamily(tprop->GetFontFamily()); this->SetBold(tprop->GetBold()); this->SetItalic(tprop->GetItalic()); this->SetShadow(tprop->GetShadow()); this->SetOpacity(widget->GetOpacity()); } } } //---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SaveInTclScript(ofstream *file, const char *tcl_name, int tabify) { static int instance_count = 0; const char *name; char buffer[128]; if (tcl_name) { name = tcl_name; } else { sprintf(buffer, "TextProperty%d", instance_count++); name = buffer; *file << "vtkTextProperty " << name << endl; } vtkTextProperty *tprop = this->TextProperty; if (tprop) { double *rgb = this->GetColor(); if (tabify) { *file << "\t"; } *file << name << " SetColor " << rgb[0] << " " << rgb[1] << " " << rgb[2] << endl; if (tabify) { *file << "\t"; } *file << name << " SetFontFamily " << tprop->GetFontFamily() << endl; if (tabify) { *file << "\t"; } *file << name << " SetBold " << tprop->GetBold() << endl; if (tabify) { *file << "\t"; } *file << name << " SetItalic " << tprop->GetItalic() << endl; if (tabify) { *file << "\t"; } *file << name << " SetShadow " << tprop->GetShadow() << endl; if (tabify) { *file << "\t"; } *file << name << " SetOpacity " << this->GetOpacity() << endl; } } //---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->Label); this->PropagateEnableState(this->ChangeColorButton); this->PropagateEnableState(this->FontFamilyOptionMenu); this->PropagateEnableState(this->StylesCheckButtonSet); this->PropagateEnableState(this->OpacityScale); this->PropagateEnableState(this->PushButtonSet); } //---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->ChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::InvokeChangedCommand() { this->InvokeObjectMethodCommand(this->ChangedCommand); } //---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::SetColorChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->ColorChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::InvokeColorChangedCommand( double r, double g, double b) { if (this->GetApplication() && this->ColorChangedCommand && *this->ColorChangedCommand) { this->Script("%s %lf %lf %lf", this->ColorChangedCommand, r, g, b); } } //---------------------------------------------------------------------------- void vtkKWTextPropertyEditor::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); if (this->TextProperty) { os << indent << "TextProperty:\n"; this->TextProperty->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "TextProperty: None" << endl; } if (this->Actor2D) { os << indent << "Actor2D:\n"; this->Actor2D->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "Actor2D: None" << endl; } os << indent << "LongFormat: " << (this->LongFormat ? "On" : "Off") << endl; os << indent << "LabelVisibility: " << (this->LabelVisibility ? "On" : "Off") << endl; os << indent << "LabelOnTop: " << (this->LabelOnTop ? "On" : "Off") << endl; os << indent << "ColorVisibility: " << (this->ColorVisibility ? "On" : "Off") << endl; os << indent << "FontFamilyVisibility: " << (this->FontFamilyVisibility ? "On" : "Off") << endl; os << indent << "StylesVisibility: " << (this->StylesVisibility ? "On" : "Off") << endl; os << indent << "OpacityVisibility: " << (this->OpacityVisibility ? "On" : "Off") << endl; os << indent << "CopyVisibility: " << (this->CopyVisibility ? "On" : "Off") << endl; os << indent << "ChangedCommand: " << (this->ChangedCommand ? this->ChangedCommand : "None") << endl; os << indent << "ColorChangedCommand: " << (this->ColorChangedCommand ? this->ColorChangedCommand : "None") << endl; os << indent << "Label: " << this->Label << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWSaveImageDialog.cxx0000644000175000017500000000536410424463537021575 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWSaveImageDialog.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWSaveImageDialog.h" #include "vtkKWLoadSaveDialog.h" #include "vtkKWInternationalization.h" #include "vtkKWMessageDialog.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWSaveImageDialog ); vtkCxxRevisionMacro(vtkKWSaveImageDialog, "$Revision: 1.32 $"); //---------------------------------------------------------------------------- int vtkKWSaveImageDialog::Invoke() { int res = 0; this->SaveDialogOn(); this->SetFileTypes("{{Windows Bitmap} {.bmp}} " "{{JPEG} {.jpg}} " "{{PNG} {.png}} " "{{Binary PPM} {.ppm}} " "{{TIFF} {.tif}}"); int done = 0; while (!done) { if (!this->vtkKWLoadSaveDialog::Invoke()) { done = 1; } else { const char *fname = this->GetFileName(); const char *ext = fname + strlen(fname) - 4; if (fname && strlen(fname) && (!strcmp(ext,".bmp") || !strcmp(ext,".jpg") || !strcmp(ext,".png") || !strcmp(ext,".ppm") || !strcmp(ext,".tif"))) { this->GenerateLastPath(fname); res = 1; done = 1; } else { vtkKWMessageDialog::PopupMessage( this->GetApplication(), 0, ks_("Save Image Dialog|Title|Save Image Error!"), k_("A valid file extension was not found. " "Please use a .bmp, .jpg, .png, .ppm, or .tif file extension " "when naming your file."), vtkKWMessageDialog::ErrorIcon); } } } return res; } //---------------------------------------------------------------------------- void vtkKWSaveImageDialog::CreateWidget() { if (this->IsCreated()) { vtkErrorMacro("vtkKWSaveImageDialog already created"); return; } // Call the superclass to create the dialog this->Superclass::CreateWidget(); this->SetTitle(ks_("Save Image Dialog|Title|Save As Image")); } //---------------------------------------------------------------------------- void vtkKWSaveImageDialog::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/Wrapping/0000755000175000017500000000000011461110203016635 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Wrapping/CMakeLists.txt0000644000175000017500000000170711006107372021412 0ustar domibeldomibel# Handle the subdirectories subdirs(Tcl) if(VTK_WRAP_PYTHON) subdirs(Python) endif(VTK_WRAP_PYTHON) # Generate a few small scripts (.bat, .sh, .csh) that can be sourced to set # the various environments variables (PATH, TCLLIBPATH, LD_LIBRARY_PATH, etc.) # required by this executable and its known third-party dependencies (VTK, ITK, # SOV, KWWidgets, etc.). # Also Generate a lightweight C launcher for testing purposes. This # launcher sets the above environment variables before launching an executable. if(KWWidgets_USE_SOVIEWER AND SOV_FOUND) include(${SOV_USE_FILE}) endif(KWWidgets_USE_SOVIEWER AND SOV_FOUND) include("${KWWidgets_CMAKE_DIR}/KWWidgetsPathsMacros.cmake") kwwidgets_generate_setup_paths_scripts("${EXECUTABLE_OUTPUT_PATH}") if(BUILD_TESTING AND KWWidgets_BUILD_TESTING) kwwidgets_generate_setup_paths_launcher( "${CMAKE_CURRENT_BINARY_DIR}" "KWWidgetsSetupPathsLauncher" "" "") endif(BUILD_TESTING AND KWWidgets_BUILD_TESTING) kwwidgets-1.0.0~cvs20100930/Wrapping/Python/0000755000175000017500000000000011461110203020116 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Wrapping/Python/setup.py.in0000644000175000017500000001050411053304277022252 0ustar domibeldomibel#!/usr/bin/env python """ setup.py for installing the VTK-Python bindings using distutils. Created by Prabhu Ramachandran, June 2002. Updated for install with configuration types by Brad King, August 2005. Modified for kwwidgets by David Gobbi, January 2005. """ import sys import string import os import os.path from types import StringType from distutils.core import setup from distutils.command.install_data import install_data from distutils.sysconfig import get_config_var # Support for Python Eggs: # http://peak.telecommunity.com/DevCenter/PythonEggs # http://peak.telecommunity.com/DevCenter/EasyInstall has_setup_tools = 0 # Uncomment the following two lines if you need to build an Egg. # This is commented out by default since the install rule seems # broken for setuptools-0.5a13. #from setuptools import setup #has_setup_tools = 1 # VTK build configuration settings. kwwidgets_version = "@KWWidgets_MAJOR_VERSION@.@KWWidgets_MINOR_VERSION@" kwwidgets_lib_dir = "@LIBRARY_OUTPUT_PATH@" kwwidgets_bin_dir = "@EXECUTABLE_OUTPUT_PATH@" kwwidgets_has_configuration_types = @KWWidgets_PYTHON_HAS_CONFIG_TYPES@ # The build type ('Release', 'Debug' etc.). If kwwidgets_has_configuration_types # is true this must be set. It may be set on the command line by something # like 'BUILD_TYPE=Release'. For example:: # python setup.py install --prefix=D:\\Python23 BUILD_TYPE=Release kwwidgets_build_type = @KWWidgets_PYTHON_BUILD_TYPE@ # Construct the list of kit names to be installed. kwwidgets_kit_names = ['KWWidgets'] # Construct the list of executable names to be installed. kwwidgets_exe_names = [] #['kwpython'] #if kwwidgets_use_parallel and kwwidgets_use_mpi: # kwwidgets_exe_names.extend(['pkwpython']) def get_libs(): """Returns a list of libraries to be installed. """ libs = [] # Select platform-specific components of the module file names. if os.name == 'posix': dir = kwwidgets_lib_dir prefix = 'lib' suffix = 'Python' + get_config_var('SO') else: dir = kwwidgets_bin_dir.replace('/', '\\') prefix = '' suffix = 'Python.pyd' # If this build has configuration types append the selected configuration. if kwwidgets_has_configuration_types: dir = os.path.join(dir, kwwidgets_build_type) # Enumerate ths list of module files. for kit in kwwidgets_kit_names: libs.append(os.path.abspath(os.path.join(dir, prefix+kit+suffix))) return libs class my_install_data (install_data): def finalize_options (self): """Needed to make this thing work properly.""" self.set_undefined_options ('install', ('install_lib', 'install_dir'), ('root', 'root'), ('force', 'force'), ) if __name__ == '__main__': # Get the optional build type argument. for x in sys.argv[:]: if string.find(x, 'BUILD_TYPE') > -1: kwwidgets_build_type = string.strip(string.split(x, '=')[1]) sys.argv.remove(x) break # Make sure a build type was specified if it is required. if kwwidgets_has_configuration_types: if not kwwidgets_build_type: raise "ERROR: Must specify BUILD_TYPE= on command line." def mk_dict(**kw): # Unnecessary in recent Pythons but handy for earlier # versions. return kw # The options for setup. opts = mk_dict(name = "KWWidgets", version = kwwidgets_version, description = "KWWidgets", maintainer = "KWWidgets Developers", maintainer_email = "kwwidgets-developers@vtk.org", license = "BSD", long_description = "Tk-Based Widgets for VTK", url = "http://www.kwwidgets.org/", platforms = ['Any'], cmdclass = {'install_data': my_install_data}, py_modules = ['kwwidgets'], data_files = [('', get_libs())] ) # If setup_tools is available, then add an extra option to disable # creation of a ZIP file. if has_setup_tools: opts['zip_safe'] = 0 setup(**opts) kwwidgets-1.0.0~cvs20100930/Wrapping/Python/CMakeLists.txt0000644000175000017500000001102511006107374022667 0ustar domibeldomibel# Handle out-of-source builds correctly. # # 1. Create a list of Python files to be installed/copied. # 2. Copy them to KWWIDGETS_BINARY_DIR if different from KWWIDGETS_SOURCE_DIR. # 3. Use Python's compileall to compile the copied files. # # *** Step 1 has to be done carefully to avoid missing out files *** if(PYTHON_EXECUTABLE) # Wrapping/Python/kwwidgets.py set(KWWidgets_PYTHON_FILES kwwidgets ) # Done listing of files. # Now copy these files if necessary. set(KWWidgets_PYTHON_SOURCE_FILES) set(KWWidgets_PYTHON_OUTPUT_FILES) foreach(file ${KWWidgets_PYTHON_FILES}) set(src "${KWWidgets_BINARY_DIR}/Wrapping/Python/${file}.py") set(KWWidgets_PYTHON_SOURCE_FILES ${KWWidgets_PYTHON_SOURCE_FILES} ${src}) endforeach(file) if ("${KWWidgets_BINARY_DIR}" MATCHES "^${KWWidgets_SOURCE_DIR}$") #MESSAGE("In source build -- no need to copy Python files.") else ("${KWWidgets_BINARY_DIR}" MATCHES "^${KWWidgets_SOURCE_DIR}$") foreach(file ${KWWidgets_PYTHON_FILES}) set(src "${KWWidgets_SOURCE_DIR}/Wrapping/Python/${file}.py") set(tgt "${KWWidgets_BINARY_DIR}/Wrapping/Python/${file}.py") add_custom_command(DEPENDS ${src} COMMAND ${CMAKE_COMMAND} ARGS -E copy ${src} ${tgt} OUTPUT ${tgt} COMMENT "source copy") endforeach(file) endif ("${KWWidgets_BINARY_DIR}" MATCHES "^${KWWidgets_SOURCE_DIR}$") # Byte compile the Python files. configure_file(${CMAKE_CURRENT_SOURCE_DIR}/compile_all_vtk.py.in ${CMAKE_CURRENT_BINARY_DIR}/compile_all_vtk.py @ONLY IMMEDIATE) add_custom_command( COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_BINARY_DIR}/compile_all_vtk.py DEPENDS ${KWWidgets_PYTHON_SOURCE_FILES} ${CMAKE_CURRENT_BINARY_DIR}/compile_all_vtk.py OUTPUT "${KWWidgets_BINARY_DIR}/Wrapping/Python/vtk_compile_complete" ) # Create a target on which custom commands can depend. When this # is up-to-date, it is safe to run VTK python code. Therefore # this should also depend on the vtkpython executable. add_custom_target(vtkpython_pyc ALL echo "..." DEPENDS "${KWWidgets_BINARY_DIR}/Wrapping/Python/vtk_compile_complete") # If no runtime is to be installed then do not install python modules. if(KWWidgets_INSTALL_NO_RUNTIME) set(KWWidgets_INSTALL_NO_PYTHON 1) endif(KWWidgets_INSTALL_NO_RUNTIME) # Add a rule to use python distutils to install the python wrappers. if(NOT KWWidgets_INSTALL_NO_PYTHON) set(DOLLAR "$") # Create default python setup arguments if they are not set. if(DEFINED KWWidgets_PYTHON_SETUP_ARGS) else(DEFINED KWWidgets_PYTHON_SETUP_ARGS) set(KWWidgets_PYTHON_SETUP_ARGS "--prefix=\"${DOLLAR}{CMAKE_INSTALL_PREFIX}\"" CACHE STRING "Arguments passed to \"python setup.py install ...\" during installation.") mark_as_advanced(KWWidgets_PYTHON_SETUP_ARGS) endif(DEFINED KWWidgets_PYTHON_SETUP_ARGS) # If there are multiple configurations then add a BUILD_TYPE=... # argument to the python setup.py call. The build type to use is set # in the CMake variable BUILD_TYPE while running the install script. if(CMAKE_CONFIGURATION_TYPES) set(KWWidgets_PYTHON_SETUP_BUILD_TYPE "BUILD_TYPE=${DOLLAR}{BUILD_TYPE}") else(CMAKE_CONFIGURATION_TYPES) set(KWWidgets_PYTHON_SETUP_BUILD_TYPE) endif(CMAKE_CONFIGURATION_TYPES) # Configure the post-install script to run python on setup.py. configure_file(${KWWidgets_SOURCE_DIR}/Wrapping/Python/PythonInstall.cmake.in ${KWWidgets_BINARY_DIR}/Wrapping/Python/PythonInstall.cmake @ONLY IMMEDIATE) set_target_properties(vtkpython_pyc PROPERTIES POST_INSTALL_SCRIPT ${KWWidgets_BINARY_DIR}/Wrapping/Python/PythonInstall.cmake ) endif(NOT KWWidgets_INSTALL_NO_PYTHON) endif(PYTHON_EXECUTABLE) # Create the setup.py file. if(CMAKE_CONFIGURATION_TYPES) # The build has multiple configuration types. If CMAKE_BUILD_TYPE # is set use it as the default BUILD_TYPE for setup.py to install. set(KWWidgets_PYTHON_HAS_CONFIG_TYPES 1) if(CMAKE_BUILD_TYPE) set(KWWidgets_PYTHON_BUILD_TYPE "\"${CMAKE_BUILD_TYPE}\"") else(CMAKE_BUILD_TYPE) set(KWWidgets_PYTHON_BUILD_TYPE "[]") endif(CMAKE_BUILD_TYPE) else(CMAKE_CONFIGURATION_TYPES) # The build has one configuration type. The build type does not # affect installation. set(KWWidgets_PYTHON_HAS_CONFIG_TYPES 0) set(KWWidgets_PYTHON_BUILD_TYPE "[]") endif(CMAKE_CONFIGURATION_TYPES) configure_file(${KWWidgets_SOURCE_DIR}/Wrapping/Python/setup.py.in ${KWWidgets_BINARY_DIR}/Wrapping/Python/setup.py @ONLY IMMEDIATE) kwwidgets-1.0.0~cvs20100930/Wrapping/Python/KWWidgetsPythonExtraInit.cxx0000644000175000017500000004004510473334550025566 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: KWWidgetsPythonExtraInit.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkPythonUtil.h" #include "vtkKWTkUtilities.h" #include "vtkKWObject.h" #include "vtkKWApplication.h" #include /* To Do: Connect Tkinter: Widget.tk.interpaddr() will return the address of the interpreter as a long integer The InitializeTcl() method should look for an interpaddr() method of its argument and call it. It should probably also accept a SWIG string. The Tkinter_Create method in _tkinter is hard-coded to create a new interpreter, so mixed apps will need Tkinter's interpreter to be the primary. Tkinter.py defines a "Misc" class that is the base class of all Tcl objects, and a "BaseWidget" class that is the base of all widgets. The widget works through self.tk, where tk is the tcl interpreter defined in _tkinter.c, and self._w, where _w is the tcl name for the widget. The BaseWidget __init__ method takes a "name" keyword that can be used to specify the name of an existing widget (just the name, not the full path: the path is obtained by consulting master._w where "master" is another keyword that must be set. For parenting, the following attributes are requested from the master: master.tk the Tkapp interpreter master._w the Tcl window name master._register(callback) - set by variables master.deletecommand(cbname) - delete the callback master.children - a dict of name : widget For going in the other direction, the vtkKWWidget class has SetWidgetName, SetParent, and Create methods that can be used together to create a vtkKWWidget from a Tkinter widget. Since the "parent" must also be a vtkKWWidget, it seems that it is actually necessary for all Tkinter widgets to have a basic vtkKWWidget wrapper, which could be created on the fly whenever vtkKWWidgets sees an object that needs wrapping. Use python callbacks: The command callbacks in KWWidgets execute Tcl strings, which is not ideal for someone who is programming in python. Tkinter has code that can be used as an example of how a Tcl function can call a Python function. */ // the init function for the python module #if defined(_WIN32) #if defined(__CYGWIN__) extern "C" {void __declspec(dllexport) initlibKWWidgetsPython();} #else /* defined(__CYGWIN__) */ extern "C" {void __declspec(dllexport) initKWWidgetsPython();} #endif /* defined(__CYGWIN__) */ #else /* defined(_WIN32) */ extern "C" {void initlibKWWidgetsPython();} #endif /* defined(_WIN32) */ // change the old "init" function into a pre-init function #define initlibKWWidgetsPython preInitKWWidgetsPython #define initKWWidgetsPython preInitKWWidgetsPython // include the original init file #include "KWWidgetsPythonInit.cxx" // undefine #undef initlibKWWidgetsPython #undef initKWWidgetsPython // define a bunch of extra stuff to go into the init file //---------------------------------------------------------------------------- static PyObject *PyvtkKWObject_Script(PyObject *self, PyObject *args) { char *input; const char *output; vtkKWObject *op; PyObject *format_args = 0; PyObject *format_string = 0; int n; int i = 1; /* check whether this method is bound */ if (PyVTKClass_Check(self)) { i = 2; } /* Get the format string and arguments */ n = PyTuple_Size(args); if (n >= i) { format_args = PyTuple_GetSlice(args,i,n); format_string = PyTuple_GetItem(args,i-1); /* Reslice args to not contain any format_args */ args = PyTuple_GetSlice(args,0,i); } else { PyErr_Format(PyExc_TypeError, "function takes at least %d argument (%d given)", i, n); return NULL; } op = (vtkKWObject *)PyArg_VTKParseTuple(self, args, (char*)"s", &input); if (op) { PyObject *formatted_string; formatted_string = PyString_Format(format_string, format_args); if (formatted_string) { input = PyString_AsString(formatted_string); /* formatting again isn't very efficient, but is safe */ if (PyVTKClass_Check(self)) { output = op->vtkKWObject::Script("%s", input); } else { output = op->Script("%s", input); } Py_DECREF(formatted_string); Py_DECREF(format_args); Py_DECREF(args); if (output == NULL) { Py_INCREF(Py_None); return Py_None; } else { return PyString_FromString(output); } } } if (format_args) { Py_DECREF(format_args); Py_DECREF(args); } return NULL; } static PyObject *PyvtkKWApplication_Script(PyObject *self, PyObject *args) { char *input; const char *output; vtkKWApplication *op; PyObject *format_args = 0; PyObject *format_string = 0; int n; int i = 1; /* check whether this method is bound */ if (PyVTKClass_Check(self)) { i = 2; } /* Get the format string and arguments */ n = PyTuple_Size(args); if (n >= i) { format_args = PyTuple_GetSlice(args,i,n); format_string = PyTuple_GetItem(args,i-1); /* Reslice args to not contain any format_args */ args = PyTuple_GetSlice(args,0,i); } else { PyErr_Format(PyExc_TypeError, "function takes at least %d argument (%d given)", i, n); return NULL; } op = (vtkKWApplication *)PyArg_VTKParseTuple(self, args, (char*)"s", &input); if (op) { PyObject *formatted_string; formatted_string = PyString_Format(format_string, format_args); if (formatted_string) { input = PyString_AsString(formatted_string); /* formatting again isn't very efficient, but is safe */ if (PyVTKClass_Check(self)) { output = op->vtkKWObject::Script("%s", input); } else { output = op->Script("%s", input); } Py_DECREF(formatted_string); Py_DECREF(format_args); Py_DECREF(args); if (output == NULL) { Py_INCREF(Py_None); return Py_None; } else { return PyString_FromString(output); } } } if (format_args) { Py_DECREF(format_args); Py_DECREF(args); } return NULL; } static PyObject *PyvtkKWApplication_EvaluateBooleanExpression(PyObject *self, PyObject *args) { char *input; long output; vtkKWApplication *op; PyObject *format_args = 0; PyObject *format_string = 0; int n; int i = 1; /* check whether this method is bound */ if (PyVTKClass_Check(self)) { i = 2; } /* Get the format string and arguments */ n = PyTuple_Size(args); if (n >= i) { format_args = PyTuple_GetSlice(args,i,n); format_string = PyTuple_GetItem(args,i-1); /* Reslice args to not contain any format_args */ args = PyTuple_GetSlice(args,0,i); } else { PyErr_Format(PyExc_TypeError, "function takes at least %d argument (%d given)", i, n); return NULL; } op = (vtkKWApplication *)PyArg_VTKParseTuple(self, args, (char*)"s", &input); if (op) { PyObject *formatted_string; formatted_string = PyString_Format(format_string, format_args); if (formatted_string) { input = PyString_AsString(formatted_string); /* formatting again isn't very efficient, but is safe */ if (PyVTKClass_Check(self)) { output = op->vtkKWApplication::EvaluateBooleanExpression("%s", input); } else { output = op->EvaluateBooleanExpression("%s", input); } Py_DECREF(formatted_string); Py_DECREF(format_args); Py_DECREF(args); return PyInt_FromLong(output); } } if (format_args) { Py_DECREF(format_args); Py_DECREF(args); } return NULL; } static PyObject *PyvtkKWApplication_InitializeTcl(PyObject *, PyObject *args) { // check to see if a Tkinter "tk" interpreter has been passed PyObject *tkinter; if ((PyArg_ParseTuple(args, (char*)"O", &tkinter))) { // check to see if this is a Tkinter Tkapp PyObject *func = PyObject_GetAttrString(tkinter,(char*)"interpaddr"); if (func) { PyObject *arglist = Py_BuildValue((char*)"()"); PyObject *result = PyEval_CallObject(func, arglist); Py_DECREF(arglist); Py_DECREF(func); if (result == NULL) { return NULL; } if (!PyInt_Check(result)) { PyErr_SetString(PyExc_ValueError,"interpaddr() must return an int"); Py_DECREF(result); return NULL; } // Tkinter in python 2.3 assumes long is big enough for a // pointer, so we do the same here Tcl_Interp *interp; *((long *)(&interp)) = PyInt_AsLong(result); vtkKWApplication::InitializeTcl(interp); Py_INCREF(Py_None); return Py_None; } } // clear error and try (argc, argv) arguments PyErr_Clear(); int argc; PyObject *pyargv; if ((PyArg_ParseTuple(args, (char*)"iO", &argc, &pyargv))) { static char emptystring[1] = ""; int errcheck = 0; int l = 1; int i; PyObject *str; char *cp; char **argv; // make sure argv has at least one value if (argc > l) { l = argc; } argv = (char **)malloc(l*sizeof(char *)); argv[0] = emptystring; for (i = 0; i < argc && errcheck == 0; i++) { errcheck = 1; str = PySequence_GetItem(pyargv, i); if (str) { cp = PyString_AsString(str); if (cp) { argv[i] = cp; errcheck = 0; } } } if (errcheck == 0) { vtkKWApplication::InitializeTcl(argc, argv); } free(argv); if (errcheck == 0) { Py_INCREF(Py_None); return Py_None; } } return NULL; } static PyObject *PyvtkKWApplication_Start(PyObject *self, PyObject *args) { /* handle signature with no arguments */ { vtkKWApplication *op; op = (vtkKWApplication *)PyArg_VTKParseTuple(self, args, (char*)""); if (op) { if (PyVTKClass_Check(self)) { op->vtkKWApplication::Start(); } else { op->Start(); } Py_INCREF(Py_None); return Py_None; } } PyErr_Clear(); /* handle signature with argc, argv arguments */ { int argc; PyObject *pyargv; vtkKWApplication *op; op = (vtkKWApplication *)PyArg_VTKParseTuple(self, args, (char*)"iO", &argc, &pyargv); if (op) { static char emptystring[1] = ""; int errcheck = 0; int l = 1; int i; PyObject *str; char *cp; char **argv; // make sure argv has at least one value if (argc > l) { l = argc; } argv = (char **)malloc(l*sizeof(char *)); argv[0] = emptystring; for (i = 0; i < argc && errcheck == 0; i++) { errcheck = 1; str = PySequence_GetItem(pyargv, i); if (str) { cp = PyString_AsString(str); if (cp) { argv[i] = cp; errcheck = 0; } } } if (errcheck == 0) { if (PyVTKClass_Check(self)) { op->vtkKWApplication::Start(argc, argv); } else { op->Start(argc, argv); } } free(argv); if (errcheck == 0) { Py_INCREF(Py_None); return Py_None; } } } return NULL; } static PyMethodDef PyvtkKWApplicationPythonMethods[] = { {(char*)"Script", (PyCFunction)PyvtkKWApplication_Script, 1, (char*)"V.Script(format, ...) -> string\nC++: const char *Script (const char *format, ...);\n\n Convenience methods to evaluate Tcl script/code and\n perform argument substitutions.\n"}, {(char*)"EvaluateBooleanExpression", (PyCFunction)PyvtkKWApplication_EvaluateBooleanExpression, 1, (char*)"V.EvaluateBooleanExpression(string) -> int\nC++: int EvaluateBooleanExpression (const char *text);\n\n Convenience methods to evaluate Tcl script/code and\n perform argument substitutions.\n"}, {(char*)"Start", (PyCFunction)PyvtkKWApplication_Start, 1, (char*)"V.Start()\nC++: virtual void Start ();\nV.Start(int argc, list argv)\nC++: virtual void Start (int argc, char *argv[])\n\n Start running the application, with or without arguments.\n"}, {(char*)"InitializeTcl", (PyCFunction)PyvtkKWApplication_InitializeTcl, 1, (char*)"V.InitializeTcl(int argc, list argv)\nC++: static void InitializeTcl(int argc, char *argv[]);\nV.InitializeTcl(tkapp tk)\nC++: static void InitializeTcl(Tcl_Interp *tcl);\n\n Initialize Tcl/Tk\n Return NULL on error (eventually provides an ostream where detailed\n error messages will be stored).\n One method takes argc/argv and will create an internal Tcl interpreter\n on the fly, the other takes a Tcl interpreter and uses it afterward\n (this is mainly intended for initialization as a Tcl package)\n"}, {NULL, NULL, 0, NULL} }; static PyMethodDef PyvtkKWObjectPythonMethods[] = { {(char*)"PScript", (PyCFunction)PyvtkKWObject_Script, 1, (char*)"V.Script(format, ...) -> string\nC++: const char *Script (const char *format, ...);\n\nreturn this Script EventString \n\n"}, {NULL, NULL, 0, NULL} }; void PyVTKClass_AddExtraMethods(PyVTKClass *self, PyMethodDef *methods) { PyMethodDef *meth; // if dict isn't built yet, then build it if (self->vtk_dict == NULL) { self->vtk_dict = PyDict_New(); for (meth = self->vtk_methods; meth && meth->ml_name; meth++) { PyDict_SetItemString(self->vtk_dict, meth->ml_name, PyCFunction_New(meth, (PyObject *)self)); } } // add new methods (this clobbers existing methods of the same name) for (meth = methods; meth && meth->ml_name; meth++) { PyDict_SetItemString(self->vtk_dict, meth->ml_name, PyCFunction_New(meth, (PyObject *)self)); } } /* define the init function for the module, handle different platforms */ #if defined(_WIN32) && !defined(__CYGWIN__) void initKWWidgetsPython() #else /* defined(_WIN32) && !defined(__CYGWIN__) */ void initlibKWWidgetsPython() #endif /* defined(_WIN32) && !defined(__CYGWIN__) */ { // call init function from KWWidgetsPythonInit.cxx preInitKWWidgetsPython(); // add extra items to module, on top of basic wrapping PyObject *dict = PyImport_GetModuleDict(); if (dict == 0) { Py_FatalError((char*)"can't find module KWWidgetsPython!"); return; } PyObject *module = 0; #if defined(_WIN32) && !defined(__CYGWIN__) const char *modulename = "KWWidgetsPython"; #else const char *modulename = "libKWWidgetsPython"; #endif module = PyDict_GetItemString(dict, (char *)modulename); if (module == 0) { Py_FatalError((char*)"can't find module KWWidgetsPython!"); return; } dict = PyModule_GetDict(module); if (dict == 0) { Py_FatalError((char*)"can't get dict for module KWWidgetsPython!"); return; } PyObject *pyclass = 0; // add vtkKWObject methods pyclass = PyDict_GetItemString(dict, "vtkKWObject"); if (pyclass == 0 || PyVTKClass_Check(pyclass) == 0) { Py_FatalError((char*)"can't find vtkKWObject class!"); return; } PyVTKClass_AddExtraMethods((PyVTKClass *)pyclass, PyvtkKWObjectPythonMethods); // add vtkKWApplication methods pyclass = PyDict_GetItemString(dict, "vtkKWApplication"); if (pyclass == 0 || PyVTKClass_Check(pyclass) == 0) { Py_FatalError((char*)"can't find vtkKWApplication class!"); return; } PyVTKClass_AddExtraMethods((PyVTKClass *)pyclass, PyvtkKWApplicationPythonMethods); } kwwidgets-1.0.0~cvs20100930/Wrapping/Python/compile_all_vtk.py.in0000644000175000017500000000026610367213764024271 0ustar domibeldomibelimport compileall compileall.compile_dir('@KWWidgets_BINARY_DIR@/Wrapping/Python') file = open('@KWWidgets_BINARY_DIR@/Wrapping/Python/vtk_compile_complete', 'w') file.write('Done') kwwidgets-1.0.0~cvs20100930/Wrapping/Python/kwwidgets.py0000644000175000017500000000636310371132206022516 0ustar domibeldomibel# module for kwwidgets import os if os.name == 'posix': from libKWWidgetsPython import * else: from KWWidgetsPython import * icons = { "IconNoIcon" : 0, "IconAngleTool" : 14, "IconBoundingBox" : 13, "IconCamera" : 19, "IconColorBarAnnotation" : 12, "IconColorSquares" : 18, "IconConnection" : 1, "IconContourTool" : 16, "IconContourSegment" : 33, "IconCornerAnnotation" : 11, "IconCropTool" : 22, "IconDistanceTool" : 15, "IconDocument" : 9, "IconEmpty16x16" : 6, "IconEmpty1x1" : 10, "IconError" : 2, "IconErrorMini" : 3, "IconErrorRedMini" : 4, "IconExpand" : 5, "IconEye" : 17, "IconFileOpen" : 8, "IconFloppy" : 7, "IconFolder" : 20, "IconFolderOpen" : 21, "IconGridLinear" : 40, "IconGridLog" : 41, "IconHeaderAnnotation" : 50, "IconHelpBubble" : 60, "IconInfoMini" : 61, "IconLock" : 62, "IconMagGlass" : 63, "IconMinus" : 64, "IconMove" : 80, "IconMoveH" : 81, "IconMoveV" : 82, "IconOrientationCubeAnnotation" : 83, "IconPanHand" : 84, "IconPlus" : 100, "IconPointFinger" : 90, "IconPresetAdd" : 94, "IconPresetApply" : 95, "IconPresetDelete" : 96, "IconPresetEmail" : 97, "IconPresetLocate" : 98, "IconPresetUpdate" : 99, "IconQuestion" : 101, "IconReload" : 102, "IconRotate" : 105, "IconScaleBarAnnotation" : 106, "IconSideAnnotation" : 110, "IconSpinDown" : 111, "IconSpinLeft" : 112, "IconSpinRight" : 113, "IconSpinUp" : 114, "IconShrink" : 103, "IconStopwatch" : 104, "IconTransportBeginning" : 120, "IconTransportEnd" : 121, "IconTransportFastForward" : 122, "IconTransportFastForwardToKey" : 123, "IconTransportLoop" : 124, "IconTransportPause" : 125, "IconTransportPlay" : 126, "IconTransportPlayToKey" : 127, "IconTransportRewind" : 128, "IconTransportRewindToKey" : 129, "IconTransportStop" : 130, "IconTrashcan" : 131, "IconTreeClose" : 150, "IconTreeOpen" : 151, "IconWarning" : 170, "IconWarningMini" : 171, "IconWindowLevel" : 172, } for key, val in icons.items(): vtkKWIcon.__dict__[key] = val del icons kwwidgets-1.0.0~cvs20100930/Wrapping/Python/PythonInstall.cmake.in0000644000175000017500000000126711006107374024355 0ustar domibeldomibel# Configured file and directory locations. set(PYTHON_EXECUTABLE "@PYTHON_EXECUTABLE@") set(CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@") set(KWWidgets_BINARY_DIR "@KWWidgets_BINARY_DIR@") # Convert the prefix to a windows path if necessary. The python # distutils implementation seems sensitive to the slash direction. if(WIN32 AND NOT CYGWIN) string(REGEX REPLACE "/" "\\\\" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") endif(WIN32 AND NOT CYGWIN) # Run python on setup.py to install the python modules. exec_program("${PYTHON_EXECUTABLE}" "${KWWidgets_BINARY_DIR}/Wrapping/Python" ARGS "setup.py" "install" @KWWidgets_PYTHON_SETUP_BUILD_TYPE@ @KWWidgets_PYTHON_SETUP_ARGS@ ) kwwidgets-1.0.0~cvs20100930/Wrapping/Tcl/0000755000175000017500000000000011461110203017357 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Wrapping/Tcl/CMakeLists.txt0000644000175000017500000000445711006107374022143 0ustar domibeldomibel# Make sure we have Tcl include(FindTCL) if (NOT TCL_LIBRARY) message("VTK_WRAP_TCL is ON, but the Tcl library was not found. Please set TCL_LIBRARY." "Error") endif (NOT TCL_LIBRARY) set(KWWidgets_TCL_LIBNAME_PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}") # Configure the Tcl package index files for the build tree. # You can then point TCLLIBPATH to the Wrapping/Tcl dir in the right # build directory (so that the right shared lib is loaded) set(KWWidgets_TCL_SCRIPT_DIR "${KWWidgets_SOURCE_DIR}/Wrapping/Tcl") set(KWWidgets_TCL_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES}) if(KWWidgets_TCL_CONFIGURATION_TYPES) foreach(config ${KWWidgets_TCL_CONFIGURATION_TYPES}) set(KWWidgets_TCL_LIBRARY_DIR "${LIBRARY_OUTPUT_PATH}/${config}") configure_file(${KWWidgets_SOURCE_DIR}/Wrapping/Tcl/pkgIndex.tcl.in ${KWWidgets_BINARY_DIR}/Wrapping/Tcl/${config}/pkgIndex.tcl @ONLY IMMEDIATE) endforeach(config) else(KWWidgets_TCL_CONFIGURATION_TYPES) set(KWWidgets_TCL_LIBRARY_DIR "${LIBRARY_OUTPUT_PATH}") configure_file(${KWWidgets_SOURCE_DIR}/Wrapping/Tcl/pkgIndex.tcl.in ${KWWidgets_BINARY_DIR}/Wrapping/Tcl/pkgIndex.tcl @ONLY IMMEDIATE) endif(KWWidgets_TCL_CONFIGURATION_TYPES) # Configure the Tcl package index file for the install tree. # You can then point TCLLIBPATH to the lib/KWWidgets/tcl dir in the right # installation directory # We configure a new pkgIndex file that uses KWWidgets_TCL_LIBRARY_DIR # It has to be in Install/Hide so that Tcl does not find it automatically set(KWWidgets_TCL_SCRIPT_DIR "[file dirname [info script]]") if(UNIX) # KWWidgets_TCL_LIBRARY_DIR is used to find the library in the bin # directory relative to the pkgIndex file located in the lib directory set(KWWidgets_TCL_LIBRARY_DIR "[file dirname [file dirname [info script]]]") else(UNIX) set(KWWidgets_TCL_LIBRARY_DIR "[file join [file dirname [file dirname [file dirname [file dirname [info script]]]]] bin]") endif(UNIX) configure_file(${KWWidgets_SOURCE_DIR}/Wrapping/Tcl/pkgIndex.tcl.in ${KWWidgets_BINARY_DIR}/Wrapping/Tcl/Install/Hide/pkgIndex.tcl @ONLY IMMEDIATE) if(NOT KWWidgets_INSTALL_NO_RUNTIME) install_files(${KWWidgets_INSTALL_LIB_DIR}/tcl FILES ${KWWidgets_BINARY_DIR}/Wrapping/Tcl/Install/Hide/pkgIndex.tcl) endif(NOT KWWidgets_INSTALL_NO_RUNTIME) # Install kits subdirs(kwwidgets) kwwidgets-1.0.0~cvs20100930/Wrapping/Tcl/vtkKWWidgetsInitializeCommand.cxx0000644000175000017500000000223210671745173026046 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetsInitializeCommand.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWApplication.h" #include "vtkTclUtil.h" #include extern "C" {int VTK_TK_EXPORT Vtkkwwidgetsinitializecommand_Init(Tcl_Interp *interp);} int VTK_TK_EXPORT Vtkkwwidgetsinitializecommand_Init(Tcl_Interp *interp) { if(Tcl_PkgPresent(interp, (char *)"Tcl", (char *)TCL_VERSION, 0)) { vtksys_ios::ostringstream err; Tcl_Interp *res = vtkKWApplication::InitializeTcl(interp, &err); if (!res && (err.str() != "")) { vtkGenericWarningMacro(<< " Vtkkwwidgetsinitializecommand_Init: failed to InitializeTcl: " << err.str().c_str()); } } return TCL_OK; } kwwidgets-1.0.0~cvs20100930/Wrapping/Tcl/kwwidgets/0000755000175000017500000000000011461110203021367 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Wrapping/Tcl/kwwidgets/CMakeLists.txt0000644000175000017500000000023011006107374024134 0ustar domibeldomibelif(NOT KWWidgets_INSTALL_NO_RUNTIME) install_files(${KWWidgets_INSTALL_LIB_DIR}/tcl/kwwidgets .tcl kwwidgets) endif(NOT KWWidgets_INSTALL_NO_RUNTIME) kwwidgets-1.0.0~cvs20100930/Wrapping/Tcl/kwwidgets/kwwidgets.tcl0000644000175000017500000000023510252365746024130 0ustar domibeldomibelpackage require vtkcommon if {[package require -exact KWWidgets $::kwwidgets::init::version]} { package provide kwwidgets $::kwwidgets::init::version } kwwidgets-1.0.0~cvs20100930/Wrapping/Tcl/pkgIndex.tcl.in0000644000175000017500000000355510345573670022276 0ustar domibeldomibel# KWWidgets Tcl package configuration. package ifneeded kwwidgetsinit {@KWWidgets_MAJOR_VERSION@.@KWWidgets_MINOR_VERSION@} { namespace eval ::kwwidgets::init { proc load_library_package {libName libPath {libPrefix {@KWWidgets_TCL_LIBNAME_PREFIX@}}} { set libExt [info sharedlibextension] set currentDirectory [pwd] set libFile [file join $libPath "$libPrefix$libName$libExt"] if {[catch "cd {$libPath}; load {$libFile}" errorMessage]} { puts $errorMessage } cd $currentDirectory } set version {@KWWidgets_MAJOR_VERSION@.@KWWidgets_MINOR_VERSION@} } package provide kwwidgetsinit {@KWWidgets_MAJOR_VERSION@.@KWWidgets_MINOR_VERSION@} } # Note that we @KWWidgets_TCL_LIBRARY_DIR@ will be set for install targets # to some Tcl code that uses "info script". Be aware that "info script" does # *not* return anything in the current pkgIndex.tcl context, because it # is not sourced, per say. That is the reason why we need to source # another file, inside each kits subdirectory. That source will in turn # perform a "package require" that will call load_library_package successfully # since "info script" will be defined. # The is the C++ DLL itself # Do not mess up with the quoting package ifneeded KWWidgets {@KWWidgets_MAJOR_VERSION@.@KWWidgets_MINOR_VERSION@} " package require -exact kwwidgetsinit {@KWWidgets_MAJOR_VERSION@.@KWWidgets_MINOR_VERSION@} ::kwwidgets::init::load_library_package KWWidgets {@KWWidgets_TCL_LIBRARY_DIR@} " # The is the Tcl package itself # Do not mess up with the quoting package ifneeded kwwidgets {@KWWidgets_MAJOR_VERSION@.@KWWidgets_MINOR_VERSION@} " package require -exact kwwidgetsinit {@KWWidgets_MAJOR_VERSION@.@KWWidgets_MINOR_VERSION@} if {\[catch {source \[file join {@KWWidgets_TCL_SCRIPT_DIR@} kwwidgets kwwidgets.tcl\]} errorMessage\]} { puts \$errorMessage } " kwwidgets-1.0.0~cvs20100930/vtkKWColorSpectrumWidget.cxx0000644000175000017500000010206011160006633022534 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWColorSpectrumWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWColorSpectrumWidget.h" #include "vtkObjectFactory.h" #include "vtkKWLabel.h" #include "vtkKWRadioButtonSet.h" #include "vtkKWRadioButton.h" #include "vtkMath.h" #include "vtkKWCanvas.h" #include "vtkKWTkUtilities.h" #include #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWColorSpectrumWidget ); vtkCxxRevisionMacro(vtkKWColorSpectrumWidget, "$Revision: 1.6 $"); #define VTK_KW_COLOR_SPECTRUM_WIDGET_FIXED_FONT "fixed" #define VTK_KW_COLOR_SPECTRUM_WIDGET_FIXED_FONT_85 "TkDefaultFont" #define VTK_KW_COLOR_SPECTRUM_WIDGET_IMAGE_TAG "image" #define VTK_KW_COLOR_SPECTRUM_WIDGET_CURSOR_TAG "sel" //---------------------------------------------------------------------------- class vtkKWColorSpectrumWidgetInternals { public: double PreviousPickColor[3]; // track the color that was picked double PreviousFixedAxisValue; // track the color that was rendered int PreviousFixedAxis; // in the canvas to avoid re-rendering unsigned char *ImageBuffer; // permanent buffer for speed }; //---------------------------------------------------------------------------- vtkKWColorSpectrumWidget::vtkKWColorSpectrumWidget() { this->Internals = new vtkKWColorSpectrumWidgetInternals; this->Internals->PreviousFixedAxisValue = -1; /* unitialized */ this->Internals->PreviousFixedAxis = -1; this->Internals->ImageBuffer = NULL; this->ColorCanvas = NULL; this->FixedAxisRadioButtonSet = NULL; this->FixedAxis = vtkKWColorSpectrumWidget::FixedAxisV; this->FixedAxisSelectorVisibility = 1; this->CanvasSize = 256; this->InternalColorRGB[0] = -1; /* unitialized */ this->InternalColorRGB[1] = -1; this->InternalColorRGB[2] = -1; this->InternalColorHSV[0] = -1; this->InternalColorHSV[1] = -1; this->InternalColorHSV[2] = -1; this->SetColorAsHSV(0.5, 1.0, 1.0); this->ColorChangedCommand = NULL; this->ColorChangingCommand = NULL; } //---------------------------------------------------------------------------- vtkKWColorSpectrumWidget::~vtkKWColorSpectrumWidget() { delete [] this->Internals->ImageBuffer; delete this->Internals; this->Internals = NULL; if (this->ColorCanvas) { this->ColorCanvas->Delete(); this->ColorCanvas = NULL; } if (this->FixedAxisRadioButtonSet) { this->FixedAxisRadioButtonSet->Delete(); this->FixedAxisRadioButtonSet = NULL; } if (this->ColorChangedCommand) { delete [] this->ColorChangedCommand; this->ColorChangedCommand = NULL; } if (this->ColorChangingCommand) { delete [] this->ColorChangingCommand; this->ColorChangingCommand = NULL; } } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); vtksys_ios::ostringstream tk_cmd; double frame_rgb[3], frame_hsv[3]; this->GetBackgroundColor(&frame_rgb[0], &frame_rgb[1], &frame_rgb[2]); vtkMath::RGBToHSV(frame_rgb, frame_hsv); frame_hsv[2] = frame_hsv[2] * 0.5; vtkMath::HSVToRGB(frame_hsv, frame_rgb); // -------------------------------------------------------------- // Create the Hue/Sat canvas if (!this->ColorCanvas) { this->ColorCanvas = vtkKWCanvas::New(); } this->ColorCanvas->SetParent(this); this->ColorCanvas->Create(); this->ColorCanvas->SetReliefToFlat(); this->ColorCanvas->SetReliefToSolid(); this->ColorCanvas->SetBorderWidth(0); this->ColorCanvas->SetConfigurationOption("-cursor", "target"); // "circle" const char *canv = this->ColorCanvas->GetWidgetName(); vtksys_ios::ostringstream img_name; img_name << this->ColorCanvas->GetWidgetName() << "." << VTK_KW_COLOR_SPECTRUM_WIDGET_IMAGE_TAG; tk_cmd << "image create photo " << img_name.str().c_str() << endl; tk_cmd << canv << " create image 0 0 -anchor nw " << " -image " << img_name.str().c_str() << " -tag " << VTK_KW_COLOR_SPECTRUM_WIDGET_IMAGE_TAG << endl; tk_cmd << canv << " create oval 0 0 0 0 " << " -tag " << VTK_KW_COLOR_SPECTRUM_WIDGET_CURSOR_TAG << endl; // -------------------------------------------------------------- // Fixed Axis choice if (!this->FixedAxisRadioButtonSet) { this->FixedAxisRadioButtonSet = vtkKWRadioButtonSet::New(); } if (!this->FixedAxisRadioButtonSet->IsCreated()) { this->FixedAxisRadioButtonSet->SetParent(this); this->FixedAxisRadioButtonSet->Create(); this->FixedAxisRadioButtonSet->ExpandWidgetsOn(); //this->FixedAxisRadioButtonSet->PackHorizontallyOn(); typedef struct { int value; const char *label; const char *callback; } entry_t; entry_t entries[] = { {vtkKWColorSpectrumWidget::FixedAxisR, "R", "SetFixedAxisToR"}, {vtkKWColorSpectrumWidget::FixedAxisG, "G", "SetFixedAxisToG"}, {vtkKWColorSpectrumWidget::FixedAxisB, "B", "SetFixedAxisToB"}, {vtkKWColorSpectrumWidget::FixedAxisH, "H", "SetFixedAxisToH"}, {vtkKWColorSpectrumWidget::FixedAxisS, "S", "SetFixedAxisToS"}, {vtkKWColorSpectrumWidget::FixedAxisV, "V", "SetFixedAxisToV"}, }; int tcl_major = 0, tcl_minor = 0, tcl_patch_level = 0; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); vtksys_stl::string font("{"); font += (tcl_major < 8 || (tcl_major == 8 && tcl_minor < 5)) ? VTK_KW_COLOR_SPECTRUM_WIDGET_FIXED_FONT : VTK_KW_COLOR_SPECTRUM_WIDGET_FIXED_FONT_85; font += "} 7"; for (int i = 0; i < sizeof(entries) / sizeof(entries[0]); i++) { entry_t entry = entries[i]; vtkKWRadioButton *radiob = this->FixedAxisRadioButtonSet->AddWidget(entry.value); radiob->SetText(entry.label); radiob->SetCommand(this, entry.callback); radiob->IndicatorVisibilityOff(); radiob->SetFont(font.c_str()); radiob->SetOffReliefToFlat(); radiob->SetBorderWidth(0); radiob->SetSelectColor(frame_rgb); } this->FixedAxisRadioButtonSet->GetWidget(this->GetFixedAxis())->Select(); } this->Script(tk_cmd.str().c_str()); this->Pack(); this->AdjustToCanvasSize(); // calls UpdateColorCanvas and UpdateColorCursor this->AddBindings(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::AdjustToCanvasSize() { delete [] this->Internals->ImageBuffer; this->Internals->ImageBuffer = NULL; this->ColorCanvas->SetHeight(this->CanvasSize); this->ColorCanvas->SetWidth(this->CanvasSize); vtksys_ios::ostringstream img_name; img_name << this->ColorCanvas->GetWidgetName() << "." << VTK_KW_COLOR_SPECTRUM_WIDGET_IMAGE_TAG; vtksys_ios::ostringstream tk_cmd; tk_cmd << img_name.str().c_str() << " configure -width " << this->CanvasSize << " -height " << this->CanvasSize << endl; this->Script(tk_cmd.str().c_str()); this->Internals->PreviousFixedAxisValue = -1; // unitialize again this->Internals->PreviousFixedAxis = -1; // to force UpdateColorCanvas this->UpdateColorCanvas(); this->UpdateColorCursor(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::Pack() { if (!this->IsCreated()) { return; } this->UnpackChildren(); vtksys_ios::ostringstream tk_cmd; if (this->FixedAxisSelectorVisibility) { tk_cmd << "pack " << this->FixedAxisRadioButtonSet->GetWidgetName() << " -side left -anchor nw -expand n -fill none" << endl; this->ColorCanvas->SetBorderWidth(2); vtkKWRadioButton *radiob = this->FixedAxisRadioButtonSet->GetWidget( vtkKWColorSpectrumWidget::FixedAxisR); this->ColorCanvas->SetBackgroundColor(radiob->GetBackgroundColor()); } else { this->ColorCanvas->SetBorderWidth(0); this->ColorCanvas->SetBackgroundColor(this->GetBackgroundColor()); } tk_cmd << "pack " << this->ColorCanvas->GetWidgetName() << " -side left -anchor nw -expand n -fill both" << endl; this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetColorAsRGB(double r, double g, double b) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&r, range); vtkMath::ClampValue(&g, range); vtkMath::ClampValue(&b, range); double current[3]; this->GetColorAsRGB(current); if (r == current[0] && g == current[1] && b == current[2]) { return; } this->SetInternalColorRGB(r, g, b); double h, s, v; vtkMath::RGBToHSV(r, g, b, &h, &s, &v); this->SetInternalColorHSV(h, s, v); this->UpdateColorCanvas(); this->UpdateColorCursor(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetColorAsRGB(double rgb[3]) { this->SetColorAsRGB(rgb[0], rgb[1], rgb[2]); } //---------------------------------------------------------------------------- double* vtkKWColorSpectrumWidget::GetColorAsRGB() { return this->GetInternalColorRGB(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::GetColorAsRGB( double &_arg1, double &_arg2, double &_arg3) { this->GetInternalColorRGB(_arg1, _arg2, _arg3); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::GetColorAsRGB(double _arg[3]) { this->GetColorAsRGB(_arg[0], _arg[1], _arg[2]); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetInternalColorRGB( double r, double g, double b) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&r, range); vtkMath::ClampValue(&g, range); vtkMath::ClampValue(&b, range); if (r == this->InternalColorRGB[0] && g == this->InternalColorRGB[1] && b == this->InternalColorRGB[2]) { return; } this->InternalColorRGB[0] = r; this->InternalColorRGB[1] = g; this->InternalColorRGB[2] = b; this->Modified(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetInternalColorRGB(double rgb[3]) { this->SetInternalColorRGB(rgb[0], rgb[1], rgb[2]); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetColorAsHSV(double h, double s, double v) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&h, range); vtkMath::ClampValue(&s, range); vtkMath::ClampValue(&v, range); double current[3]; this->GetColorAsHSV(current); if (h == current[0] && s == current[1] && v == current[2]) { return; } this->SetInternalColorHSV(h, s, v); double r, g, b; vtkMath::HSVToRGB(h, s, v, &r, &g, &b); this->SetInternalColorRGB(r, g, b); this->UpdateColorCanvas(); this->UpdateColorCursor(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetColorAsHSV(double rgb[3]) { this->SetColorAsHSV(rgb[0], rgb[1], rgb[2]); } //---------------------------------------------------------------------------- double* vtkKWColorSpectrumWidget::GetColorAsHSV() { return this->GetInternalColorHSV(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::GetColorAsHSV( double &_arg1, double &_arg2, double &_arg3) { this->GetInternalColorHSV(_arg1, _arg2, _arg3); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::GetColorAsHSV(double _arg[3]) { this->GetColorAsHSV(_arg[0], _arg[1], _arg[2]); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetInternalColorHSV( double h, double s, double v) { double range[2] = {0.0, 1.0}; vtkMath::ClampValue(&h, range); vtkMath::ClampValue(&s, range); vtkMath::ClampValue(&v, range); if (h == this->InternalColorHSV[0] && s == this->InternalColorHSV[1] && v == this->InternalColorHSV[2]) { return; } this->InternalColorHSV[0] = h; this->InternalColorHSV[1] = s; this->InternalColorHSV[2] = v; this->Modified(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetInternalColorHSV(double hsv[3]) { this->SetInternalColorHSV(hsv[0], hsv[1], hsv[2]); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetFixedAxis(int arg) { if (arg < vtkKWColorSpectrumWidget::FixedAxisR) { arg = vtkKWColorSpectrumWidget::FixedAxisR; } else if (arg > vtkKWColorSpectrumWidget::FixedAxisV) { arg = vtkKWColorSpectrumWidget::FixedAxisV; } if (this->FixedAxis == arg) { return; } this->FixedAxis = arg; this->Modified(); this->UpdateColorCanvas(); this->UpdateColorCursor(); } void vtkKWColorSpectrumWidget::SetFixedAxisToR() { this->SetFixedAxis(vtkKWColorSpectrumWidget::FixedAxisR); } void vtkKWColorSpectrumWidget::SetFixedAxisToG() { this->SetFixedAxis(vtkKWColorSpectrumWidget::FixedAxisG); } void vtkKWColorSpectrumWidget::SetFixedAxisToB() { this->SetFixedAxis(vtkKWColorSpectrumWidget::FixedAxisB); } void vtkKWColorSpectrumWidget::SetFixedAxisToH() { this->SetFixedAxis(vtkKWColorSpectrumWidget::FixedAxisH); } void vtkKWColorSpectrumWidget::SetFixedAxisToS() { this->SetFixedAxis(vtkKWColorSpectrumWidget::FixedAxisS); } void vtkKWColorSpectrumWidget::SetFixedAxisToV() { this->SetFixedAxis(vtkKWColorSpectrumWidget::FixedAxisV); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetFixedAxisSelectorVisibility(int arg) { if (this->FixedAxisSelectorVisibility == arg) { return; } this->FixedAxisSelectorVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetCanvasSize(int arg) { if (arg < 10) { arg = 10; } else if (arg > 512) { arg = 512; } if (this->CanvasSize == arg) { return; } this->CanvasSize = arg; this->Modified(); this->AdjustToCanvasSize(); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::UpdateColorCanvas() { if (!this->ColorCanvas || !this->ColorCanvas->IsCreated()) { return; } int size = this->CanvasSize; if (!this->Internals->ImageBuffer) { this->Internals->ImageBuffer = new unsigned char[size * size * 3]; } double h, s, v; double r, g, b; double inc, one_s; // Should be (size - 1), but precision issues make that the final value // which should be 1.0, is very slighly higher, triggering the next // swtich/case choice and a wrong value. Let's fix that. Visually the // difference won't be noticeable, and the right value will be used // during interaction anyway. inc = 1.0 / (double)size; const double onehalf = 0.5; const double onethird = 1.0 / 3.0; const double onesixth = 1.0 / 6.0; const double onesixthinv = 6.0; const double twothird = 2.0 / 3.0; const double fivesixth = 5.0 / 6.0; unsigned char *img_ptr = this->Internals->ImageBuffer; int i, j; switch (this->FixedAxis) { // over R, G vertically (1.0 -> 0.0), B horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisR: if (this->Internals->PreviousFixedAxis == this->FixedAxis && this->Internals->PreviousFixedAxisValue == this->InternalColorRGB[0]) { return; } this->Internals->PreviousFixedAxisValue = this->InternalColorRGB[0]; r = this->InternalColorRGB[0]; g = 1.0; for (i = 0; i < size; i++) { b = 0.0; for (j = 0; j < size; j++) { *img_ptr++ = (unsigned char)(255.0 * r); *img_ptr++ = (unsigned char)(255.0 * g); *img_ptr++ = (unsigned char)(255.0 * b); b += inc; } g -= inc; } break; // over G, R vertically (1.0 -> 0.0), B horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisG: if (this->Internals->PreviousFixedAxis == this->FixedAxis && this->Internals->PreviousFixedAxisValue == this->InternalColorRGB[1]) { return; } this->Internals->PreviousFixedAxisValue = this->InternalColorRGB[1]; g = this->InternalColorRGB[1]; r = 1.0; for (i = 0; i < size; i++) { b = 0.0; for (j = 0; j < size; j++) { *img_ptr++ = (unsigned char)(255.0 * r); *img_ptr++ = (unsigned char)(255.0 * g); *img_ptr++ = (unsigned char)(255.0 * b); b += inc; } r -= inc; } break; // over B, G vertically (1.0 -> 0.0), R horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisB: if (this->Internals->PreviousFixedAxis == this->FixedAxis && this->Internals->PreviousFixedAxisValue == this->InternalColorRGB[2]) { return; } this->Internals->PreviousFixedAxisValue = this->InternalColorRGB[2]; b = this->InternalColorRGB[2]; g = 1.0; for (i = 0; i < size; i++) { r = 0.0; for (j = 0; j < size; j++) { *img_ptr++ = (unsigned char)(255.0 * r); *img_ptr++ = (unsigned char)(255.0 * g); *img_ptr++ = (unsigned char)(255.0 * b); r += inc; } g -= inc; } break; // over H, V vertically (1.0 -> 0.0), S horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisH: if (this->Internals->PreviousFixedAxis == this->FixedAxis && this->Internals->PreviousFixedAxisValue == this->InternalColorHSV[0]) { return; } this->Internals->PreviousFixedAxisValue = this->InternalColorHSV[0]; h = this->InternalColorHSV[0]; v = 1.0; for (i = 0; i < size; i++) { s = 0.0; for (j = 0; j < size; j++) { one_s = 1.0 - s; if (h > onesixth && h <= onethird) // green/red { r = (s*((onethird-h)*onesixthinv)+one_s)*v; g = v; b = one_s*v; } else if (h > onethird && h <= onehalf) // green/blue { r = one_s*v; g = v; b = (s*((h-onethird)*onesixthinv)+one_s)*v; } else if (h > onehalf && h <= twothird) // blue/green { r = one_s*v; g = (s*((twothird-h)*onesixthinv)+one_s)*v; b = v; } else if (h > twothird && h <= fivesixth) // blue/red { r = (s*((h-twothird)*onesixthinv)+one_s)*v; g = one_s*v; b = v; } else if (h > fivesixth && h <= 1.0) // red/blue { r = v; g = one_s*v; b = (s*((1.0-h)*onesixthinv)+one_s)*v; } else // red/green { r = v; g = (s*(h*onesixthinv)+one_s)*v; b = one_s*v; } *img_ptr++ = (unsigned char)(255.0 * r); *img_ptr++ = (unsigned char)(255.0 * g); *img_ptr++ = (unsigned char)(255.0 * b); s += inc; } v -= inc; } break; // over S, V vertically (1.0 -> 0.0), H horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisS: if (this->Internals->PreviousFixedAxis == this->FixedAxis && this->Internals->PreviousFixedAxisValue == this->InternalColorHSV[1]) { return; } this->Internals->PreviousFixedAxisValue = this->InternalColorHSV[1]; s = this->InternalColorHSV[1]; one_s = 1.0 - s; v = 1.0; for (i = 0; i < size; i++) { h = 0.0; for (j = 0; j < size; j++) { if (h > onesixth && h <= onethird) // green/red { r = (s*((onethird-h)*onesixthinv)+one_s)*v; g = v; b = one_s*v; } else if (h > onethird && h <= onehalf) // green/blue { r = one_s*v; g = v; b = (s*((h-onethird)*onesixthinv)+one_s)*v; } else if (h > onehalf && h <= twothird) // blue/green { r = one_s*v; g = (s*((twothird-h)*onesixthinv)+one_s)*v; b = v; } else if (h > twothird && h <= fivesixth) // blue/red { r = (s*((h-twothird)*onesixthinv)+one_s)*v; g = one_s*v; b = v; } else if (h > fivesixth && h <= 1.0) // red/blue { r = v; g = one_s*v; b = (s*((1.0-h)*onesixthinv)+one_s)*v; } else // red/green { r = v; g = (s*(h*onesixthinv)+one_s)*v; b = one_s*v; } *img_ptr++ = (unsigned char)(255.0 * r); *img_ptr++ = (unsigned char)(255.0 * g); *img_ptr++ = (unsigned char)(255.0 * b); h += inc; } v -= inc; } break; // over V, S vertically (1.0 -> 0.0), H horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisV: if (this->Internals->PreviousFixedAxis == this->FixedAxis && this->Internals->PreviousFixedAxisValue == this->InternalColorHSV[2]) { return; } this->Internals->PreviousFixedAxisValue = this->InternalColorHSV[2]; v = this->InternalColorHSV[2]; s = 1.0; for (i = 0; i < size; i++) { one_s = 1.0 - s; h = 0.0; for (j = 0; j < size; j++) { if (h > onesixth && h <= onethird) // green/red { r = (s*((onethird-h)*onesixthinv)+one_s)*v; g = v; b = one_s*v; } else if (h > onethird && h <= onehalf) // green/blue { r = one_s*v; g = v; b = (s*((h-onethird)*onesixthinv)+one_s)*v; } else if (h > onehalf && h <= twothird) // blue/green { r = one_s*v; g = (s*((twothird-h)*onesixthinv)+one_s)*v; b = v; } else if (h > twothird && h <= fivesixth) // blue/red { r = (s*((h-twothird)*onesixthinv)+one_s)*v; g = one_s*v; b = v; } else if (h > fivesixth && h <= 1.0) // red/blue { r = v; g = one_s*v; b = (s*((1.0-h)*onesixthinv)+one_s)*v; } else // red/green { r = v; g = (s*(h*onesixthinv)+one_s)*v; b = one_s*v; } *img_ptr++ = (unsigned char)(255.0 * r); *img_ptr++ = (unsigned char)(255.0 * g); *img_ptr++ = (unsigned char)(255.0 * b); h += inc; } s -= inc; } break; } this->Internals->PreviousFixedAxis = this->FixedAxis; // Update the image vtksys_ios::ostringstream img_name; img_name << this->ColorCanvas->GetWidgetName() << "." << VTK_KW_COLOR_SPECTRUM_WIDGET_IMAGE_TAG; vtkKWTkUtilities::UpdatePhoto(this->GetApplication(), img_name.str().c_str(), this->Internals->ImageBuffer, size, size, 3, size * size * 3); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::UpdateColorCursor() { if (!this->ColorCanvas || !this->ColorCanvas->IsCreated()) { return; } double x, y; switch (this->FixedAxis) { // over R, G vertically (1.0 -> 0.0), B horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisR: x = this->InternalColorRGB[2]; y = this->InternalColorRGB[1]; break; // over G, R vertically (1.0 -> 0.0), B horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisG: x = this->InternalColorRGB[2]; y = this->InternalColorRGB[0]; break; // over B, G vertically (1.0 -> 0.0), R horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisB: x = this->InternalColorRGB[0]; y = this->InternalColorRGB[1]; break; // over H, V vertically (1.0 -> 0.0), S horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisH: x = this->InternalColorHSV[1]; y = this->InternalColorHSV[2]; break; // over S, V vertically (1.0 -> 0.0), H horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisS: x = this->InternalColorHSV[0]; y = this->InternalColorHSV[2]; break; // over V, S vertically (1.0 -> 0.0), H horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisV: x = this->InternalColorHSV[0]; y = this->InternalColorHSV[1]; break; } y = 1.0 - y; const int size = this->CanvasSize; double radius = 5.0; vtksys_ios::ostringstream tk_cmd; tk_cmd << this->ColorCanvas->GetWidgetName() << " coords " << VTK_KW_COLOR_SPECTRUM_WIDGET_CURSOR_TAG << " " << x * size - radius << " " << y * size - radius << " " << x * size + radius << " " << y * size + radius << endl; tk_cmd << this->ColorCanvas->GetWidgetName() << " itemconfigure " << VTK_KW_COLOR_SPECTRUM_WIDGET_CURSOR_TAG << " -outline " << (this->InternalColorHSV[2] > 0.5 ? "#000000" : "#c9c9c9") << endl; this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::PickColorPressCallback(int x, int y) { switch (this->FixedAxis) { case vtkKWColorSpectrumWidget::FixedAxisR: case vtkKWColorSpectrumWidget::FixedAxisG: case vtkKWColorSpectrumWidget::FixedAxisB: this->Internals->PreviousPickColor[0] = this->InternalColorRGB[0]; this->Internals->PreviousPickColor[1] = this->InternalColorRGB[1]; this->Internals->PreviousPickColor[2] = this->InternalColorRGB[2]; break; case vtkKWColorSpectrumWidget::FixedAxisH: case vtkKWColorSpectrumWidget::FixedAxisS: case vtkKWColorSpectrumWidget::FixedAxisV: this->Internals->PreviousPickColor[0] = this->InternalColorHSV[0]; this->Internals->PreviousPickColor[1] = this->InternalColorHSV[1]; this->Internals->PreviousPickColor[2] = this->InternalColorHSV[2]; break; } this->PickColorMoveCallback(x, y); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::PickColorMoveCallback(int x, int y) { const int size = this->CanvasSize; double dx = (double)x / (double)size; double dy = (double)(size - y) / (double)size; double h, s, v; double r, g, b; switch (this->FixedAxis) { // over R, G vertically (1.0 -> 0.0), B horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisR: r = this->InternalColorRGB[0]; g = dy; b = dx; break; // over G, R vertically (1.0 -> 0.0), B horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisG: r = dy; g = this->InternalColorRGB[1]; b = dx; break; // over B, G vertically (1.0 -> 0.0), R horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisB: r = dx; g = dy; b = this->InternalColorRGB[2]; break; // over H, V vertically (1.0 -> 0.0), S horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisH: h = this->InternalColorHSV[0]; s = dx; v = dy; break; // over S, V vertically (1.0 -> 0.0), H horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisS: h = dx; s = this->InternalColorHSV[1]; v = dy; break; // over V, S vertically (1.0 -> 0.0), H horizontally (0.0 -> 1.0) case vtkKWColorSpectrumWidget::FixedAxisV: h = dx; s = dy; v = this->InternalColorHSV[2]; break; } // Set color switch (this->FixedAxis) { case vtkKWColorSpectrumWidget::FixedAxisR: case vtkKWColorSpectrumWidget::FixedAxisG: case vtkKWColorSpectrumWidget::FixedAxisB: if (this->Internals->PreviousPickColor[0] != r || this->Internals->PreviousPickColor[1] != g || this->Internals->PreviousPickColor[2] != b) { this->SetInternalColorRGB(r, g, b); vtkMath::RGBToHSV(r, g, b, &h, &s, &v); this->SetInternalColorHSV(h, s, v); this->UpdateColorCursor(); this->InvokeColorChangingCommand(); } break; case vtkKWColorSpectrumWidget::FixedAxisH: case vtkKWColorSpectrumWidget::FixedAxisS: case vtkKWColorSpectrumWidget::FixedAxisV: if (this->Internals->PreviousPickColor[0] != h || this->Internals->PreviousPickColor[1] != s || this->Internals->PreviousPickColor[2] != v) { this->SetInternalColorHSV(h, s, v); vtkMath::HSVToRGB(h, s, v, &r, &g, &b); this->SetInternalColorRGB(r, g, b); this->UpdateColorCursor(); this->InvokeColorChangingCommand(); } break; } } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::PickColorReleaseCallback() { switch (this->FixedAxis) { case vtkKWColorSpectrumWidget::FixedAxisR: case vtkKWColorSpectrumWidget::FixedAxisG: case vtkKWColorSpectrumWidget::FixedAxisB: if (this->Internals->PreviousPickColor[0] != this->InternalColorRGB[0] || this->Internals->PreviousPickColor[1] != this->InternalColorRGB[1] || this->Internals->PreviousPickColor[2] != this->InternalColorRGB[2]) { this->InvokeColorChangedCommand(); } break; case vtkKWColorSpectrumWidget::FixedAxisH: case vtkKWColorSpectrumWidget::FixedAxisS: case vtkKWColorSpectrumWidget::FixedAxisV: if (this->Internals->PreviousPickColor[0] != this->InternalColorHSV[0] || this->Internals->PreviousPickColor[1] != this->InternalColorHSV[1] || this->Internals->PreviousPickColor[2] != this->InternalColorHSV[2]) { this->InvokeColorChangedCommand(); } break; } } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::AddBindings() { if (!this->IsCreated()) { return; } if (this->ColorCanvas && this->ColorCanvas->IsAlive()) { this->ColorCanvas->SetBinding( "", this, "PickColorPressCallback %x %y"); this->ColorCanvas->SetBinding( "", this, "PickColorMoveCallback %x %y"); this->ColorCanvas->SetBinding( "", this, "PickColorReleaseCallback"); } } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::RemoveBindings() { if (!this->IsCreated()) { return; } if (this->ColorCanvas && this->ColorCanvas->IsAlive()) { this->ColorCanvas->RemoveBinding(""); this->ColorCanvas->RemoveBinding(""); this->ColorCanvas->RemoveBinding(""); } } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetColorChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->ColorChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::InvokeColorChangedCommand() { this->InvokeEvent(vtkKWColorSpectrumWidget::ColorChangedEvent); this->InvokeObjectMethodCommand(this->ColorChangedCommand); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::SetColorChangingCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->ColorChangingCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::InvokeColorChangingCommand() { this->InvokeEvent(vtkKWColorSpectrumWidget::ColorChangingEvent); this->InvokeObjectMethodCommand(this->ColorChangingCommand); } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->ColorCanvas); if (this->GetEnabled()) { this->AddBindings(); } else { this->RemoveBindings(); } } //---------------------------------------------------------------------------- void vtkKWColorSpectrumWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/CMakeLists.txt0000644000175000017500000007431411354736572017647 0ustar domibeldomibelcmake_minimum_required(VERSION 2.6) project(KWWidgets) # -------------------------------------------------------------------------- # To use this library in a larger project you will need to SUBDIR into this # directory so that it gets built and then you will use the following variables # in your CMakeLists files to get the proper include paths and libraries set(KWWidgets_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR}/AutoGeneratedClasses;${CMAKE_CURRENT_BINARY_DIR}" CACHE INTERNAL "include paths for KWWidgets" ) set(KWWidgets_LIBRARIES KWWidgets CACHE INTERNAL "libraries for KWWidgets") # You will also need to define a value for the following variables: # KWWidgets_INSTALL_BIN_DIR - binary dir (executables) # KWWidgets_INSTALL_LIB_DIR - library dir (libs) # KWWidgets_INSTALL_DATA_DIR - share dir (say, examples, data, etc) # KWWidgets_INSTALL_INCLUDE_DIR - include dir (headers) # KWWidgets_INSTALL_PACKAGE_DIR - package/export configuration files # KWWidgets_VTK_INSTALL_PACKAGE_DIR - VTK package/export configuration files # KWWidgets_INSTALL_NO_DEVELOPMENT - do not install development files # KWWidgets_INSTALL_NO_RUNTIME - do not install runtime files # KWWidgets_INSTALL_NO_DOCUMENTATION - do not install documentation files # -------------------------------------------------------------------------- # -------------------------------------------------------------------------- # Version set(KWWidgets_MAJOR_VERSION 1) set(KWWidgets_MINOR_VERSION 0) set(KWWidgets_PATCH_VERSION 0) set(KWWidgets_VERSION "${KWWidgets_MAJOR_VERSION}.${KWWidgets_MINOR_VERSION}.${KWWidgets_PATCH_VERSION}") # -------------------------------------------------------------------------- # We need VTK if(NOT VTK_SOURCE_DIR) find_package(VTK REQUIRED) include(${VTK_USE_FILE}) if(NOT VTK_WRAP_TCL) message(FATAL_ERROR "Please set VTK_WRAP_TCL to ON in VTK") endif(NOT VTK_WRAP_TCL) if(VTK_MAJOR_VERSION LESS 5) message(FATAL_ERROR "Please use VTK 5.0 or later") endif(VTK_MAJOR_VERSION LESS 5) else(NOT VTK_SOURCE_DIR) if(NOT VTK_WRAP_TCL) include_directories(${VTK_TK_RESOURCES_DIR}) endif(NOT VTK_WRAP_TCL) endif(NOT VTK_SOURCE_DIR) # -------------------------------------------------------------------------- # Output directories if(NOT LIBRARY_OUTPUT_PATH) set(LIBRARY_OUTPUT_PATH ${KWWidgets_BINARY_DIR}/bin CACHE INTERNAL "Single output directory for building all libraries.") endif(NOT LIBRARY_OUTPUT_PATH) set(KWWidgets_LIBRARY_DIRS ${LIBRARY_OUTPUT_PATH}) set(KWWidgets_RUNTIME_DIRS ${LIBRARY_OUTPUT_PATH}) if(NOT EXECUTABLE_OUTPUT_PATH) set(EXECUTABLE_OUTPUT_PATH ${KWWidgets_BINARY_DIR}/bin CACHE INTERNAL "Single output directory for building all executables.") endif(NOT EXECUTABLE_OUTPUT_PATH) # -------------------------------------------------------------------------- # Some flags include_regular_expression("^(vtk|kw|icons).*$") set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}") if(CMAKE_COMPILER_2005) add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) endif(CMAKE_COMPILER_2005) set(BUILD_SHARED_LIBS ${VTK_BUILD_SHARED_LIBS}) set(KWWidgets_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) set(KWWidgets_CMAKE_DIR "${KWWidgets_SOURCE_DIR}/CMake" CACHE INTERNAL "") subdirs(CMake) # Make sure VTK_CMAKE_DIR is at the beginning so that VTK's FindTCL is # used before CMake's FindTCL. set(CMAKE_MODULE_PATH "${VTK_CMAKE_DIR}" ${CMAKE_MODULE_PATH} "${KWWidgets_CMAKE_DIR}") set(KWWidgets_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES}) mark_as_advanced(CMAKE_BACKWARDS_COMPATIBILITY) include("${KWWidgets_SOURCE_DIR}/Utilities/tkdnd/TkDnD.cmake") tkdnd_get_library(KWWidgets_USE_TKDND TKDND_SRCS TKDND_INCLUDE_PATH TKDND_LIBS) include("${KWWidgets_SOURCE_DIR}/Utilities/TkTreeCtrl/TkTreeCtrl.cmake") tktreectrl_get_library(KWWidgets_USE_TKTREECTRL TKTREECTRL_SRCS TKTREECTRL_INCLUDE_PATH TKTREECTRL_LIBS) # -------------------------------------------------------------------------- # Install directories if(NOT KWWidgets_INSTALL_BIN_DIR) set(KWWidgets_INSTALL_BIN_DIR "/bin") endif(NOT KWWidgets_INSTALL_BIN_DIR) if(NOT KWWidgets_INSTALL_LIB_DIR) set(KWWidgets_INSTALL_LIB_DIR "/lib/${PROJECT_NAME}") endif(NOT KWWidgets_INSTALL_LIB_DIR) if(NOT KWWidgets_INSTALL_DATA_DIR) set(KWWidgets_INSTALL_DATA_DIR "/share/${PROJECT_NAME}" CACHE INTERNAL "") endif(NOT KWWidgets_INSTALL_DATA_DIR) if(NOT KWWidgets_INSTALL_INCLUDE_DIR) set(KWWidgets_INSTALL_INCLUDE_DIR "/include/${PROJECT_NAME}") endif(NOT KWWidgets_INSTALL_INCLUDE_DIR) if(NOT KWWidgets_INSTALL_PACKAGE_DIR) set(KWWidgets_INSTALL_PACKAGE_DIR ${KWWidgets_INSTALL_LIB_DIR} CACHE INTERNAL "") endif(NOT KWWidgets_INSTALL_PACKAGE_DIR) if(NOT KWWidgets_VTK_INSTALL_PACKAGE_DIR) set(KWWidgets_VTK_INSTALL_PACKAGE_DIR ${VTK_INSTALL_PACKAGE_DIR}) endif(NOT KWWidgets_VTK_INSTALL_PACKAGE_DIR) if(NOT KWWidgets_INSTALL_NO_DEVELOPMENT) set(KWWidgets_INSTALL_NO_DEVELOPMENT 0) endif(NOT KWWidgets_INSTALL_NO_DEVELOPMENT) if(NOT KWWidgets_INSTALL_NO_RUNTIME) set(KWWidgets_INSTALL_NO_RUNTIME 0) endif(NOT KWWidgets_INSTALL_NO_RUNTIME) if(NOT KWWidgets_INSTALL_NO_DOCUMENTATION) set(KWWidgets_INSTALL_NO_DOCUMENTATION 0) endif(NOT KWWidgets_INSTALL_NO_DOCUMENTATION) set(KWWidgets_INSTALL_NO_LIBRARIES) if(KWWidgets_BUILD_SHARED_LIBS) if(KWWidgets_INSTALL_NO_RUNTIME AND KWWidgets_INSTALL_NO_DEVELOPMENT) set(KWWidgets_INSTALL_NO_LIBRARIES 1) endif(KWWidgets_INSTALL_NO_RUNTIME AND KWWidgets_INSTALL_NO_DEVELOPMENT) else(KWWidgets_BUILD_SHARED_LIBS) if(KWWidgets_INSTALL_NO_DEVELOPMENT) set(KWWidgets_INSTALL_NO_LIBRARIES 1) endif(KWWidgets_INSTALL_NO_DEVELOPMENT) endif(KWWidgets_BUILD_SHARED_LIBS) # -------------------------------------------------------------------------- # Sources option(KWWidgets_BUILD_VTK_WIDGETS "Build the widgets that can be interfaced to complex VTK classes. Set it to OFF to build a core version of the library." ON) mark_as_advanced(KWWidgets_BUILD_VTK_WIDGETS) set(KWWidgets_SRCS vtkKWApplication.cxx vtkKWApplicationSettingsInterface.cxx vtkKWBalloonHelpManager.cxx vtkKWCanvas.cxx vtkKWChangeColorButton.cxx vtkKWCheckButton.cxx vtkKWCheckButtonWithChangeColorButton.cxx vtkKWCheckButtonWithPopupFrame.cxx vtkKWClipboardHelper.cxx vtkKWColorPickerDialog.cxx vtkKWColorPickerWidget.cxx vtkKWColorPresetSelector.cxx vtkKWColorSpectrumWidget.cxx vtkKWColorSwatchesWidget.cxx vtkKWComboBox.cxx vtkKWCompositeWidget.cxx vtkKWCoreWidget.cxx vtkKWDialog.cxx vtkKWDirectoryExplorer.cxx vtkKWDirectoryPresetSelector.cxx vtkKWDragAndDropTargetSet.cxx vtkKWEntry.cxx vtkKWEvent.cxx vtkKWEventMap.cxx vtkKWExtent.cxx vtkKWFavoriteDirectoriesFrame.cxx vtkKWFileBrowserDialog.cxx vtkKWFileBrowserWidget.cxx vtkKWFileListTable.cxx vtkKWFrame.cxx vtkKWFrameWithLabel.cxx vtkKWFrameWithScrollbar.cxx vtkKWHSVColorSelector.cxx vtkKWIcon.cxx vtkKWInternationalization.cxx vtkKWKeyBindingsManager.cxx vtkKWKeyBindingsWidget.cxx vtkKWLabel.cxx vtkKWLanguage.cxx vtkKWListBox.cxx vtkKWListBoxToListBoxSelectionEditor.cxx vtkKWLoadSaveButton.cxx vtkKWLoadSaveDialog.cxx vtkKWLogDialog.cxx vtkKWLogWidget.cxx vtkKWMaterialPropertyWidget.cxx vtkKWMatrixWidget.cxx vtkKWMenu.cxx vtkKWMenuButton.cxx vtkKWMessage.cxx vtkKWMessageDialog.cxx vtkKWMostRecentFilesManager.cxx vtkKWMultiColumnList.cxx vtkKWNotebook.cxx vtkKWObject.cxx vtkKWOptionDataBase.cxx vtkKWOptions.cxx vtkKWPopupButton.cxx vtkKWPopupFrame.cxx vtkKWPresetSelector.cxx vtkKWProgressGauge.cxx vtkKWPushButton.cxx vtkKWPushButtonWithMenu.cxx vtkKWRadioButton.cxx vtkKWRadioButtonSet.cxx vtkKWRange.cxx vtkKWRegistryHelper.cxx vtkKWResourceUtilities.cxx vtkKWSaveImageDialog.cxx vtkKWScalarComponentSelectionWidget.cxx vtkKWScale.cxx vtkKWScaleWithEntry.cxx vtkKWScrollbar.cxx vtkKWSeparator.cxx vtkKWSimpleEntryDialog.cxx vtkKWSmallCounterLabel.cxx vtkKWSpinBox.cxx vtkKWSpinButtons.cxx vtkKWSplashScreen.cxx vtkKWSplitFrame.cxx vtkKWStartupPageWidget.cxx vtkKWStateMachine.cxx vtkKWStateMachineCluster.cxx vtkKWStateMachineDOTWriter.cxx vtkKWStateMachineInput.cxx vtkKWStateMachineState.cxx vtkKWStateMachineTransition.cxx vtkKWStateMachineWriter.cxx vtkKWTclInteractor.cxx vtkKWText.cxx vtkKWTheme.cxx vtkKWThumbWheel.cxx vtkKWTkUtilities.cxx vtkKWTkcon.cxx vtkKWToolbar.cxx vtkKWToolbarSet.cxx vtkKWTopLevel.cxx vtkKWTree.cxx vtkKWTreeWithScrollbars.cxx vtkKWUserInterfaceManager.cxx vtkKWUserInterfaceManagerDialog.cxx vtkKWUserInterfaceManagerNotebook.cxx vtkKWUserInterfacePanel.cxx vtkKWWidget.cxx vtkKWWidgetSet.cxx vtkKWWidgetWithLabel.cxx vtkKWWidgetWithScrollbars.cxx vtkKWWidgetWithSpinButtons.cxx vtkKWWidgetsVersion.cxx vtkKWWindow.cxx vtkKWWindowBase.cxx vtkKWWindowLevelPresetSelector.cxx vtkKWWizardDialog.cxx vtkKWWizardStep.cxx vtkKWWizardWidget.cxx vtkKWWizardWorkflow.cxx ) if(KWWidgets_BUILD_VTK_WIDGETS) if(NOT VTK_USE_TK) message(FATAL_ERROR "Please set VTK_USE_TK to ON in VTK for KWWidgets_BUILD_VTK_WIDGETS to be ON as well.") endif(NOT VTK_USE_TK) set(KWWidgets_SRCS ${KWWidgets_SRCS} vtkKWColorPresetMenu.cxx vtkKWColorTransferFunctionEditor.cxx vtkKWCornerAnnotationEditor.cxx vtkKWGenericRenderWindowInteractor.cxx vtkKWHeaderAnnotationEditor.cxx vtkKWHistogram.cxx vtkKWHistogramSet.cxx vtkKWParameterValueFunctionEditor.cxx vtkKWParameterValueFunctionInterface.cxx vtkKWParameterValueHermiteFunctionEditor.cxx vtkKWPiecewiseFunctionEditor.cxx vtkKWRenderWidget.cxx vtkKWScalarBarAnnotation.cxx vtkKWSelectionFrame.cxx vtkKWSelectionFrameLayoutManager.cxx vtkKWSimpleAnimationWidget.cxx vtkKWSurfaceMaterialPropertyWidget.cxx vtkKWTextPropertyEditor.cxx vtkKWVolumePropertyHelper.cxx vtkKWVolumeMaterialPropertyWidget.cxx vtkKWVolumePropertyPresetSelector.cxx vtkKWVolumePropertyWidget.cxx ) endif(KWWidgets_BUILD_VTK_WIDGETS) # Utilities/Extra sources set(KWWidgets_UTILS_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/Wrapping/Tcl/vtkKWWidgetsInitializeCommand.cxx ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/BWidgets/vtkKWBWidgetsInit.cxx ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/Tablelist/vtkKWTablelistInit.cxx ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/tkcon/vtkKWTkconInit.cxx ) if(TKDND_SRCS) set(KWWidgets_UTILS_SRCS ${KWWidgets_UTILS_SRCS} ${TKDND_SRCS}) endif(TKDND_SRCS) if(TKTREECTRL_SRCS) set(KWWidgets_UTILS_SRCS ${KWWidgets_UTILS_SRCS} ${TKTREECTRL_SRCS}) endif(TKTREECTRL_SRCS) # Abstract/pure virtual classes set_source_files_properties( vtkKWClipboardHelper.cxx vtkKWMaterialPropertyWidget.cxx vtkKWParameterValueFunctionEditor.cxx vtkKWParameterValueFunctionInterface.cxx vtkKWParameterValueHermiteFunctionEditor.cxx vtkKWRegistryHelper.cxx vtkKWStateMachineWriter.cxx vtkKWUserInterfaceManager.cxx vtkKWWidgetSet.cxx vtkKWWidgetWithScrollbars.cxx ${KWWidgets_UTILS_SRCS} ABSTRACT ) # Helper classes set_source_files_properties( vtkKWEvent.cxx ${KWWidgets_UTILS_SRCS} WRAP_EXCLUDE ) if(NOT VTK_WRAP_TCL) set_source_files_properties( vtkKWGenericRenderWindowInteractor.cxx WRAP_EXCLUDE ) endif(NOT VTK_WRAP_TCL) # Add the registry code, and the set_icon command on win32 if(WIN32) set(KWWidgets_UTILS_SRCS ${KWWidgets_UTILS_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ApplicationIcon/vtkKWSetApplicationIconTclCommand.c) set(KWWidgets_SRCS ${KWWidgets_SRCS} vtkKWWin32RegistryHelper.cxx) set_source_files_properties( ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ApplicationIcon/vtkKWSetApplicationIconTclCommand.c WRAP_EXCLUDE) else(WIN32) set(KWWidgets_SRCS ${KWWidgets_SRCS} vtkKWUNIXRegistryHelper.cxx) endif(WIN32) # -------------------------------------------------------------------------- # Sources generated automatically from templates set(KWWidgets_TEMPLATES_DIR ${KWWidgets_SOURCE_DIR}/Templates) set(KWWidgets_AUTOGENERATED_DIR ${KWWidgets_BINARY_DIR}/AutoGeneratedClasses) set(KWWidgets_AUTOGENERATED_SRCS) set(KWWidgets_TEMPLATE_SRCS) subdirs(Templates) macro(KWWidgets_AUTOGENERATE_CLASS template build_dir class suffix src_list) set(WidgetType ${class}) configure_file( ${template}.h.in ${build_dir}/${class}${suffix}.h IMMEDIATE) configure_file( ${template}.cxx.in ${build_dir}/${class}${suffix}.cxx IMMEDIATE) set(${src_list} ${${src_list}} ${build_dir}/${class}${suffix}.cxx) endmacro(KWWidgets_AUTOGENERATE_CLASS) # The "set of widgets" are automatically generated from some core widgets # (i.e., vtkKWCheckButton => vtkKWCheckButtonSet). set(list vtkKWCheckButton vtkKWComboBox vtkKWEntry vtkKWFrame vtkKWLabel vtkKWLabelWithLabel vtkKWPushButton vtkKWScale vtkKWScaleWithEntry vtkKWScaleWithLabel vtkKWSpinBox ) if(KWWidgets_BUILD_VTK_WIDGETS) set(list ${list} vtkKWColorTransferFunctionEditor vtkKWPiecewiseFunctionEditor ) endif(KWWidgets_BUILD_VTK_WIDGETS) foreach(WidgetType ${list}) kwwidgets_autogenerate_class( ${KWWidgets_TEMPLATES_DIR}/vtkKWWidgetSetSubclass ${KWWidgets_AUTOGENERATED_DIR} ${WidgetType} Set KWWidgets_AUTOGENERATED_SRCS) endforeach(WidgetType) set(KWWidgets_TEMPLATE_SRCS ${KWWidgets_TEMPLATE_SRCS} ${KWWidgets_TEMPLATES_DIR}/vtkKWWidgetSetSubclass.cxx.in) # The "labeled widgets" are automatically generated from some core widgets # (i.e., vtkKWCheckButton => vtkKWCheckButtonWithLabel) set(list vtkKWCheckButton vtkKWCheckButtonSet vtkKWComboBox vtkKWEntry vtkKWLabel vtkKWLoadSaveButton vtkKWListBoxWithScrollbars vtkKWMatrixWidget vtkKWMenuButton vtkKWMenuButtonWithSpinButtons vtkKWMessage vtkKWMultiColumnList vtkKWMultiColumnListWithScrollbars vtkKWPopupButton vtkKWPushButton vtkKWPushButtonSet vtkKWRadioButtonSet vtkKWScale vtkKWScaleWithEntrySet vtkKWSpinBox vtkKWText vtkKWTextWithScrollbars ) foreach(WidgetType ${list}) kwwidgets_autogenerate_class( ${KWWidgets_TEMPLATES_DIR}/vtkKWWidgetWithLabelSubclass ${KWWidgets_AUTOGENERATED_DIR} ${WidgetType} WithLabel KWWidgets_AUTOGENERATED_SRCS) endforeach(WidgetType) set(KWWidgets_TEMPLATE_SRCS ${KWWidgets_TEMPLATE_SRCS} ${KWWidgets_TEMPLATES_DIR}/vtkKWWidgetWithLabelSubclass.cxx.in) # The "widgets with scrollbars" are automatically generated from some core # widgets # (i.e., vtkKWText => vtkKWTextWithScrollbars) set(list vtkKWCanvas vtkKWListBox vtkKWMultiColumnList vtkKWText ) foreach(WidgetType ${list}) kwwidgets_autogenerate_class( ${KWWidgets_TEMPLATES_DIR}/vtkKWWidgetWithScrollbarsSubclass ${KWWidgets_AUTOGENERATED_DIR} ${WidgetType} WithScrollbars KWWidgets_AUTOGENERATED_SRCS) endforeach(WidgetType) set(KWWidgets_TEMPLATE_SRCS ${KWWidgets_TEMPLATE_SRCS} ${KWWidgets_TEMPLATES_DIR}/vtkKWWidgetWithScrollbarsSubclass.cxx.in) # The "widgets with spinbuttons" are automatically generated from some # core widgets # (i.e., vtkKWMenuButton => vtkKWMenuButtonWithSpinButtons) set(list vtkKWMenuButton ) foreach(WidgetType ${list}) kwwidgets_autogenerate_class( ${KWWidgets_TEMPLATES_DIR}/vtkKWWidgetWithSpinButtonsSubclass ${KWWidgets_AUTOGENERATED_DIR} ${WidgetType} WithSpinButtons KWWidgets_AUTOGENERATED_SRCS) endforeach(WidgetType) set(KWWidgets_TEMPLATE_SRCS ${KWWidgets_TEMPLATE_SRCS} ${KWWidgets_TEMPLATES_DIR}/vtkKWWidgetWithSpinButtonsSubclass.cxx.in) # -------------------------------------------------------------------------- # SOViewer support option(KWWidgets_USE_SOVIEWER "Use the SOViewer library (SOV_DIR) and build the corresponding support classes and examples." OFF) mark_as_advanced(KWWidgets_USE_SOVIEWER) if(KWWidgets_USE_SOVIEWER) find_package(SOV REQUIRED) if(SOV_FOUND) mark_as_advanced(FLTK_FLUID_EXECUTABLE SOV_DIR) endif(SOV_FOUND) endif(KWWidgets_USE_SOVIEWER) # -------------------------------------------------------------------------- # HTML Help can help # http://msdn.microsoft.com/ # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/htmlhelp/html/vsconwhtshw.asp if(WIN32) if(HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) else(HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) include(FindHTMLHelp) endif(HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) if(HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) set(KWWidgets_USE_HTML_HELP 1) else(HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) set(KWWidgets_USE_HTML_HELP 0) endif(HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) if(KWWidgets_USE_HTML_HELP) set(KWWidgets_INCLUDE_PATH ${KWWidgets_INCLUDE_PATH} ${HTML_HELP_INCLUDE_PATH} CACHE INTERNAL "" FORCE) endif(KWWidgets_USE_HTML_HELP) endif(WIN32) # -------------------------------------------------------------------------- # Internationalization set(default_val 0) if(DEFINED KWWidgets_USE_INTERNATIONALIZATION_DEFAULT) set(default_val ${KWWidgets_USE_INTERNATIONALIZATION_DEFAULT}) endif(DEFINED KWWidgets_USE_INTERNATIONALIZATION_DEFAULT) option(KWWidgets_USE_INTERNATIONALIZATION "Enable internationalization support in KWWidgets." ${default_val}) mark_as_advanced(KWWidgets_USE_INTERNATIONALIZATION) if(KWWidgets_USE_INTERNATIONALIZATION) find_package(Gettext) if(GETTEXT_FOUND) include("${KWWidgets_CMAKE_DIR}/KWWidgetsInternationalizationMacros.cmake") set(KWWidgets_INCLUDE_PATH ${KWWidgets_INCLUDE_PATH} ${GETTEXT_INCLUDE_DIR} CACHE INTERNAL "" FORCE) kwwidgets_create_gettext_targets( DOMAIN_NAME "KWWidgets" LOCALE_LIST "fr" COPYRIGHT_HOLDER "Kitware, Inc." SOURCES "${KWWidgets_SRCS};${KWWidgets_TEMPLATE_SRCS}" PO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/po" POT_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/Resources/po" PO_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/Resources/po" MO_INSTALL_DIR "${KWWidgets_INSTALL_DATA_DIR}/locale" ADD_MO_TARGET_TO_ALL) else(GETTEXT_FOUND) set(msg "KWWidgets_USE_INTERNATIONALIZATION is ON but the gettext runtime library and tools were not found.\n\nMore information about internationalization support in KWWidgets can be found at http://public.kitware.com/Wiki/KWWidgets/i18n.\n\n${GETTEXT_INFO_MSG}") message(FATAL_ERROR "${msg}") endif(GETTEXT_FOUND) endif(KWWidgets_USE_INTERNATIONALIZATION) # -------------------------------------------------------------------------- # Use [incr Tcl] set(default_val 0) if(DEFINED KWWidgets_USE_INCR_TCL_DEFAULT) set(default_val ${KWWidgets_USE_INCR_TCL_DEFAULT}) endif(DEFINED KWWidgets_USE_INCR_TCL_DEFAULT) option(KWWidgets_USE_INCR_TCL "Enable [incr Tcl] support in KWWidgets." ${default_val}) mark_as_advanced(KWWidgets_USE_INCR_TCL) if(KWWidgets_USE_INCR_TCL) find_package(IncrTCL REQUIRED) endif(KWWidgets_USE_INCR_TCL) # -------------------------------------------------------------------------- # Include dirs include_directories( ${KWWidgets_INCLUDE_PATH} ${VTK_INCLUDE_DIR} ${TKDND_INCLUDE_PATH} ) # A tricky one. Tcl/Tk 8.5.0 provides (for the first time) some of the # "internal headers" we usually provide in VTK (tclPort.h, tclWinPort.h, etc). # Alas, tclPort.h is buggy by default, as it tries to explicitly include # "../win/tclWinPort.h" instead of "tclWinPort.h". Our VTK internal headers # were fixed. The trick is therefore to include ours before ActiveState's, # by using the BEFORE keyword below. include_directories(BEFORE ${TKTREECTRL_INCLUDE_PATH}) # -------------------------------------------------------------------------- # Wrapping subdirs(Wrapping) set(KWWidgets_SRCS ${KWWidgets_SRCS} ${KWWidgets_AUTOGENERATED_SRCS}) # -------------------------------------------------------------------------- # Wrap the classes in Tcl include("${KWWidgets_CMAKE_DIR}/KWWidgetsWrappingMacros.cmake") set(VTK_WRAP_HINTS ${KWWidgets_SOURCE_DIR}/hints) kwwidgets_wrap_tcl( KWWidgets KWWidgetsTCL_SRCS "${KWWidgets_SRCS}" "vtkKWWidgetsInitializeCommand" "${KWWidgets_MAJOR_VERSION}.${KWWidgets_MINOR_VERSION}") set(KWWidgets_TCL_PACKAGE_INDEX_DIR ${KWWidgets_BINARY_DIR}/Wrapping/Tcl) # If needed, copy the Tcl/Tk support files required at run-time # to initialize Tcl/Tk. This is used by the examples or larger # projects that include KWWidgets directly in their source trees. if(TclTk_INSTALL_LIB_DIR) set(KWWidgets_TclTk_INSTALL_LIB_DIR "${TclTk_INSTALL_LIB_DIR}") else(TclTk_INSTALL_LIB_DIR) set(KWWidgets_TclTk_INSTALL_LIB_DIR "${KWWidgets_INSTALL_LIB_DIR}/TclTk/lib") endif(TclTk_INSTALL_LIB_DIR) include("${KWWidgets_CMAKE_DIR}/KWWidgetsTclTkMacros.cmake") kwwidgets_copy_tcl_tk_support_files("${PROJECT_BINARY_DIR}/lib") kwwidgets_install_tcl_tk_support_files("${KWWidgets_TclTk_INSTALL_LIB_DIR}") incr_tcl_get_version("INCR_TCL_MAJOR_VERSION" "INCR_TCL_MINOR_VERSION") # -------------------------------------------------------------------------- # Wrap the classes in Python if(VTK_WRAP_PYTHON) set(KWWidgetsPythonExtra_SRCS) set(KWWidgetsPython_LIBS vtkCommonPythonD) include("${VTK_CMAKE_DIR}/vtkWrapPython.cmake") vtk_wrap_python3(KWWidgetsPython KWWidgetsPython_SRCS "${KWWidgets_SRCS} ${KWWidgetsPythonExtra_SRCS}") set(KWWidgets_PYTHON_MODULE_DIR ${KWWidgets_BINARY_DIR}/Wrapping/Python) if(BORLAND) write_file(${LIBRARY_OUTPUT_PATH}/KWWidgetsPython.def "EXPORTS\ninitKWWidgetsPython=_initKWWidgetsPython\n") endif(BORLAND) add_library(KWWidgetsPythonD ${KWWidgetsPython_SRCS} ${KWWidgetsPythonExtra_SRCS} ) target_link_libraries(KWWidgetsPythonD KWWidgets ${KWWidgetsPython_LIBS}) if(KWWidgets_BUILD_VTK_WIDGETS AND VTK_USE_RENDERING OR VTK_USE_RENDERING_ISSET) target_link_libraries(KWWidgetsPythonD vtkRenderingPythonD) endif(KWWidgets_BUILD_VTK_WIDGETS AND VTK_USE_RENDERING OR VTK_USE_RENDERING_ISSET) if(WIN32 OR APPLE) target_link_libraries(KWWidgetsPythonD ${VTK_PYTHON_LIBRARIES}) endif(WIN32 OR APPLE) if(NOT KWWidgets_INSTALL_NO_LIBRARIES) install_targets( ${KWWidgets_INSTALL_LIB_DIR} RUNTIME_DIRECTORY ${KWWidgets_INSTALL_BIN_DIR} KWWidgetsPythonD) endif(NOT KWWidgets_INSTALL_NO_LIBRARIES) # Create a python module that can be loaded dynamically. add_library(KWWidgetsPython MODULE Wrapping/Python/KWWidgetsPythonExtraInit.cxx) target_link_libraries(KWWidgetsPython KWWidgetsPythonD) # Python extension modules on Windows must have the extension ".pyd" # instead of ".dll" as of Python 2.5. Older python versions do support # this suffix. if(WIN32 AND NOT CYGWIN) set_target_properties(KWWidgetsPython PROPERTIES SUFFIX ".pyd") endif(WIN32 AND NOT CYGWIN) if(WIN32 OR APPLE) target_link_libraries(KWWidgetsPython ${VTK_PYTHON_LIBRARIES}) endif(WIN32 OR APPLE) if(KWWidgets_BUILD_VTK_WIDGETS AND VTK_USE_RENDERING OR VTK_USE_RENDERING_ISSET) # TARGET_LINK_LIBRARIES(KWWidgetsPython vtkRenderingPython) endif(KWWidgets_BUILD_VTK_WIDGETS AND VTK_USE_RENDERING OR VTK_USE_RENDERING_ISSET) find_program(PYTHON_EXECUTABLE NAMES python2.6 python2.5 python2.4 python2.3 python2.2 python PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.2\\InstallPath] ) mark_as_advanced(PYTHON_EXECUTABLE) endif(VTK_WRAP_PYTHON) # -------------------------------------------------------------------------- # Create the instantiators set(VTK_USE_INSTANTIATOR_NEW 1) vtk_make_instantiator3(KWWidgetsInstantiator KWWidgets_Instantiator_SRCS "${KWWidgets_SRCS}" KWWidgets_EXPORT ${KWWidgets_BINARY_DIR} "vtkKWWidgets.h") # -------------------------------------------------------------------------- # Build the library add_library(KWWidgets ${KWWidgetsTCL_SRCS} ${KWWidgets_SRCS} ${KWWidgets_Instantiator_SRCS} ${KWWidgets_UTILS_SRCS}) target_link_libraries(KWWidgets vtkCommonTCL) if(KWWidgets_BUILD_VTK_WIDGETS) if(VTK_WRAP_TCL) if(VTK_USE_RENDERING OR VTK_USE_RENDERING_ISSET) target_link_libraries(KWWidgets vtkRenderingTCL) target_link_libraries(KWWidgets vtkHybridTCL) if(VTK_MAJOR_VERSION GREATER 4) target_link_libraries(KWWidgets vtkWidgetsTCL) target_link_libraries(KWWidgets vtkVolumeRenderingTCL) endif(VTK_MAJOR_VERSION GREATER 4) endif(VTK_USE_RENDERING OR VTK_USE_RENDERING_ISSET) if(VTK_USE_PARALLEL OR VTK_USE_PARALLEL_ISSET) target_link_libraries(KWWidgets vtkParallelTCL) endif(VTK_USE_PARALLEL OR VTK_USE_PARALLEL_ISSET) else(VTK_WRAP_TCL) if(VTK_USE_RENDERING OR VTK_USE_RENDERING_ISSET) target_link_libraries(KWWidgets vtkRendering) target_link_libraries(KWWidgets vtkHybrid) if(VTK_MAJOR_VERSION GREATER 4) target_link_libraries(KWWidgets vtkWidgets) target_link_libraries(KWWidgets vtkVolumeRendering) endif(VTK_MAJOR_VERSION GREATER 4) endif(VTK_USE_RENDERING OR VTK_USE_RENDERING_ISSET) if(VTK_USE_PARALLEL OR VTK_USE_PARALLEL_ISSET) target_link_libraries(KWWidgets vtkParallel) endif(VTK_USE_PARALLEL OR VTK_USE_PARALLEL_ISSET) endif(VTK_WRAP_TCL) else(KWWidgets_BUILD_VTK_WIDGETS) if(TK_LIBRARY_DEBUG) set(KWWidgets_TK_LIBRARIES optimized ${TK_LIBRARY} debug ${TK_LIBRARY_DEBUG}) else(TK_LIBRARY_DEBUG) set(KWWidgets_TK_LIBRARIES ${TK_LIBRARY}) endif(TK_LIBRARY_DEBUG) target_link_libraries(KWWidgets ${KWWidgets_TK_LIBRARIES}) endif(KWWidgets_BUILD_VTK_WIDGETS) target_link_libraries(KWWidgets ${VTK_PNG_LIBRARIES} ${KWSYS_NAMESPACE} ) if(WIN32) target_link_libraries(KWWidgets comctl32 mpr) if(HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) target_link_libraries(KWWidgets ${HTML_HELP_LIBRARY} ) endif(HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) endif(WIN32) # link ApplicationServices.framework on OSX for vtkKWClipboardHelper if(APPLE) target_link_libraries (KWWidgets "-framework ApplicationServices") # As much as we should try to avoid linking against Carbon, I'm # afraid we will need it to run an AppleScript using OSAExecute() # (see vtkKWApplication::RunAppleScript and SendEmail) target_link_libraries (KWWidgets "-framework Carbon") endif(APPLE) if(KWWidgets_USE_INTERNATIONALIZATION AND GETTEXT_RUNTIME_FOUND) target_link_libraries(KWWidgets ${GETTEXT_LIBRARIES}) endif(KWWidgets_USE_INTERNATIONALIZATION AND GETTEXT_RUNTIME_FOUND) if(KWWidgets_USE_INCR_TCL AND INCR_TCL_FOUND) target_link_libraries(KWWidgets ${INCR_TCL_LIBRARY} ${INCR_TK_LIBRARY}) endif(KWWidgets_USE_INCR_TCL AND INCR_TCL_FOUND) if(TKDND_LIBS) target_link_libraries(KWWidgets ${TKDND_LIBS}) endif(TKDND_LIBS) if(TKTREECTRL_LIBS) target_link_libraries(KWWidgets ${TKTREECTRL_LIBS}) endif(TKTREECTRL_LIBS) if(NOT KWWidgets_INSTALL_NO_LIBRARIES) install_targets( ${KWWidgets_INSTALL_LIB_DIR} RUNTIME_DIRECTORY ${KWWidgets_INSTALL_BIN_DIR} ${KWWidgets_LIBRARIES}) endif(NOT KWWidgets_INSTALL_NO_LIBRARIES) # -------------------------------------------------------------------------- # Examples set(KWWidgets_EXAMPLES_DIR ${KWWidgets_SOURCE_DIR}/Examples) option(KWWidgets_BUILD_EXAMPLES "Build KWWidgets examples." ${BUILD_EXAMPLES}) mark_as_advanced(KWWidgets_BUILD_EXAMPLES) set(KWWidgets_NEED_TO_BUILD_EXAMPLES ${KWWidgets_BUILD_EXAMPLES}) # -------------------------------------------------------------------------- # Testing (requires some of the examples) include(Dart) mark_as_advanced(BUILD_TESTING DART_ROOT TCL_TCLSH) set(default_val 1) if(DEFINED KWWidgets_BUILD_TESTING_DEFAULT) set(default_val ${KWWidgets_BUILD_TESTING_DEFAULT}) endif(DEFINED KWWidgets_BUILD_TESTING_DEFAULT) option(KWWidgets_BUILD_TESTING "Enable testing in KWWidgets (if BUILD_TESTING is ON as well)." ${default_val}) mark_as_advanced(KWWidgets_BUILD_TESTING) if(BUILD_TESTING AND KWWidgets_BUILD_TESTING) enable_testing() #SET(BUILDNAME "${PROJECT_NAME}-${BUILDNAME}") set(KWWidgets_NEED_TO_BUILD_EXAMPLES 1) option(KWWidgets_TEST_OUT_OF_SOURCE "Perform existing tests as out-of-source tests. This checks that external projects can be built against a KWWidgets build tree." OFF) mark_as_advanced(KWWidgets_TEST_OUT_OF_SOURCE) if(KWWidgets_TEST_OUT_OF_SOURCE) option(KWWidgets_TEST_INSTALLATION "Perform existing out-of-source tests against an installed KWWidgets library as well. This checks that external projects can be built against a KWWidgets installation tree. Make sure CMAKE_INSTALL_PREFIX is set and KWWidgets has been installed properly before running the tests." OFF) mark_as_advanced(KWWidgets_TEST_INSTALLATION) endif(KWWidgets_TEST_OUT_OF_SOURCE) subdirs(Testing) endif(BUILD_TESTING AND KWWidgets_BUILD_TESTING) # -------------------------------------------------------------------------- # Build the utilities subdirs(Utilities) # -------------------------------------------------------------------------- # Install the headers if(NOT KWWidgets_INSTALL_NO_DEVELOPMENT) install_files(${KWWidgets_INSTALL_INCLUDE_DIR} .h ${KWWidgets_SRCS}) install_files(${KWWidgets_INSTALL_INCLUDE_DIR} FILES vtkKWWidgets.h) endif(NOT KWWidgets_INSTALL_NO_DEVELOPMENT) # -------------------------------------------------------------------------- # Resources set(KWWidgets_RESOURCES_DIR ${KWWidgets_SOURCE_DIR}/Resources CACHE INTERNAL "") subdirs(Resources) # -------------------------------------------------------------------------- # Configure the export configuration subdirs(CMake/ExportConfiguration) # -------------------------------------------------------------------------- # Build the examples # This need to be done *at the end*, so that the installation process # goes as far as possible before trying to install the examples; # examples would stop the install process if they failed to build (say, if a # third-party lib like ITK or SOV was broken). if(KWWidgets_NEED_TO_BUILD_EXAMPLES) subdirs(Examples) endif(KWWidgets_NEED_TO_BUILD_EXAMPLES) # -------------------------------------------------------------------------- # Testing with Squish if(BUILD_TESTING AND KWWidgets_BUILD_TESTING) option(KWWidgets_USE_Squish "Test KWWidgets With Squish" OFF) mark_as_advanced(KWWidgets_USE_Squish) if(KWWidgets_USE_Squish) find_package(Squish) if(NOT SQUISH_FOUND) MESSAGE("Warning: Squish not found, can't add Squish Tk GUI tests") endif(NOT SQUISH_FOUND) endif(KWWidgets_USE_Squish) endif(BUILD_TESTING AND KWWidgets_BUILD_TESTING) kwwidgets-1.0.0~cvs20100930/vtkKWRadioButton.cxx0000644000175000017500000001045310770314423021032 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWRadioButton.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWApplication.h" #include "vtkKWRadioButton.h" #include "vtkObjectFactory.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWRadioButton ); vtkCxxRevisionMacro(vtkKWRadioButton, "$Revision: 1.33 $"); //---------------------------------------------------------------------------- void vtkKWRadioButton::CreateWidget() { // Call the superclass to create the widget and set the appropriate flags if (!vtkKWWidget::CreateSpecificTkWidget(this, "radiobutton", "-value 1 -highlightthickness 0 -padx 2 -pady 2 -bd 2")) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } this->Configure(); } //---------------------------------------------------------------------------- void vtkKWRadioButton::SetValue(const char *v) { this->SetConfigurationOption("-value", v); } //---------------------------------------------------------------------------- const char* vtkKWRadioButton::GetValue() { return this->GetConfigurationOption("-value"); } //---------------------------------------------------------------------------- void vtkKWRadioButton::SetValueAsInt(int v) { this->SetConfigurationOptionAsInt("-value", v); } //---------------------------------------------------------------------------- int vtkKWRadioButton::GetValueAsInt() { return this->GetConfigurationOptionAsInt("-value"); } //---------------------------------------------------------------------------- void vtkKWRadioButton::SetVariableValue(const char *v) { if (this->IsCreated() && this->GetVariableName()) { this->Script("set %s {%s}", this->GetVariableName(), v ? v : ""); } } //---------------------------------------------------------------------------- const char* vtkKWRadioButton::GetVariableValue() { if (this->IsCreated() && this->GetVariableName()) { return this->Script("set %s", this->GetVariableName()); } return NULL; } //---------------------------------------------------------------------------- void vtkKWRadioButton::SetVariableValueAsInt(int v) { char buffer[256]; sprintf(buffer, "%d", v); this->SetVariableValue(buffer); } //---------------------------------------------------------------------------- int vtkKWRadioButton::GetVariableValueAsInt() { return atoi(this->GetVariableValue()); } //---------------------------------------------------------------------------- int vtkKWRadioButton::GetSelectedState() { if (this->IsCreated() && this->GetVariableName()) { #if 0 return atoi( this->Script("expr {${%s}} == {[%s cget -value]}", this->VariableName, this->GetWidgetName())); #else vtksys_stl::string varvalue( Tcl_GetVar(this->GetApplication()->GetMainInterp(), this->VariableName, TCL_GLOBAL_ONLY)); vtksys_stl::string value(this->GetConfigurationOption("-value")); return !strcmp(varvalue.c_str(), value.c_str()); #endif } return 0; } //---------------------------------------------------------------------------- void vtkKWRadioButton::CommandCallback() { int state = this->GetSelectedState(); this->InvokeCommand(state); this->InvokeEvent(vtkKWRadioButton::SelectedStateChangedEvent, &state); } //---------------------------------------------------------------------------- void vtkKWRadioButton::SetCommand(vtkObject *object, const char *method) { this->Superclass::SetCommand(object, method); } //---------------------------------------------------------------------------- void vtkKWRadioButton::InvokeCommand(int) { this->InvokeObjectMethodCommand(this->Command); } //---------------------------------------------------------------------------- void vtkKWRadioButton::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWOptions.cxx0000644000175000017500000002502610464737265020252 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWOptions.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWOptions.h" #include "vtkKWWidget.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWOptions ); vtkCxxRevisionMacro(vtkKWOptions, "$Revision: 1.2 $"); //---------------------------------------------------------------------------- const char* vtkKWOptions::GetCharacterEncodingAsTclOptionValue(int encoding) { switch (encoding) { case VTK_ENCODING_US_ASCII: return "ascii"; case VTK_ENCODING_UNICODE: return "unicode"; case VTK_ENCODING_UTF_8: return "utf-8"; case VTK_ENCODING_ISO_8859_1: return "iso8859-1"; case VTK_ENCODING_ISO_8859_2: return "iso8859-2"; case VTK_ENCODING_ISO_8859_3: return "iso8859-3"; case VTK_ENCODING_ISO_8859_4: return "iso8859-4"; case VTK_ENCODING_ISO_8859_5: return "iso8859-5"; case VTK_ENCODING_ISO_8859_6: return "iso8859-5"; case VTK_ENCODING_ISO_8859_7: return "iso8859-7"; case VTK_ENCODING_ISO_8859_8: return "iso8859-8"; case VTK_ENCODING_ISO_8859_9: return "iso8859-9"; case VTK_ENCODING_ISO_8859_10: return "iso8859-10"; case VTK_ENCODING_ISO_8859_11: return "iso8859-11"; case VTK_ENCODING_ISO_8859_12: return "iso8859-12"; case VTK_ENCODING_ISO_8859_13: return "iso8859-13"; case VTK_ENCODING_ISO_8859_14: return "iso8859-14"; case VTK_ENCODING_ISO_8859_15: return "iso8859-15"; case VTK_ENCODING_ISO_8859_16: return "iso8859-16"; default: return "identity"; } } //---------------------------------------------------------------------------- const char* vtkKWOptions::GetAnchorAsTkOptionValue(int anchor) { switch (anchor) { case vtkKWOptions::AnchorNorth: return "n"; case vtkKWOptions::AnchorNorthEast: return "ne"; case vtkKWOptions::AnchorEast: return "e"; case vtkKWOptions::AnchorSouthEast: return "se"; case vtkKWOptions::AnchorSouth: return "s"; case vtkKWOptions::AnchorSouthWest: return "sw"; case vtkKWOptions::AnchorWest: return "w"; case vtkKWOptions::AnchorNorthWest: return "nw"; case vtkKWOptions::AnchorCenter: return "center"; default: return ""; } } //---------------------------------------------------------------------------- int vtkKWOptions::GetAnchorFromTkOptionValue(const char *anchor) { if (!anchor) { return vtkKWOptions::AnchorUnknown; } if (!strcmp(anchor, "n")) { return vtkKWOptions::AnchorNorth; } if (!strcmp(anchor, "ne")) { return vtkKWOptions::AnchorNorthEast; } if (!strcmp(anchor, "e")) { return vtkKWOptions::AnchorEast; } if (!strcmp(anchor, "se")) { return vtkKWOptions::AnchorSouthEast; } if (!strcmp(anchor, "s")) { return vtkKWOptions::AnchorSouth; } if (!strcmp(anchor, "sw")) { return vtkKWOptions::AnchorSouthWest; } if (!strcmp(anchor, "w")) { return vtkKWOptions::AnchorWest; } if (!strcmp(anchor, "nw")) { return vtkKWOptions::AnchorNorthWest; } if (!strcmp(anchor, "center")) { return vtkKWOptions::AnchorCenter; } return vtkKWOptions::AnchorUnknown; } //---------------------------------------------------------------------------- const char* vtkKWOptions::GetReliefAsTkOptionValue(int relief) { switch (relief) { case vtkKWOptions::ReliefRaised: return "raised"; case vtkKWOptions::ReliefSunken: return "sunken"; case vtkKWOptions::ReliefFlat: return "flat"; case vtkKWOptions::ReliefRidge: return "ridge"; case vtkKWOptions::ReliefSolid: return "solid"; case vtkKWOptions::ReliefGroove: return "groove"; default: return ""; } } //---------------------------------------------------------------------------- int vtkKWOptions::GetReliefFromTkOptionValue(const char *relief) { if (!relief) { return vtkKWOptions::ReliefUnknown; } if (!strcmp(relief, "raised")) { return vtkKWOptions::ReliefRaised; } if (!strcmp(relief, "sunken")) { return vtkKWOptions::ReliefSunken; } if (!strcmp(relief, "flat")) { return vtkKWOptions::ReliefFlat; } if (!strcmp(relief, "ridge")) { return vtkKWOptions::ReliefRidge; } if (!strcmp(relief, "solid")) { return vtkKWOptions::ReliefSolid; } if (!strcmp(relief, "groove")) { return vtkKWOptions::ReliefGroove; } return vtkKWOptions::ReliefUnknown; } //---------------------------------------------------------------------------- const char* vtkKWOptions::GetJustificationAsTkOptionValue(int justification) { switch (justification) { case vtkKWOptions::JustificationLeft: return "left"; case vtkKWOptions::JustificationCenter: return "center"; case vtkKWOptions::JustificationRight: return "right"; default: return ""; } } //---------------------------------------------------------------------------- int vtkKWOptions::GetJustificationFromTkOptionValue(const char *justification) { if (!justification) { return vtkKWOptions::JustificationUnknown; } if (!strcmp(justification, "left")) { return vtkKWOptions::JustificationLeft; } if (!strcmp(justification, "center")) { return vtkKWOptions::JustificationCenter; } if (!strcmp(justification, "right")) { return vtkKWOptions::JustificationRight; } return vtkKWOptions::JustificationUnknown; } //---------------------------------------------------------------------------- const char* vtkKWOptions::GetSelectionModeAsTkOptionValue(int mode) { switch (mode) { case vtkKWOptions::SelectionModeSingle: return "single"; case vtkKWOptions::SelectionModeBrowse: return "browse"; case vtkKWOptions::SelectionModeMultiple: return "multiple"; case vtkKWOptions::SelectionModeExtended: return "extended"; default: return ""; } } //---------------------------------------------------------------------------- int vtkKWOptions::GetSelectionModeFromTkOptionValue(const char *mode) { if (!mode) { return vtkKWOptions::SelectionModeUnknown; } if (!strcmp(mode, "single")) { return vtkKWOptions::SelectionModeSingle; } if (!strcmp(mode, "browse")) { return vtkKWOptions::SelectionModeBrowse; } if (!strcmp(mode, "multiple")) { return vtkKWOptions::SelectionModeMultiple; } if (!strcmp(mode, "extended")) { return vtkKWOptions::SelectionModeExtended; } return vtkKWOptions::SelectionModeUnknown; } //---------------------------------------------------------------------------- const char* vtkKWOptions::GetOrientationAsTkOptionValue(int orientation) { switch (orientation) { case vtkKWOptions::OrientationHorizontal: return "horizontal"; case vtkKWOptions::OrientationVertical: return "vertical"; default: return ""; } } //---------------------------------------------------------------------------- int vtkKWOptions::GetOrientationFromTkOptionValue(const char *orientation) { if (!orientation) { return vtkKWOptions::OrientationUnknown; } if (!strcmp(orientation, "horizontal")) { return vtkKWOptions::OrientationHorizontal; } if (!strcmp(orientation, "vertical")) { return vtkKWOptions::OrientationVertical; } return vtkKWOptions::OrientationUnknown; } //---------------------------------------------------------------------------- const char* vtkKWOptions::GetStateAsTkOptionValue(int state) { switch (state) { case vtkKWOptions::StateDisabled: return "disabled"; case vtkKWOptions::StateNormal: return "normal"; case vtkKWOptions::StateActive: return "active"; case vtkKWOptions::StateReadOnly: return "readonly"; default: return ""; } } //---------------------------------------------------------------------------- int vtkKWOptions::GetStateFromTkOptionValue(const char *state) { if (!state) { return vtkKWOptions::StateUnknown; } if (!strcmp(state, "disabled")) { return vtkKWOptions::StateDisabled; } if (!strcmp(state, "normal")) { return vtkKWOptions::StateNormal; } if (!strcmp(state, "active")) { return vtkKWOptions::StateActive; } if (!strcmp(state, "readonly")) { return vtkKWOptions::StateReadOnly; } return vtkKWOptions::StateUnknown; } //---------------------------------------------------------------------------- const char* vtkKWOptions::GetCompoundModeAsTkOptionValue(int compound) { switch (compound) { case vtkKWOptions::CompoundModeNone: return "none"; case vtkKWOptions::CompoundModeLeft: return "left"; case vtkKWOptions::CompoundModeCenter: return "center"; case vtkKWOptions::CompoundModeRight: return "right"; case vtkKWOptions::CompoundModeTop: return "top"; case vtkKWOptions::CompoundModeBottom: return "bottom"; default: return ""; } } //---------------------------------------------------------------------------- int vtkKWOptions::GetCompoundModeFromTkOptionValue(const char *compound) { if (!compound) { return vtkKWOptions::CompoundModeUnknown; } if (!strcmp(compound, "none")) { return vtkKWOptions::CompoundModeNone; } if (!strcmp(compound, "left")) { return vtkKWOptions::CompoundModeLeft; } if (!strcmp(compound, "center")) { return vtkKWOptions::CompoundModeCenter; } if (!strcmp(compound, "right")) { return vtkKWOptions::CompoundModeRight; } if (!strcmp(compound, "top")) { return vtkKWOptions::CompoundModeTop; } if (!strcmp(compound, "bottom")) { return vtkKWOptions::CompoundModeBottom; } return vtkKWOptions::CompoundModeUnknown; } //---------------------------------------------------------------------------- void vtkKWOptions::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWTheme.cxx0000644000175000017500000000577410424463540017655 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTheme.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWTheme.h" #include "vtkKWOptions.h" #include "vtkKWApplication.h" #include "vtkObjectFactory.h" #include "vtkKWOptionDataBase.h" #include "vtkKWOptions.h" //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWTheme); vtkCxxRevisionMacro(vtkKWTheme, "$Revision: 1.5 $"); //---------------------------------------------------------------------------- vtkKWTheme::vtkKWTheme() { this->BackupOptionDataBase = NULL; } //---------------------------------------------------------------------------- vtkKWTheme::~vtkKWTheme() { if (this->BackupOptionDataBase) { this->BackupOptionDataBase->Delete(); this->BackupOptionDataBase = NULL; } } //---------------------------------------------------------------------------- void vtkKWTheme::Install() { if (!this->GetApplication()) { return; } this->BackupCurrentOptionDataBase(); /* Here is the kind of thing you could probably do here. Check the Themes example in the Examples/Cxx subdirectory. */ #if 0 vtkKWOptionDataBase *odb = this->GetApplication()->GetOptionDataBase(); odb->AddEntryAsInt("vtkKWLabel", "SetReliefToGroove"); odb->AddEntryAsInt("vtkKWLabel", "SetBorderWidth", 2); odb->AddEntryAsDouble3("vtkKWLabel", "SetBackgroundColor", 0.2, 0.3, 0.6); odb->AddEntryAsDouble3("vtkKWFrame", "SetBackgroundColor", 0.2, 0.3, 0.6); #endif } //---------------------------------------------------------------------------- void vtkKWTheme::Uninstall() { this->RestorePreviousOptionDataBase(); } //---------------------------------------------------------------------------- void vtkKWTheme::BackupCurrentOptionDataBase() { if (!this->GetApplication()) { return; } if (!this->BackupOptionDataBase) { this->BackupOptionDataBase = vtkKWOptionDataBase::New(); } else if (this->BackupOptionDataBase->GetNumberOfEntries()) { return; } this->BackupOptionDataBase->DeepCopy( this->GetApplication()->GetOptionDataBase()); } //---------------------------------------------------------------------------- void vtkKWTheme::RestorePreviousOptionDataBase() { if (!this->GetApplication() || !this->BackupOptionDataBase) { return; } this->GetApplication()->GetOptionDataBase()->DeepCopy( this->BackupOptionDataBase); } //---------------------------------------------------------------------------- void vtkKWTheme::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWToolbar.h0000644000175000017500000002104411111321026017610 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWToolbar.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWToolbar - a frame that holds tool buttons // .SECTION Description // Simply a frame to hold a bunch of tools. It uses bindings to control // the height of the frame. // In the future we could use the object to move toolbars groups around. #ifndef __vtkKWToolbar_h #define __vtkKWToolbar_h #include "vtkKWCompositeWidget.h" class vtkKWFrame; class vtkKWRadioButton; class vtkKWToolbarInternals; class KWWidgets_EXPORT vtkKWToolbar : public vtkKWCompositeWidget { public: static vtkKWToolbar* New(); vtkTypeRevisionMacro(vtkKWToolbar, vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Returns the main frame of the toolbar. // This should be used as the parent of all the widgets in the toolbar. vtkGetObjectMacro(Frame, vtkKWFrame); // Description: // Determines whether the toolbar is resizable. virtual void SetResizable(int); vtkGetMacro(Resizable, int); vtkBooleanMacro(Resizable, int); // Description: // Set/Get the name of the toolbar. This is optional but certainly // useful if this toolbar is meant to be added to a vtkKWToolbarSet vtkGetStringMacro(Name); vtkSetStringMacro(Name); // Description: // Add a widget to the toolbar, insert a widget before 'location' (or at // beginning of list if 'location' is not found) virtual void AddWidget(vtkKWWidget* widget); virtual void InsertWidget(vtkKWWidget* location, vtkKWWidget* widget); // Description: // Add a separator to the toolbar, insert a separator before 'location' (or at // beginning of list if 'location' is not found) virtual void AddSeparator(); virtual void InsertSeparator(vtkKWWidget* location); // Description: // Query widgets virtual int HasWidget(vtkKWWidget* widget); virtual int GetNumberOfWidgets(); // Description: // Remove a widget (or all) from the toolbar virtual void RemoveWidget(vtkKWWidget* widget); virtual void RemoveAllWidgets(); // Description: // Retrieve a widget given its name. The name is looked up in common Tk // options like -label, -text, -image, -selectimage virtual vtkKWWidget* GetWidget(const char *name); // Description: // Retrieve the nth- widget virtual vtkKWWidget* GetNthWidget(int rank); // Description: // Set/Get widget visibility virtual void SetWidgetVisibility(vtkKWWidget *widget, int val); virtual int GetWidgetVisibility(vtkKWWidget *widget); // Description: // Create and add a specific type of widget. // Note: for radiobutton, the variable_name should be the same for // each radiobutton in the set of radiobuttons. // for checkbutton, this is only optional (can be NULL) vtkKWWidget* AddRadioButtonImage(int value, const char *image_name, const char *select_image_name, const char *variable_name, vtkObject *object, const char *method, const char *help = 0); vtkKWWidget* AddCheckButtonImage(const char *image_name, const char *select_image_name, const char *variable_name, vtkObject *object, const char *method, const char *help = 0); // Description: // Update/refresh the widgets layout/aspect virtual void UpdateWidgets(); // Description: // Update/refresh the toolbar layout/aspect (does not include the widgets) virtual void Update(); // Description: // Set/Get the aspect of the toolbar (flat or 3D GUI style, or unchanged) // The static GlobalToolbarAspect member can be set so that all toolbars // are rendered using the same aspect. //BTX enum { ToolbarAspectRelief = 0, ToolbarAspectFlat = 1, ToolbarAspectUnChanged }; //ETX vtkGetMacro(ToolbarAspect, int); virtual void SetToolbarAspect(int); virtual void SetToolbarAspectToFlat(); virtual void SetToolbarAspectToRelief(); virtual void SetToolbarAspectToUnChanged(); static int GetGlobalToolbarAspect(); static void SetGlobalToolbarAspect(int val); static void SetGlobalToolbarAspectToFlat(); static void SetGlobalToolbarAspectToRelief(); static void SetGlobalToolbarAspectToUnChanged(); // Description: // Set/Get the aspect of the widgets (flat, 3D GUI style, or unchanged) // The static GlobalWidgetsAspect member can be set so that all widgets // are rendered using the same aspect. //BTX enum { WidgetsAspectRelief = 0, WidgetsAspectFlat = 1, WidgetsAspectUnChanged }; //ETX vtkGetMacro(WidgetsAspect, int); virtual void SetWidgetsAspect(int); virtual void SetWidgetsAspectToFlat(); virtual void SetWidgetsAspectToRelief(); virtual void SetWidgetsAspectToUnChanged(); static int GetGlobalWidgetsAspect(); static void SetGlobalWidgetsAspect(int val); static void SetGlobalWidgetsAspectToFlat(); static void SetGlobalWidgetsAspectToRelief(); static void SetGlobalWidgetsAspectToUnChanged(); // Description: // Set/Get the padding that will be applied around each widget. // (default to 0 on Windows, 1 otherwise). virtual void SetWidgetsPadX(int); vtkGetMacro(WidgetsPadX, int); virtual void SetWidgetsPadY(int); vtkGetMacro(WidgetsPadY, int); // Description: // Set/Get the padding that will be applied inside each widget. // (default to 0 on Windows, 1 otherwise). virtual void SetWidgetsInternalPadX(int); vtkGetMacro(WidgetsInternalPadX, int); virtual void SetWidgetsInternalPadY(int); vtkGetMacro(WidgetsInternalPadY, int); // Description: // Set/Get the additional internal padding that will be applied around // each widget when WidgetsAspect is On (default to 1). virtual void SetWidgetsFlatAdditionalPadX(int); vtkGetMacro(WidgetsFlatAdditionalPadX, int); virtual void SetWidgetsFlatAdditionalPadY(int); vtkGetMacro(WidgetsFlatAdditionalPadY, int); // Description: // Set/Get the additional internal padding that will be applied inside // each widget when WidgetsAspect is On (default to 1). virtual void SetWidgetsFlatAdditionalInternalPadX(int); vtkGetMacro(WidgetsFlatAdditionalInternalPadX, int); virtual void SetWidgetsFlatAdditionalInternalPadY(int); vtkGetMacro(WidgetsFlatAdditionalInternalPadY, int); // Description: // Schedule the widget to resize itself, or resize it right away virtual void ScheduleResize(); virtual void Resize(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts subwidgets. This will, for example, // enable disable parts of the widget UI, enable disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Some constants //BTX static const char *ToolbarAspectRegKey; static const char *WidgetsAspectRegKey; //ETX protected: vtkKWToolbar(); ~vtkKWToolbar(); // Description: // Create the widget. virtual void CreateWidget(); int Expanding; vtkKWFrame *Frame; vtkKWFrame *Handle; void ConstrainWidgetsLayout(); void UpdateWidgetsLayout(); void UpdateWidgetsAspect(); void UpdateToolbarFrameAspect(); //BTX // PIMPL Encapsulation for STL containers vtkKWToolbarInternals *Internals; //ETX int WidgetsPadX; int WidgetsPadY; int WidgetsFlatAdditionalPadX; int WidgetsFlatAdditionalPadY; int WidgetsInternalPadX; int WidgetsInternalPadY; int WidgetsFlatAdditionalInternalPadX; int WidgetsFlatAdditionalInternalPadY; int ToolbarAspect; int WidgetsAspect; int Resizable; vtkKWRadioButton *DefaultOptionsWidget; char *Name; // Description: // Bind/Unbind events. virtual void Bind(); virtual void UnBind(); private: vtkKWToolbar(const vtkKWToolbar&); // Not implemented void operator=(const vtkKWToolbar&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/Templates/0000755000175000017500000000000011461110202017003 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Templates/KWWidgetsSetupPathsLauncher.c.in0000644000175000017500000001465311242556200025151 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: KWWidgetsSetupPathsLauncher.c.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #include #else #include #endif #include #if defined(PATH_MAX) #define MAX_PATH_len ((size_t)PATH_MAX) #elif defined(MAXPATHLEN) #define MAX_PATH_len ((size_t)MAXPATHLEN) #else #define MAX_PATH_len ((size_t)16384) #endif #define MAX_QUOTED_ARGV 50 int main(int argc, char** argv) { char exe_path[MAX_PATH_len]; char real_exe_path[MAX_PATH_len]; char path_env[MAX_PATH_len]; const char *old_path_env; char ld_path_env[MAX_PATH_len]; const char *old_ld_path_env; char tcllibpath_env[MAX_PATH_len]; const char *old_tcllibpath_env; char pythonpath_env[MAX_PATH_len]; const char *old_pythonpath_env; #if @KWWidgets_USE_INCR_TCL_ENV@ char itcl_library_env[MAX_PATH_len]; char itk_library_env[MAX_PATH_len]; #endif char message[MAX_PATH_len]; char **arg; char current_exe[MAX_PATH_len]; char *slash_pos; #if defined(_WIN32) size_t exe_path_len; #if !defined(__CYGWIN__) char quoted_argv[MAX_QUOTED_ARGV][MAX_PATH_len]; int nb_quoted_argv; #endif #endif /* save the current directory */ char saved_working_directory[MAX_PATH_len+1]; #if defined(_WIN32) _getcwd(saved_working_directory,MAX_PATH_len); #else getcwd(saved_working_directory,MAX_PATH_len); #endif /* PATH */ strcpy(path_env, "PATH=@KWWidgets_PATH_ENV@"); old_path_env = getenv("PATH"); if(old_path_env) { strcat(path_env, "@KWWidgets_PATH_SEP@"); strcat(path_env, old_path_env); } putenv(path_env); /* LD_LIBRARY_PATH and such */ strcpy(ld_path_env, "@SHARED_LIBRARY_PATH_VAR_NAME@=@KWWidgets_SHARED_LIBRARY_PATH_ENV@"); old_ld_path_env = getenv("@SHARED_LIBRARY_PATH_VAR_NAME@"); if(old_ld_path_env) { strcat(ld_path_env, "@KWWidgets_SHARED_LIBRARY_PATH_SEP@"); strcat(ld_path_env, old_ld_path_env); } putenv(ld_path_env); /* TCLLIBPATH */ strcpy(tcllibpath_env, "TCLLIBPATH=@KWWidgets_TCLLIBPATH_ENV@"); old_tcllibpath_env = getenv("TCLLIBPATH"); if(old_tcllibpath_env) { strcat(tcllibpath_env, " "); strcat(tcllibpath_env, old_tcllibpath_env); } putenv(tcllibpath_env); /* PYTHONPATH */ strcpy(pythonpath_env, "PYTHONPATH=@KWWidgets_PYTHONPATH_ENV@"); old_pythonpath_env = getenv("PYTHONPATH"); if(old_pythonpath_env) { strcat(pythonpath_env, "@KWWidgets_PYTHONPATH_SEP@"); strcat(pythonpath_env, old_pythonpath_env); } putenv(pythonpath_env); #if @KWWidgets_USE_INCR_TCL_ENV@ /* ITCL_LIBRARY */ strcpy(itcl_library_env, "ITCL_LIBRARY=@KWWidgets_ITCL_LIBRARY_ENV@"); putenv(itcl_library_env); /* ITK_LIBRARY */ strcpy(itk_library_env, "ITK_LIBRARY=@KWWidgets_ITK_LIBRARY_ENV@"); putenv(itk_library_env); #endif /* Save the native form of the current executable path so that we can set our working dir to its location later on. */ #if defined(_WIN32) && !defined(__CYGWIN__) GetFullPathName(argv[0], MAX_PATH_len, current_exe, 0); #else realpath(argv[0], current_exe); #endif /* Replace this process with the real executable. If no executable was specified for EXECUTABLE, use the first argument that was passed. */ strcpy(exe_path, "@EXECUTABLE@"); if(strlen(exe_path) == 0 && argv) { argv++; if (argv[0]) { strcpy(exe_path, argv[0]); } } /* Append .exe extension if it was not found */ #if defined(_WIN32) exe_path_len = strlen(exe_path); if (exe_path_len < 4 || (strcmp(exe_path + exe_path_len - 4, ".exe") && strcmp(exe_path + exe_path_len - 4, ".EXE") && strcmp(exe_path + exe_path_len - 4, ".com") && strcmp(exe_path + exe_path_len - 4, ".COM"))) { strcat(exe_path, ".exe"); } #endif /* Change the current working dir to the dir of the original executable so that the executable to launch can be found if is relative. */ #if defined(_WIN32) && !defined(__CYGWIN__) slash_pos = strrchr(current_exe, '\\'); #else slash_pos = strrchr(current_exe, '/'); #endif if (slash_pos) { *slash_pos = '\0'; #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__)) _chdir(current_exe); #else chdir(current_exe); #endif } /* Retrieve the native path to the executable to launch; this will use the current working dir if exe_path is relative. */ #if defined(_WIN32) && !defined(__CYGWIN__) GetFullPathName(exe_path, MAX_PATH_len, real_exe_path, 0); #else realpath(exe_path, real_exe_path); #endif argv[0] = real_exe_path; /* Quote unquoted args, otherwise args seem to get mixed up */ #if defined(_WIN32) && !defined(__CYGWIN__) for(argc = 0, nb_quoted_argv = 0; nb_quoted_argv < MAX_QUOTED_ARGV && argv[argc]; ++argc) { if (argv[argc][0] != '"' && strstr(argv[argc], " ") != NULL) { strcpy(quoted_argv[nb_quoted_argv], "\""); strcat(quoted_argv[nb_quoted_argv], argv[argc]); strcat(quoted_argv[nb_quoted_argv], "\""); argv[argc] = quoted_argv[nb_quoted_argv]; nb_quoted_argv++; } } #endif #if defined(_WIN32) && !defined(__CYGWIN__) _chdir(saved_working_directory); #else chdir(saved_working_directory); #endif #if defined(_MSC_VER) /* _execv can't be used as it does not property return the exit value of the process to execute. */ return _spawnv(_P_WAIT, real_exe_path, argv); #else execv(real_exe_path, argv); #endif /* Report why execution failed. */ #if defined(_WIN32) && !defined(__CYGWIN__) #else strcpy(message, strerror(errno)); #endif fprintf(stderr, "Error running"); for(arg = argv; *arg; ++arg) { fprintf(stderr, " \"%s\"", *arg); } fprintf(stderr, ": %s\n", message); (void)argc; return 1; } kwwidgets-1.0.0~cvs20100930/Templates/KWWidgetsContents.in0000644000175000017500000000001310412064776022736 0ustar domibeldomibel${contents}kwwidgets-1.0.0~cvs20100930/Templates/CMakeLists.txt0000644000175000017500000000222311006107365021555 0ustar domibeldomibel# Configuration options that can be exported configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/vtkKWWidgetsConfigure.h.in ${KWWidgets_BINARY_DIR}/vtkKWWidgetsConfigure.h) # Configuration options that are relevant to the build tree only configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/vtkKWWidgetsBuildConfigure.h.in ${KWWidgets_BINARY_DIR}/vtkKWWidgetsBuildConfigure.h) if(NOT KWWidgets_INSTALL_NO_DEVELOPMENT) install_files(${KWWidgets_INSTALL_INCLUDE_DIR} FILES ${KWWidgets_BINARY_DIR}/vtkKWWidgetsConfigure.h) install_files(${KWWidgets_INSTALL_INCLUDE_DIR}/Templates FILES KWWidgetsContents.in KWWidgetsSetupPaths.bat.in KWWidgetsSetupPaths.cmake.in KWWidgetsSetupPaths.csh.in KWWidgetsSetupPaths.sh.in KWWidgetsSetupPathsLauncher.c.in vtkKWWidgetSetSubclass.cxx.in vtkKWWidgetSetSubclass.h.in vtkKWWidgetsPaths.h.in vtkKWWidgetWithLabelSubclass.cxx.in vtkKWWidgetWithLabelSubclass.h.in vtkKWWidgetWithScrollbarsSubclass.cxx.in vtkKWWidgetWithScrollbarsSubclass.h.in vtkKWWidgetWithSpinButtonsSubclass.cxx.in vtkKWWidgetWithSpinButtonsSubclass.h.in) endif(NOT KWWidgets_INSTALL_NO_DEVELOPMENT) kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetWithLabelSubclass.h.in0000644000175000017500000000661310424463545025320 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetWithLabelSubclass.h.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME @WidgetType@WithLabel - a @WidgetType@ associated to a vtkKWLabel // .SECTION Description // This class creates a composite widget associating a @WidgetType@ to a // vtkKWLabel. // As a subclass of vtkKWWidgetWithLabel, it inherits a label and methods to // set its position and visibility. Note that the default label position // implemented in this class is on the left of the @WidgetType@, but // specific positions listed in vtkKWWidgetWithLabel are supported as well. // @ingroup kwwidgets_autogenerated_widget_with_label_group // .SECTION Note // This class and the corresponding code were // \subpage kwwidgets_autogenerated_page "generated automatically" by // instantiating the Templates/vtkKWWidgetWithLabelSubclass.h.in // and Templates/vtkKWWidgetWithLabelSubclass.cxx.in files for // the type @WidgetType@. Classes related to the same template can be found // in the \ref kwwidgets_autogenerated_widget_with_label_group section. // .SECTION See Also // vtkKWWidgetWithLabel @WidgetType@ #ifndef __@WidgetType@WithLabel_h #define __@WidgetType@WithLabel_h #include "vtkKWWidgetWithLabel.h" class @WidgetType@; class KWWidgets_EXPORT @WidgetType@WithLabel : public vtkKWWidgetWithLabel { public: static @WidgetType@WithLabel* New(); vtkTypeRevisionMacro(@WidgetType@WithLabel, vtkKWWidgetWithLabel); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the @WidgetType@ that is being labeled virtual @WidgetType@* GetWidget(); // Description: // Set the layout to allow the widget that is labeled to expand // horizontally automatically virtual void SetExpandWidget(int); vtkBooleanMacro(ExpandWidget, int); vtkGetMacro(ExpandWidget, int); // Description: // Set the string that enables balloon help for this widget. // Override to pass down to children. virtual void SetBalloonHelpString(const char *str); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); protected: @WidgetType@WithLabel(); ~@WidgetType@WithLabel(); // Description: // Create the widget virtual void CreateWidget(); // Description: // Expand the widget that is being labeled int ExpandWidget; // Description: // Pack or repack the widget. To be implemented by subclasses. virtual void Pack(); // Description: // Internal widget @WidgetType@ *Widget; private: @WidgetType@WithLabel(const @WidgetType@WithLabel&); // Not implemented void operator=(const @WidgetType@WithLabel&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetCallbackCommand.h.in0000644000175000017500000000442010363014267024725 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetCallbackCommand.h.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME @WidgetType@CallbackCommand - a callback command // .SECTION Description // This vtkCommand subclass takes a @WidgetType@ as a target, and invoke its // @WidgetType@::ProcessEvent() method when an event is triggered. // @ingroup kwwidgets_autogenerated_widget_callback_command_group // .SECTION Note // This class and the corresponding code were // \subpage kwwidgets_autogenerated_page "generated automatically" by // instantiating the Templates/vtkKWWidgetCallbackCommand.h.in // and Templates/vtkKWWidgetCallbackCommand.cxx.in files for // the type @WidgetType@. Classes related to the same template can be found // in the \ref kwwidgets_autogenerated_widget_callback_command_group section. // .SECTION See Also // vtkCommand @WidgetType@ #ifndef __@WidgetType@CallbackCommand_h #define __@WidgetType@CallbackCommand_h #include "vtkCommand.h" #include "vtkKWWidgets.h" // Needed for export symbols directives class @WidgetType@; class KWWidgets_EXPORT @WidgetType@CallbackCommand : public vtkCommand { public: static @WidgetType@CallbackCommand *New() { return new @WidgetType@CallbackCommand; }; // Description: // Methods that gets executed when an event triggers this command virtual void Execute(vtkObject *caller, unsigned long event, void *callData); // Description: // Set/Get the object a ProcessEvent() method will be invoked on. virtual @WidgetType@* GetTarget(); virtual void SetTarget(@WidgetType@ *target); protected: @WidgetType@CallbackCommand(); ~@WidgetType@CallbackCommand(); @WidgetType@ *Target; private: @WidgetType@CallbackCommand(const @WidgetType@CallbackCommand&); // Not implemented void operator=(const @WidgetType@CallbackCommand&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetsPaths.h.in0000644000175000017500000000153310346363502023176 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetsPaths.h.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #ifndef __vtkKWWidgetsPaths_h #define __vtkKWWidgetsPaths_h #define KWWidgets_EXAMPLES_DIR "${KWWidgets_EXAMPLES_DIR}" #define KWWidgets_TEMPLATES_DIR "${KWWidgets_TEMPLATES_DIR}" #define KWWidgets_RESOURCES_DIR "${KWWidgets_RESOURCES_DIR}" #define KWWidgets_INSTALL_DATA_DIR "${KWWidgets_INSTALL_DATA_DIR}" #endif kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetWithScrollbarsSubclass.h.in0000644000175000017500000000630410424463545026404 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetWithScrollbarsSubclass.h.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME @WidgetType@WithScrollbars - a @WidgetType@ associated to two vtkKWScrollbar's // .SECTION Description // This composite widget provides horizontal and vertical scrolling // capabilities to a core widget. They can be enabled or disabled separately. // As a subclass of vtkKWWidgetWithScrollbars, it inherits methods to // retrieve the scrollbars and set their visibility and layout. // @ingroup kwwidgets_autogenerated_widget_with_scrollbars_group // .SECTION Note // This class and the corresponding code were // \subpage kwwidgets_autogenerated_page "generated automatically" by // instantiating the Templates/vtkKWWidgetWithScrollbarsSubclass.h.in // and Templates/vtkKWWidgetWithScrollbarsSubclass.cxx.in files for // the type @WidgetType@. Classes related to the same template can be found // in the \ref kwwidgets_autogenerated_widget_with_scrollbars_group section. // .SECTION See Also // vtkKWWidgetWithScrollbars @WidgetType@ #ifndef __@WidgetType@WithScrollbars_h #define __@WidgetType@WithScrollbars_h #include "vtkKWWidgetWithScrollbars.h" class vtkKWScrollbar; class @WidgetType@; class KWWidgets_EXPORT @WidgetType@WithScrollbars : public vtkKWWidgetWithScrollbars { public: static @WidgetType@WithScrollbars* New(); vtkTypeRevisionMacro(@WidgetType@WithScrollbars,vtkKWWidgetWithScrollbars); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the @WidgetType@ for which we addded the scrollbars virtual @WidgetType@* GetWidget(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); protected: @WidgetType@WithScrollbars(); ~@WidgetType@WithScrollbars(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Internal widget @WidgetType@ *Widget; // Description: // Create scrollbars and associate the scrollbars to a widget by // setting up the callbacks between both instances. // Re-implemented to set the associated now that we know the internal widget virtual void CreateHorizontalScrollbar(); virtual void CreateVerticalScrollbar(); // Description: // Pack. virtual void Pack(); private: @WidgetType@WithScrollbars(const @WidgetType@WithScrollbars&); // Not implemented void operator=(const @WidgetType@WithScrollbars&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetWithSpinButtonsSubclass.h.in0000644000175000017500000000636710424463545026577 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetWithSpinButtonsSubclass.h.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME @WidgetType@WithSpinButtons - a @WidgetType@ associated to a vtkKWSpinButtons // .SECTION Description // This class creates a composite widget associating a @WidgetType@ to a // vtkKWSpinButtons. // As a subclass of vtkKWWidgetWithSpinButtons, it inherits a set of // spin buttons. // The only requirement is for the @WidgetType@ class to implement the // NextValue() and PreviousValue() callbacks. // @ingroup kwwidgets_autogenerated_widget_with_spinbuttons_group // .SECTION Note // This class and the corresponding code were // \subpage kwwidgets_autogenerated_page "generated automatically" by // instantiating the Templates/vtkKWWidgetWithSpinButtonsSubclass.h.in // and Templates/vtkKWWidgetWithSpinButtonsSubclass.cxx.in files for // the type @WidgetType@. Classes related to the same template can be found // in the \ref kwwidgets_autogenerated_widget_with_spinbuttons_group. // .SECTION See Also // vtkKWWidgetWithSpinButtons @WidgetType@ #ifndef __@WidgetType@WithSpinButtons_h #define __@WidgetType@WithSpinButtons_h #include "vtkKWWidgetWithSpinButtons.h" class @WidgetType@; class KWWidgets_EXPORT @WidgetType@WithSpinButtons : public vtkKWWidgetWithSpinButtons { public: static @WidgetType@WithSpinButtons* New(); vtkTypeRevisionMacro(@WidgetType@WithSpinButtons, vtkKWWidgetWithSpinButtons); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the @WidgetType@ that is being associated to the spin buttons virtual @WidgetType@* GetWidget(); // Description: // Set the string that enables balloon help for this widget. // Override to pass down to children. virtual void SetBalloonHelpString(const char *str); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks virtual void NextValueCallback(); virtual void PreviousValueCallback(); protected: @WidgetType@WithSpinButtons(); ~@WidgetType@WithSpinButtons(); // Description: // Create the widget virtual void CreateWidget(); // Description: // Pack or repack the widget. To be implemented by subclasses. virtual void Pack(); // Description: // Internal widget @WidgetType@ *Widget; private: @WidgetType@WithSpinButtons(const @WidgetType@WithSpinButtons&); // Not implemented void operator=(const @WidgetType@WithSpinButtons&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/Templates/KWWidgetsSetupPaths.sh.in0000644000175000017500000000100110550500116023632 0ustar domibeldomibelexport PATH="${KWWidgets_PATH_ENV}${KWWidgets_PATH_SEP}$PATH" export @SHARED_LIBRARY_PATH_VAR_NAME@="${KWWidgets_SHARED_LIBRARY_PATH_ENV}${KWWidgets_SHARED_LIBRARY_PATH_SEP}$@SHARED_LIBRARY_PATH_VAR_NAME@" export TCLLIBPATH='${KWWidgets_TCLLIBPATH_ENV} '$TCLLIBPATH export PYTHONPATH="${KWWidgets_PYTHONPATH_ENV}${KWWidgets_PYTHONPATH_SEP}$PYTHONPATH" if [ "${KWWidgets_USE_INCR_TCL_ENV}" == "1" ]; then export ITCL_LIBRARY="${KWWidgets_ITCL_LIBRARY_ENV}" export ITK_LIBRARY="${KWWidgets_ITK_LIBRARY_ENV}" fi kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetsConfigure.h.in0000644000175000017500000000214010637777240024046 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetsConfigure.h.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #ifndef __vtkKWWidgetsConfigure_h #define __vtkKWWidgetsConfigure_h #cmakedefine KWWidgets_BUILD_SHARED_LIBS #cmakedefine KWWidgets_USE_HTML_HELP #cmakedefine KWWidgets_USE_INTERNATIONALIZATION #cmakedefine KWWidgets_USE_INCR_TCL #cmakedefine KWWidgets_USE_TKDND #cmakedefine KWWidgets_USE_TKTREECTRL #cmakedefine KWWidgets_BUILD_VTK_WIDGETS #define KWWidgets_MAJOR_VERSION @KWWidgets_MAJOR_VERSION@ #define KWWidgets_MINOR_VERSION @KWWidgets_MINOR_VERSION@ #define KWWidgets_PATCH_VERSION @KWWidgets_PATCH_VERSION@ #define KWWidgets_VERSION "@KWWidgets_VERSION@" #endif kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetCallbackCommand.cxx.in0000644000175000017500000000346410275211575025312 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetCallbackCommand.cxx.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "@WidgetType@CallbackCommand.h" #include "@WidgetType@.h" //---------------------------------------------------------------------------- @WidgetType@CallbackCommand::@WidgetType@CallbackCommand() { this->Target = NULL; } //---------------------------------------------------------------------------- @WidgetType@CallbackCommand::~@WidgetType@CallbackCommand() { this->SetTarget(NULL); } //---------------------------------------------------------------------------- @WidgetType@* @WidgetType@CallbackCommand::GetTarget() { return this->Target; } //---------------------------------------------------------------------------- void @WidgetType@CallbackCommand::SetTarget(@WidgetType@ *arg) { if (this->Target != arg) { if (this->Target) { this->Target->UnRegister(NULL); } this->Target = arg; if (arg) { arg->Register(NULL); } } } //---------------------------------------------------------------------------- void @WidgetType@CallbackCommand::Execute(vtkObject *caller, unsigned long event, void *calldata) { if (this->Target) { this->Target->ProcessEvent(caller, event, calldata); this->AbortFlagOn(); } } kwwidgets-1.0.0~cvs20100930/Templates/KWWidgetsSetupPaths.cmake.in0000644000175000017500000000111211006107365024311 0ustar domibeldomibelset(ENV{PATH} "@KWWidgets_PATH_ENV@@KWWidgets_PATH_SEP@$ENV{PATH}") set(ENV{@SHARED_LIBRARY_PATH_VAR_NAME@} "@KWWidgets_SHARED_LIBRARY_PATH_ENV@@KWWidgets_SHARED_LIBRARY_PATH_SEP@$ENV{@SHARED_LIBRARY_PATH_VAR_NAME@}") set(ENV{TCLLIBPATH} "@KWWidgets_TCLLIBPATH_ENV@ $ENV{TCLLIBPATH}") set(ENV{PYTHONPATH} "@KWWidgets_PYTHONPATH_ENV@@KWWidgets_PYTHONPATH_SEP@$ENV{PYTHONPATH}") if("@KWWidgets_USE_INCR_TCL_ENV@" STREQUAL "1") set(ENV{ITCL_LIBRARY} "@KWWidgets_ITCL_LIBRARY_ENV@") set(ENV{ITK_LIBRARY} "@KWWidgets_ITK_LIBRARY_ENV@") endif("@KWWidgets_USE_INCR_TCL_ENV@" STREQUAL "1") kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetSetSubclass.cxx.in0000644000175000017500000000372510344064071024544 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetSetSubclass.cxx.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "@WidgetType@Set.h" #include "@WidgetType@.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro(@WidgetType@Set); vtkCxxRevisionMacro(@WidgetType@Set, "$Revision: 1.7 $"); //---------------------------------------------------------------------------- @WidgetType@* @WidgetType@Set::GetWidget(int id) { return static_cast<@WidgetType@*>(this->GetWidgetInternal(id)); } //---------------------------------------------------------------------------- @WidgetType@* @WidgetType@Set::AddWidget(int id) { return static_cast<@WidgetType@*>(this->InsertWidgetInternal( id, this->GetNumberOfWidgets())); } //---------------------------------------------------------------------------- @WidgetType@* @WidgetType@Set::InsertWidget(int id, int pos) { return static_cast<@WidgetType@*>(this->InsertWidgetInternal( id, pos)); } //---------------------------------------------------------------------------- vtkKWWidget* @WidgetType@Set::AllocateAndCreateWidget() { @WidgetType@ *widget = @WidgetType@::New(); widget->SetParent(this); widget->Create(); return static_cast(widget); } //---------------------------------------------------------------------------- void @WidgetType@Set::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetWithLabelSubclass.cxx.in0000644000175000017500000001122710672331340025660 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetWithLabelSubclass.cxx.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "@WidgetType@WithLabel.h" #include "vtkKWLabel.h" #include "vtkObjectFactory.h" #include "@WidgetType@.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro(@WidgetType@WithLabel); vtkCxxRevisionMacro(@WidgetType@WithLabel, "$Revision: 1.9 $"); //---------------------------------------------------------------------------- @WidgetType@WithLabel::@WidgetType@WithLabel() { this->ExpandWidget = 1; this->Widget = @WidgetType@::New(); } //---------------------------------------------------------------------------- @WidgetType@WithLabel::~@WidgetType@WithLabel() { if (this->Widget) { this->Widget->Delete(); this->Widget = NULL; } } //---------------------------------------------------------------------------- @WidgetType@* @WidgetType@WithLabel::GetWidget() { return this->Widget; } //---------------------------------------------------------------------------- void @WidgetType@WithLabel::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro("@WidgetType@WithLabel already created"); return; } // Call the superclass this->Superclass::CreateWidget(); // Create the widget if (!this->Widget->GetParent()) { this->Widget->SetParent(this); } this->Widget->Create(); if (!this->Widget->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " failed creating @WidgetType@"); return; } // Pack this->Pack(); // Update enable state this->UpdateEnableState(); } //---------------------------------------------------------------------------- void @WidgetType@WithLabel::Pack() { if (!this->IsCreated()) { return; } // Unpack everything if (this->Widget) { this->Widget->UnpackSiblings(); } // Repack everything vtksys_ios::ostringstream tk_cmd; const char *side; switch (this->LabelPosition) { case vtkKWWidgetWithLabel::LabelPositionTop: side = "top"; break; case vtkKWWidgetWithLabel::LabelPositionBottom: side = "bottom"; break; case vtkKWWidgetWithLabel::LabelPositionRight: side = "right"; break; case vtkKWWidgetWithLabel::LabelPositionDefault: case vtkKWWidgetWithLabel::LabelPositionLeft: default: side = "left"; break; } if (this->LabelVisibility && this->HasLabel() && this->GetLabel()->IsCreated()) { tk_cmd << "pack " << this->GetLabel()->GetWidgetName() << " -anchor nw -side " << side << endl; } if (this->Widget && this->Widget->IsCreated()) { tk_cmd << "pack " << this->Widget->GetWidgetName() << " -anchor nw " << " -fill " << (this->ExpandWidget ? "both" : "none") << " -side " << side << " -expand " << (this->ExpandWidget ? "y" : "n") << endl; } this->Script(tk_cmd.str().c_str()); } // ---------------------------------------------------------------------------- void @WidgetType@WithLabel::SetExpandWidget(int _arg) { if (this->ExpandWidget == _arg) { return; } this->ExpandWidget = _arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void @WidgetType@WithLabel::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->Widget); } // --------------------------------------------------------------------------- void @WidgetType@WithLabel::SetBalloonHelpString(const char *string) { this->Superclass::SetBalloonHelpString(string); if (this->Widget) { this->Widget->SetBalloonHelpString(string); } } //---------------------------------------------------------------------------- void @WidgetType@WithLabel::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "ExpandWidget: " << (this->ExpandWidget ? "On" : "Off") << endl; os << indent << "Widget: "; if (this->Widget) { os << endl; this->Widget->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetWithScrollbarsSubclass.cxx.in0000644000175000017500000000705510424463545026763 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetWithScrollbarsSubclass.cxx.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "@WidgetType@WithScrollbars.h" #include "vtkObjectFactory.h" #include "vtkKWScrollbar.h" #include "@WidgetType@.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro(@WidgetType@WithScrollbars); vtkCxxRevisionMacro(@WidgetType@WithScrollbars, "$Revision: 1.5 $"); //---------------------------------------------------------------------------- @WidgetType@WithScrollbars::@WidgetType@WithScrollbars() { this->Widget = @WidgetType@::New(); } //---------------------------------------------------------------------------- @WidgetType@WithScrollbars::~@WidgetType@WithScrollbars() { if (this->Widget) { this->Widget->Delete(); this->Widget = NULL; } } //---------------------------------------------------------------------------- @WidgetType@* @WidgetType@WithScrollbars::GetWidget() { return this->Widget; } //---------------------------------------------------------------------------- void @WidgetType@WithScrollbars::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Create the widget this->Widget->SetParent(this); this->Widget->Create(); if (!this->Widget->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " failed creating @WidgetType@"); return; } // Now that we have been created, make sure we are associated to // the scrollbars created by the super, *if any* this->AssociateVerticalScrollbarToWidget(this->Widget); this->AssociateHorizontalScrollbarToWidget(this->Widget); // Pack this->Pack(); // Update enable state this->UpdateEnableState(); } //---------------------------------------------------------------------------- void @WidgetType@WithScrollbars::CreateVerticalScrollbar() { this->Superclass::CreateVerticalScrollbar(); this->AssociateVerticalScrollbarToWidget(this->Widget); } //---------------------------------------------------------------------------- void @WidgetType@WithScrollbars::CreateHorizontalScrollbar() { this->Superclass::CreateHorizontalScrollbar(); this->AssociateHorizontalScrollbarToWidget(this->Widget); } //---------------------------------------------------------------------------- void @WidgetType@WithScrollbars::Pack() { this->PackScrollbarsWithWidget(this->Widget); } //---------------------------------------------------------------------------- void @WidgetType@WithScrollbars::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->Widget); } //---------------------------------------------------------------------------- void @WidgetType@WithScrollbars::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Widget: "; if (this->Widget) { os << this->Widget << endl; } else { os << "(None)" << endl; } } kwwidgets-1.0.0~cvs20100930/Templates/KWWidgetsSetupPaths.bat.in0000644000175000017500000000053010547526570024016 0ustar domibeldomibel@SET PATH=${KWWidgets_PATH_ENV}${KWWidgets_PATH_SEP}%PATH% @SET TCLLIBPATH=${KWWidgets_TCLLIBPATH_ENV} %TCLLIBPATH% @SET PYTHONPATH=${KWWidgets_PYTHONPATH_ENV}${KWWidgets_PYTHONPATH_SEP}%PYTHONPATH% @IF "${KWWidgets_USE_INCR_TCL_ENV}" == "1" ( @SET ITCL_LIBRARY=${KWWidgets_ITCL_LIBRARY_ENV} @SET ITK_LIBRARY=${KWWidgets_ITK_LIBRARY_ENV} ) kwwidgets-1.0.0~cvs20100930/Templates/KWWidgetsSetupPaths.csh.in0000644000175000017500000000147510547530411024023 0ustar domibeldomibelsetenv PATH "${KWWidgets_PATH_ENV}${KWWidgets_PATH_SEP}$PATH" if ( $?@SHARED_LIBRARY_PATH_VAR_NAME@ ) then setenv @SHARED_LIBRARY_PATH_VAR_NAME@ "${KWWidgets_SHARED_LIBRARY_PATH_ENV}${KWWidgets_SHARED_LIBRARY_PATH_SEP}$@SHARED_LIBRARY_PATH_VAR_NAME@" else setenv @SHARED_LIBRARY_PATH_VAR_NAME@ "${KWWidgets_SHARED_LIBRARY_PATH_ENV}" endif if ( $?TCLLIBPATH ) then setenv TCLLIBPATH '${KWWidgets_TCLLIBPATH_ENV} '$TCLLIBPATH else setenv TCLLIBPATH '${KWWidgets_TCLLIBPATH_ENV}' endif if ( $?PYTHONPATH ) then setenv PYTHONPATH "${KWWidgets_PYTHONPATH_ENV}${KWWidgets_PYTHONPATH_SEP}$PYTHONPATH" else setenv PYTHONPATH "${KWWidgets_PYTHONPATH_ENV}" endif if ( "${KWWidgets_USE_INCR_TCL_ENV}" == "1" ) then setenv ITCL_LIBRARY "${KWWidgets_ITCL_LIBRARY_ENV}" setenv ITK_LIBRARY "${KWWidgets_ITK_LIBRARY_ENV}" endif kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetSetSubclass.h.in0000644000175000017500000000556310363014267024176 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetSetSubclass.h.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME @WidgetType@Set - a concrete set of @WidgetType@ // .SECTION Description // A composite widget to conveniently store, allocate, create and pack a // set of @WidgetType@. // Each @WidgetType@ is created, removed or queried based // on a unique ID provided by the user (ids are *not* handled by the class // since it is likely that they will be defined as enum's or #define by // the user for easier retrieval). // As a subclass of vtkKWWidgetSet, it inherits methods to set the widgets // visibility individually, set the layout parameters, and query each widget. // Widgets are packed (gridded) in the order they were added. // @ingroup kwwidgets_autogenerated_widget_set_group // .SECTION Note // This class and the corresponding code were // \subpage kwwidgets_autogenerated_page "generated automatically" by // instantiating the Templates/vtkKWWidgetSetSubclass.h.in // and Templates/vtkKWWidgetSetSubclass.cxx.in files for // the type @WidgetType@. Classes related to the same template can be found // in the \ref kwwidgets_autogenerated_widget_set_group section. // .SECTION See Also // vtkKWWidgetSet @WidgetType@ #ifndef __@WidgetType@Set_h #define __@WidgetType@Set_h #include "vtkKWWidgetSet.h" class @WidgetType@; class KWWidgets_EXPORT @WidgetType@Set : public vtkKWWidgetSet { public: static @WidgetType@Set* New(); vtkTypeRevisionMacro(@WidgetType@Set,vtkKWWidgetSet); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Add a @WidgetType@ to the end of the set. // The id has to be unique among the set. // Return a pointer to the @WidgetType@, or NULL on error. virtual @WidgetType@* AddWidget(int id); // Description: // Insert a @WidgetType@ at a specific position in the set. // The id has to be unique among the set. // Return a pointer to the @WidgetType@, or NULL on error. virtual @WidgetType@* InsertWidget(int id, int pos); // Description: // Get a @WidgetType@ from the set, given its unique id. // Return a pointer to the @WidgetType@, or NULL on error. virtual @WidgetType@* GetWidget(int id); protected: @WidgetType@Set() {}; ~@WidgetType@Set() {}; // Helper methods virtual vtkKWWidget* AllocateAndCreateWidget(); private: @WidgetType@Set(const @WidgetType@Set&); // Not implemented void operator=(const @WidgetType@Set&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetsBuildConfigure.h.in0000644000175000017500000000167110410610200025001 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetsBuildConfigure.h.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #ifndef __vtkKWWidgetsBuildConfigure_h #define __vtkKWWidgetsBuildConfigure_h #ifndef KWWidgets_TclTk_INSTALL_LIB_DIR #define KWWidgets_TclTk_INSTALL_LIB_DIR "${KWWidgets_TclTk_INSTALL_LIB_DIR}" #endif #ifndef KWWidgets_INSTALL_DATA_DIR #define KWWidgets_INSTALL_DATA_DIR "${KWWidgets_INSTALL_DATA_DIR}" #endif #ifndef VTK_USE_VIDEO_FOR_WINDOWS #cmakedefine VTK_USE_VIDEO_FOR_WINDOWS #endif #endif kwwidgets-1.0.0~cvs20100930/Templates/vtkKWWidgetWithSpinButtonsSubclass.cxx.in0000644000175000017500000001023510661115507027132 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetWithSpinButtonsSubclass.cxx.in,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "@WidgetType@WithSpinButtons.h" #include "vtkKWSpinButtons.h" #include "vtkObjectFactory.h" #include "@WidgetType@.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro(@WidgetType@WithSpinButtons); vtkCxxRevisionMacro(@WidgetType@WithSpinButtons, "$Revision: 1.6 $"); //---------------------------------------------------------------------------- @WidgetType@WithSpinButtons::@WidgetType@WithSpinButtons() { this->Widget = @WidgetType@::New(); } //---------------------------------------------------------------------------- @WidgetType@WithSpinButtons::~@WidgetType@WithSpinButtons() { if (this->Widget) { this->Widget->Delete(); this->Widget = NULL; } } //---------------------------------------------------------------------------- @WidgetType@* @WidgetType@WithSpinButtons::GetWidget() { return this->Widget; } //---------------------------------------------------------------------------- void @WidgetType@WithSpinButtons::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro("@WidgetType@WithSpinButtons already created"); return; } // Call the superclass this->Superclass::CreateWidget(); // Create the widget if (!this->Widget->GetParent()) { this->Widget->SetParent(this); } this->Widget->Create(); if (!this->Widget->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " failed creating @WidgetType@"); return; } // Pack this->Pack(); // Update enable state this->UpdateEnableState(); } //---------------------------------------------------------------------------- void @WidgetType@WithSpinButtons::Pack() { if (!this->IsCreated()) { return; } // Unpack everything if (this->Widget) { this->Widget->UnpackSiblings(); } // Repack everything vtksys_ios::ostringstream tk_cmd; if (this->Widget && this->Widget->IsCreated()) { tk_cmd << "pack " << this->Widget->GetWidgetName() << " -anchor nw -side left -fill both -expand y" << endl; } if (this->SpinButtons && this->SpinButtons->IsCreated()) { tk_cmd << "pack " << this->SpinButtons->GetWidgetName() << " -anchor ne -side right -fill y -expand n" << endl; } this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void @WidgetType@WithSpinButtons::NextValueCallback() { if (this->Widget) { this->Widget->NextValue(); } } //---------------------------------------------------------------------------- void @WidgetType@WithSpinButtons::PreviousValueCallback() { if (this->Widget) { this->Widget->PreviousValue(); } } //---------------------------------------------------------------------------- void @WidgetType@WithSpinButtons::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->Widget); } // --------------------------------------------------------------------------- void @WidgetType@WithSpinButtons::SetBalloonHelpString(const char *string) { this->Superclass::SetBalloonHelpString(string); if (this->Widget) { this->Widget->SetBalloonHelpString(string); } } //---------------------------------------------------------------------------- void @WidgetType@WithSpinButtons::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Widget: "; if (this->Widget) { os << endl; this->Widget->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWBalloonHelpManager.cxx0000644000175000017500000002475410756660473022320 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWBalloonHelpManager.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWBalloonHelpManager.h" #include "vtkKWLabel.h" #include "vtkKWWidget.h" #include "vtkKWTopLevel.h" #include "vtkKWApplication.h" #include "vtkKWTkUtilities.h" #include "vtkKWWindowBase.h" #include "vtkObjectFactory.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWBalloonHelpManager ); vtkCxxRevisionMacro(vtkKWBalloonHelpManager, "$Revision: 1.15 $"); //---------------------------------------------------------------------------- vtkKWBalloonHelpManager::vtkKWBalloonHelpManager() { this->CurrentWidget = NULL; this->AfterTimerId = NULL; this->TopLevel = NULL; this->Label = NULL; this->Delay = 1200; this->Visibility = 1; this->IgnoreIfNotEnabled = 0; } //---------------------------------------------------------------------------- vtkKWBalloonHelpManager::~vtkKWBalloonHelpManager() { this->SetCurrentWidget(NULL); this->SetAfterTimerId(NULL); if (this->TopLevel) { this->TopLevel->Delete(); this->TopLevel = NULL; } if (this->Label) { this->Label->Delete(); this->Label = NULL; } } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::CreateBalloon() { if (!this->TopLevel) { this->TopLevel = vtkKWTopLevel::New(); } if (!this->Label) { this->Label = vtkKWLabel::New(); } vtkKWApplication *app = this->GetApplication(); if (!app && this->CurrentWidget) { app = this->CurrentWidget->GetApplication(); } if (app) { if (!this->TopLevel->IsCreated()) { this->TopLevel->HideDecorationOn(); this->TopLevel->SetApplication(app); this->TopLevel->Create(); this->TopLevel->SetBackgroundColor(0.0, 0.0, 0.0); this->TopLevel->SetBorderWidth(1); this->TopLevel->SetReliefToFlat(); } if (!this->Label->IsCreated() && this->TopLevel) { this->Label->SetParent(this->TopLevel); this->Label->Create(); this->Label->SetBackgroundColor(1.0, 1.0, 0.88); this->Label->SetForegroundColor(0.0, 0.0, 0.0); this->Label->SetJustificationToLeft(); this->Label->SetWrapLength("2i"); app->Script("pack %s", this->Label->GetWidgetName()); } } } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::TriggerCallback(vtkKWWidget *widget) { if (!widget || !widget->IsAlive() || this->ApplicationInExit()) { return; } // If there is no help string, do not bother if (!this->Visibility || (this->IgnoreIfNotEnabled && !widget->GetEnabled()) || (!widget->GetBalloonHelpString() && !widget->GetBalloonHelpIcon())) { this->SetAfterTimerId(NULL); return; } // Cancel the previous balloon help, and setup the new one this->CancelCallback(); this->SetCurrentWidget(widget); this->SetAfterTimerId( widget->Script("after %d {catch {%s DisplayCallback %s}}", this->Delay, this->GetTclName(), widget->GetTclName())); } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::CancelCallback() { if (!this->GetApplication() || this->ApplicationInExit()) { return; } // Cancel the previous timer if (this->AfterTimerId) { vtkKWTkUtilities::CancelTimerHandler( this->GetApplication(), this->AfterTimerId); this->SetAfterTimerId(NULL); } this->SetCurrentWidget(NULL); // Hide the balloon help if (this->TopLevel) { this->TopLevel->Withdraw(); } } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::WithdrawCallback() { if (!this->GetApplication() || this->ApplicationInExit()) { return; } // Hide the balloon help if (this->TopLevel) { this->TopLevel->Withdraw(); } // Re-schedule the balloon help for the current widget (if any) if (this->CurrentWidget) { this->TriggerCallback(this->CurrentWidget); } } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::DisplayCallback(vtkKWWidget *widget) { if (!this->GetApplication() || this->ApplicationInExit() || !this->Visibility || !widget || !widget->IsAlive() || (this->IgnoreIfNotEnabled && !widget->GetEnabled())) { return; } // If there is no help string, return if (!widget->GetBalloonHelpString() && !widget->GetBalloonHelpIcon()) { this->SetAfterTimerId(NULL); return; } // Create the UI, set the help string this->CreateBalloon(); if (widget->GetBalloonHelpIcon()) { this->Label->SetImageToIcon(widget->GetBalloonHelpIcon()); } else { this->Label->SetText(widget->GetBalloonHelpString()); } // Get the position of the mouse int pointer_x, pointer_y; vtkKWTkUtilities::GetMousePointerCoordinates(widget, &pointer_x, &pointer_y); // Get the position of the upper-left corner of the parent in its screen int parent_x; vtkKWTkUtilities::GetWidgetCoordinates(widget->GetParent(), &parent_x, NULL); // Get the size of the parent int parent_width; vtkKWTkUtilities::GetWidgetSize(widget->GetParent(), &parent_width, NULL); // Get the size of the balloon window int balloon_width, balloon_height; vtkKWTkUtilities::GetWidgetRequestedSize( this->Label, &balloon_width, &balloon_height); // Set the position of the widget relative to the mouse // Try to keep the help from going past the right edge of the widget // If it goes too far right, move it to the left, // but not past the left edge of the parent widget if (pointer_x + balloon_width > parent_x + parent_width) { pointer_x = parent_x + parent_width - balloon_width; if (pointer_x < parent_x) { pointer_x = parent_x; } } // Try to put the balloon under the mouse cursor, unless we found a // vtkKWRenderWidget. This is done for convenience, to avoid popping up // something on top of a render window; once the balloon disappears, this // would trigger a re-render... int distance_y_to_widget = 15; int balloon_bottom_y = pointer_y + distance_y_to_widget + balloon_height; vtkKWWindowBase *win = vtkKWWindowBase::SafeDownCast( widget->GetParentTopLevel()); vtkKWWidget *found_rw = vtkKWTkUtilities::ContainsCoordinatesForSpecificType( win, pointer_x, balloon_bottom_y, "vtkKWRenderWidget"); if (!found_rw) { found_rw = vtkKWTkUtilities::ContainsCoordinatesForSpecificType( win, pointer_x + balloon_width, balloon_bottom_y, "vtkKWRenderWidget"); } if (found_rw) { distance_y_to_widget = -distance_y_to_widget - balloon_height; if (pointer_y + distance_y_to_widget < 0) { distance_y_to_widget = -pointer_y; } } // Place the balloon this->TopLevel->SetPosition(pointer_x, pointer_y + distance_y_to_widget); this->GetApplication()->ProcessPendingEvents(); // Map the balloon if (this->AfterTimerId) { this->TopLevel->DeIconify(); this->TopLevel->Raise(); } this->SetAfterTimerId(NULL); } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::SetVisibility(int v) { if (this->Visibility == v) { return; } this->Visibility = v; this->Modified(); if (!this->Visibility) { this->CancelCallback(); } } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::SetCurrentWidget(vtkKWWidget *widget) { if (this->CurrentWidget == widget || (this->ApplicationInExit() && widget)) { return; } #if 0 if (this->CurrentWidget) { this->CurrentWidget->UnRegister(this); this->CurrentWidget = NULL; } if (widget) { this->CurrentWidget = widget; this->CurrentWidget->Register(this); } #else this->CurrentWidget = widget; #endif this->Modified(); } //---------------------------------------------------------------------------- int vtkKWBalloonHelpManager::ApplicationInExit() { vtkKWApplication *app = this->GetApplication(); if (!app && this->CurrentWidget) { app = this->CurrentWidget->GetApplication(); } return (app && app->GetInExit()) ? 1 : 0; } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::AddBindings(vtkKWWidget *widget) { if (!widget || !widget->IsAlive()) { return; } if (strstr(widget->GetBinding(""), "TriggerCallback")) { return; } vtksys_stl::string command("TriggerCallback "); command += widget->GetTclName(); widget->AddBinding("", this, command.c_str()); widget->AddBinding("", this, "WithdrawCallback"); widget->AddBinding("", this, "WithdrawCallback"); widget->AddBinding("", this, "WithdrawCallback"); widget->AddBinding("", this, "CancelCallback"); } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::RemoveBindings(vtkKWWidget *widget) { if (!widget || !widget->IsAlive()) { return; } vtksys_stl::string command("TriggerCallback "); command += widget->GetTclName(); widget->RemoveBinding("", this, command.c_str()); widget->RemoveBinding("", this, "WithdrawCallback"); widget->RemoveBinding("", this, "WithdrawCallback"); widget->RemoveBinding("", this, "WithdrawCallback"); widget->RemoveBinding("", this, "CancelCallback"); } //---------------------------------------------------------------------------- void vtkKWBalloonHelpManager::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Visibility: " << (this->Visibility ? "on":"off") << endl; os << indent << "IgnoreIfNotEnabled: " << (this->IgnoreIfNotEnabled ? "on":"off") << endl; os << indent << "Delay: " << this->GetDelay() << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWEvent.h0000644000175000017500000001645511207300627017313 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWEvent.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWEvent - Event enumeration. #ifndef __vtkKWEvent_h #define __vtkKWEvent_h #include "vtkKWWidgets.h" // Needed for export symbols directives class KWWidgets_EXPORT vtkKWEvent { public: static const char* GetStringFromEventId(unsigned long event); static unsigned long GetEventIdFromString(const char* event); enum { KWWidgetEvents = 2000, MessageDialogInvokeEvent, FocusInEvent, FocusOutEvent, // VV AngleVisibilityChangedEvent, AnnotationColorChangedEvent, ApplicationAreaChangedEvent, BackgroundColorChangedEvent, ContourAnnotationActiveChangedEvent, ContourAnnotationAddAtPositionEvent, ContourAnnotationAddEvent, ContourAnnotationColorByScalarsChangedEvent, ContourAnnotationColorChangedEvent, ContourAnnotationComputeStatisticsEvent, ContourAnnotationLineWidthChangedEvent, ContourAnnotationOpacityChangedEvent, ContourAnnotationRemoveAllEvent, ContourAnnotationRemoveEvent, ContourAnnotationSurfacePropertyChangedEvent, ContourAnnotationSurfaceQualityChangedEvent, ContourAnnotationSurfaceRepresentationChangedEvent, ContourAnnotationVisibilityChangedEvent, ControlLeftMouseOptionChangedEvent, ControlMiddleMouseOptionChangedEvent, ControlRightMouseOptionChangedEvent, CroppingPlanesPositionChangedEvent, CroppingRegionFlagsChangedEvent, CroppingRegionsVisibilityChangedEvent, Cursor3DInteractiveStateChangedEvent, Cursor3DPositionChangedEvent, Cursor3DPositionChangingEvent, Cursor3DTypeChangedEvent, Cursor3DVisibilityChangedEvent, Cursor3DXColorChangedEvent, Cursor3DYColorChangedEvent, Cursor3DZColorChangedEvent, DataFileNameChangedEvent, DistanceVisibilityChangedEvent, EnableShadingEvent, GradientOpacityFunctionChangedEvent, GradientOpacityFunctionPresetApplyEvent, GradientOpacityStateChangedEvent, HistogramChangedEvent, ImageAngleVisibilityChangedEvent, ImageBackgroundColorChangedEvent, ImageCameraFocalPointAndPositionChangedEvent, ImageCameraResetEvent, ImageColorMappingEvent, ImageCornerAnnotationChangedEvent, ImageDistanceVisibilityChangedEvent, ImageHeaderAnnotationChangedEvent, ImageInterpolateEvent, ImageMouseBindingChangedEvent, ImageScaleBarColorChangedEvent, ImageScaleBarVisibilityChangedEvent, BeginImageSliceChangeEvent, ImageSliceChangedEvent, ImageZoomFactorChangedEvent, InteractionModeChangedEvent, InteractiveRenderStartEvent, LeftMouseOptionChangedEvent, LightActiveChangedEvent, LightColorChangedEvent, LightIntensityChangedEvent, LightPositionChangedEvent, LightVisibilityChangedEvent, LightboxOrientationChangedEvent, LightboxResolutionChangedEvent, Marker2DColorChangedEvent, Marker2DPositionChangedEvent, Marker2DVisibilityChangedEvent, Marker3DAddMarkerEvent, Marker3DAddMarkerInGroupEvent, Marker3DAddMarkersGroupEvent, Marker3DColorChangedEvent, Marker3DPositionChangedEvent, Marker3DRemoveAllMarkerGroupsEvent, Marker3DRemoveAllMarkersEvent, Marker3DRemoveSelectedMarkerEvent, Marker3DRemoveSelectedMarkerGroupEvent, Marker3DSelectMarkerGroupEvent, Marker3DVisibilityChangedEvent, MaterialPropertyChangedEvent, MaterialPropertyChangingEvent, MiddleMouseOptionChangedEvent, MouseBindingChangedEvent, MouseOperationsChangedEvent, NotebookHidePageEvent, NotebookPinPageEvent, NotebookRaisePageEvent, NotebookShowPageEvent, NotebookUnpinPageEvent, ObjectActionEvent, ObjectNameChangedEvent, ObjectSetChangedEvent, ObjectStateChangedEvent, ObliqueProbeColorChangedEvent, ObliqueProbeMovementEvent, ObliqueProbeResetEvent, ObliqueProbeScalarsVisibilityChangedEvent, ObliqueProbeVisibilityChangedEvent, PerspectiveViewAngleChangedEvent, PluginFilterApplyEvent, PluginFilterApplyPrepareEvent, PluginFilterCancelEvent, PluginFilterListAddedEvent, PluginFilterListEvent, PluginFilterListRemovedEvent, PluginFilterRedoEvent, PluginFilterRemoveMeshEvent, PluginFilterSelectEvent, PluginFilterUndoEvent, ProbeImageRollPlaneEvent, ProbeImageTiltPlaneEvent, ProbeImageTranslatePlaneEvent, ProbeInformationChangedEvent, ProbeInformationOffEvent, ProjectionTypeChangedEvent, ReceiveRemoteSessionEvent, RenderEvent, RenderWidgetInSelectionFrameChangedEvent, ResliceChangedEvent, ResliceChangingEvent, RightMouseOptionChangedEvent, ScalarColorFunctionChangedEvent, ScalarColorFunctionPresetApplyEvent, ScalarComponentChangedEvent, ScalarComponentWeightChangedEvent, ScalarComponentWeightChangingEvent, ScalarOpacityFunctionChangedEvent, ScalarOpacityFunctionPresetApplyEvent, ScaleBarVisibilityChangedEvent, SelectionChangedEvent, ShiftLeftMouseOptionChangedEvent, ShiftMiddleMouseOptionChangedEvent, ShiftRightMouseOptionChangedEvent, StandardInteractivityChangedEvent, SurfacePropertyChangedEvent, SurfacePropertyChangingEvent, SwitchToVolumeProEvent, TimeChangedEvent, TransferFunctionsChangedEvent, TransferFunctionsChangingEvent, UserInterfaceVisibilityChangedEvent, ViewAnnotationChangedEvent, ViewTextLabelChangedEvent, ViewSelectedEvent, VolumeBackgroundColorChangedEvent, VolumeBlendModeChangedEvent, VolumeBoundingBoxColorChangedEvent, VolumeBoundingBoxVisibilityChangedEvent, VolumeCameraResetEvent, VolumeCornerAnnotationChangedEvent, VolumeDistanceVisibilityChangedEvent, VolumeFlySpeedChangedEvent, VolumeHeaderAnnotationChangedEvent, VolumeMapperRenderEndEvent, VolumeMapperRenderStartEvent, VolumeMaterialPropertyChangedEvent, VolumeMaterialPropertyChangingEvent, VolumeMouseBindingChangedEvent, VolumeOrientationMarkerColorChangedEvent, VolumeOrientationMarkerVisibilityChangedEvent, VolumePropertyChangedEvent, VolumePropertyChangingEvent, VolumeReformatBoxVisibilityChangedEvent, VolumeReformatChangedEvent, VolumeReformatManipulationStyleChangedEvent, VolumeReformatPlaneChangedEvent, VolumeReformatThicknessChangedEvent, VolumeScalarBarComponentChangedEvent, VolumeScalarBarWidgetChangedEvent, VolumeScaleBarColorChangedEvent, VolumeScaleBarVisibilityChangedEvent, VolumeStandardCameraViewEvent, VolumeZSamplingChangedEvent, WindowInterfaceChangedEvent, WindowLayoutChangedEvent, WindowLevelChangedEvent, WindowLevelChangingEndEvent, WindowLevelChangingEvent, WindowLevelResetEvent, // PV ErrorMessageEvent, InitializeTraceEvent, ManipulatorModifiedEvent, WarningMessageEvent, InformationMessageEvent, DebugMessageEvent, SourceDeletedEvent, // FinalBogusNotUsedEvent }; }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWExtent.h0000644000175000017500000002327011221206160017463 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWExtent.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWExtent - six sliders defining a (xmin,xmax,ymin,ymax,zmin,zmax) extent // .SECTION Description // vtkKWExtent is a widget containing six sliders which represent the // xmin, xmax, ymin, ymax, zmin, zmax extent of a volume. It is a // convinience object and has logic to keep the min values less than // or equal to the max values. #ifndef __vtkKWExtent_h #define __vtkKWExtent_h #include "vtkKWCompositeWidget.h" #include "vtkKWRange.h" // Needed for some constants class KWWidgets_EXPORT vtkKWExtent : public vtkKWCompositeWidget { public: static vtkKWExtent* New(); vtkTypeRevisionMacro(vtkKWExtent,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set the Range of the Extent, this is the range of // acceptable values for the sliders. Specified as // minx maxx miny maxy minz maxz virtual void SetExtentRange(const double extent[6]); virtual void SetExtentRange(double, double, double, double, double, double); virtual double* GetExtentRange(); virtual void GetExtentRange( double&, double&, double&, double&, double&, double&); virtual void GetExtentRange(double extent[6]); // Description: // Set/Get the Extent. vtkGetVector6Macro(Extent,double); virtual void SetExtent(const double extent[6]); virtual void SetExtent(double, double, double, double, double, double); // Description: // Set/Get the visibility of the extent selectively (x, y, z). virtual void SetExtentVisibility(int index, int arg); vtkBooleanMacro(XExtentVisibility, int); virtual int GetXExtentVisibility() { return this->ExtentVisibility[0]; }; virtual void SetXExtentVisibility(int arg) { this->SetExtentVisibility(0, arg); }; vtkBooleanMacro(YExtentVisibility, int); virtual int GetYExtentVisibility() { return this->ExtentVisibility[1]; }; virtual void SetYExtentVisibility(int arg) { this->SetExtentVisibility(1, arg); }; vtkBooleanMacro(ZExtentVisibility, int); virtual int GetZExtentVisibility() { return this->ExtentVisibility[2]; }; virtual void SetZExtentVisibility(int arg) { this->SetExtentVisibility(2, arg); }; // Description: // Specifies commands to associate with the widget. // 'Command' is invoked when the widget value is changing (i.e. during // user interaction). // 'StartCommand' is invoked at the beginning of a user interaction with // the widget (when a mouse button is pressed over the widget for example). // 'EndCommand' is invoked at the end of the user interaction with the // widget (when the mouse button is released for example). // The need for a 'Command', 'StartCommand' and 'EndCommand' can be // explained as follows: 'EndCommand' can be used to be notified about any // changes made to this widget *after* the corresponding user interaction has // been performed (say, after releasing the mouse button that was dragging // a slider, or after clicking on a checkbutton). 'Command' can be set // *additionally* to be notified about the intermediate changes that // occur *during* the corresponding user interaction (say, *while* dragging // a slider). While setting 'EndCommand' is enough to be notified about // any changes, setting 'Command' is an application-specific choice that // is likely to depend on how fast you want (or can) answer to rapid changes // occuring during a user interaction, if any. 'StartCommand' is rarely // used but provides an opportunity for the application to modify its // state and prepare itself for user-interaction; in that case, the // 'EndCommand' is usually set in a symmetric fashion to set the application // back to its previous state. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the current extent: int, int, int, int, int, int (if the Resolution of // all the visible ranges are integer); double, double, double, double, // double, double otherwise. // Note: the 'int' signature is for convenience, so that the command can // be set to a callback accepting 'int'. In doubt, implement the callback // using a 'double' signature that will accept both 'int' and 'double'. virtual void SetCommand(vtkObject *object, const char *method); virtual void SetStartCommand(vtkObject *object, const char *method); virtual void SetEndCommand(vtkObject *object, const char *method); // Description: // Events. The events are triggered when the extent slider is changed. //BTX enum { ChangeEvent = 10000, StartChangeEvent = 10001, EndChangeEvent = 10002 }; //ETX // Description: // Set/Get whether the above commands should be called or not. virtual void SetDisableCommands(int); vtkBooleanMacro(DisableCommands, int); // Description: // Set the ranges orientations and item positions. // This just propagates the same method to the internal ranges. virtual void SetOrientation(int); virtual void SetOrientationToHorizontal() { this->SetOrientation(vtkKWRange::OrientationHorizontal); }; virtual void SetOrientationToVertical() { this->SetOrientation(vtkKWRange::OrientationVertical); }; virtual void SetLabelPosition(int); virtual void SetLabelPositionToDefault() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionDefault); }; virtual void SetLabelPositionToTop() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionTop); }; virtual void SetLabelPositionToBottom() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionBottom); }; virtual void SetLabelPositionToLeft() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionLeft); }; virtual void SetLabelPositionToRight() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionRight); }; virtual void SetEntry1Position(int); virtual void SetEntry1PositionToDefault() { this->SetEntry1Position(vtkKWRange::EntryPositionDefault); }; virtual void SetEntry1PositionToTop() { this->SetEntry1Position(vtkKWRange::EntryPositionTop); }; virtual void SetEntry1PositionToBottom() { this->SetEntry1Position(vtkKWRange::EntryPositionBottom); }; virtual void SetEntry1PositionToLeft() { this->SetEntry1Position(vtkKWRange::EntryPositionLeft); }; virtual void SetEntry1PositionToRight() { this->SetEntry1Position(vtkKWRange::EntryPositionRight); }; virtual void SetEntry2Position(int); virtual void SetEntry2PositionToDefault() { this->SetEntry2Position(vtkKWRange::EntryPositionDefault); }; virtual void SetEntry2PositionToTop() { this->SetEntry2Position(vtkKWRange::EntryPositionTop); }; virtual void SetEntry2PositionToBottom() { this->SetEntry2Position(vtkKWRange::EntryPositionBottom); }; virtual void SetEntry2PositionToLeft() { this->SetEntry2Position(vtkKWRange::EntryPositionLeft); }; virtual void SetEntry2PositionToRight() { this->SetEntry2Position(vtkKWRange::EntryPositionRight); }; virtual void SetThickness(int); virtual void SetInternalThickness(double); virtual void SetRequestedLength(int); virtual void SetSliderSize(int); virtual void SetSliderCanPush(int); vtkBooleanMacro(SliderCanPush, int); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Access the internal vtkKWRange's. vtkKWRange* GetXRange() { return this->Range[0]; }; vtkKWRange* GetYRange() { return this->Range[1]; }; vtkKWRange* GetZRange() { return this->Range[2]; }; vtkKWRange* GetRange(int index); // Description: // Callbacks. Internal, do not use. virtual void RangeCommandCallback(double r0, double r1); virtual void RangeStartCommandCallback(double r0, double r1); virtual void RangeEndCommandCallback(double r0, double r1); virtual void RangeEntriesCommandCallback(double r0, double r1); protected: vtkKWExtent(); ~vtkKWExtent(); // Description: // Create the widget. virtual void CreateWidget(); char *Command; char *StartCommand; char *EndCommand; virtual void InvokeExtentCommand( const char *command, double x0, double x1, double y0, double y1, double z0, double z1); virtual void InvokeCommand( double x0, double x1, double y0, double y1, double z0, double z1); virtual void InvokeStartCommand( double x0, double x1, double y0, double y1, double z0, double z1); virtual void InvokeEndCommand( double x0, double x1, double y0, double y1, double z0, double z1); double Extent[6]; vtkKWRange *Range[3]; int ExtentVisibility[3]; // Pack or repack the widget virtual void Pack(); private: // Temporary var for wrapping purposes double ExtentRangeTemp[6]; vtkKWExtent(const vtkKWExtent&); // Not implemented void operator=(const vtkKWExtent&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWScalarComponentSelectionWidget.h0000644000175000017500000000767510424463540024344 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWScalarComponentSelectionWidget.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWScalarComponentSelectionWidget - a scalar component selection widget // .SECTION Description // This class contains the UI for scalar component selection. #ifndef __vtkKWScalarComponentSelectionWidget_h #define __vtkKWScalarComponentSelectionWidget_h #include "vtkKWCompositeWidget.h" class vtkKWMenuButtonWithLabel; class KWWidgets_EXPORT vtkKWScalarComponentSelectionWidget : public vtkKWCompositeWidget { public: static vtkKWScalarComponentSelectionWidget* New(); void PrintSelf(ostream& os, vtkIndent indent); vtkTypeRevisionMacro(vtkKWScalarComponentSelectionWidget,vtkKWCompositeWidget); // Description: // Are the components independent of each other? virtual void SetIndependentComponents(int); vtkGetMacro(IndependentComponents, int); vtkBooleanMacro(IndependentComponents, int); // Description: // Set/Get the number of components controlled by the widget virtual void SetNumberOfComponents(int); vtkGetMacro(NumberOfComponents, int); // Description: // Set/Get the current component controlled by the widget (if controllable) virtual void SetSelectedComponent(int); vtkGetMacro(SelectedComponent, int); // Description: // Allow component selection (a quick way to hide the UI) virtual void SetAllowComponentSelection(int); vtkBooleanMacro(AllowComponentSelection, int); vtkGetMacro(AllowComponentSelection, int); // Description: // Update the whole UI depending on the value of the Ivars virtual void Update(); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the selected component is changed. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the selected component: int virtual void SetSelectedComponentChangedCommand( vtkObject *object, const char *method); // Description: // Access to objects vtkGetObjectMacro(SelectedComponentOptionMenu, vtkKWMenuButtonWithLabel); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void SelectedComponentCallback(int); protected: vtkKWScalarComponentSelectionWidget(); ~vtkKWScalarComponentSelectionWidget(); // Description: // Create the widget. virtual void CreateWidget(); int IndependentComponents; int NumberOfComponents; int SelectedComponent; int AllowComponentSelection; char *SelectedComponentChangedCommand; virtual void InvokeSelectedComponentChangedCommand(int comp); // GUI vtkKWMenuButtonWithLabel *SelectedComponentOptionMenu; // Pack virtual void Pack(); private: vtkKWScalarComponentSelectionWidget(const vtkKWScalarComponentSelectionWidget&); // Not implemented void operator=(const vtkKWScalarComponentSelectionWidget&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWCheckButton.cxx0000644000175000017500000004726610751700431021022 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWCheckButton.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWApplication.h" #include "vtkKWCheckButton.h" #include "vtkObjectFactory.h" #include "vtkKWTkUtilities.h" #include "vtkKWIcon.h" #include "vtkKWOptions.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWCheckButton ); vtkCxxRevisionMacro(vtkKWCheckButton, "$Revision: 1.61 $"); //---------------------------------------------------------------------------- vtkKWCheckButton::vtkKWCheckButton() { this->IndicatorVisibility = 1; this->InternalText = NULL; this->VariableName = NULL; this->Command = NULL; } //---------------------------------------------------------------------------- vtkKWCheckButton::~vtkKWCheckButton() { if (this->Command) { delete [] this->Command; this->Command = NULL; } this->SetInternalText(NULL); this->SetVariableName(NULL); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetVariableName(const char* _arg) { if (this->VariableName == NULL && _arg == NULL) { return; } if (this->VariableName && _arg && (!strcmp(this->VariableName, _arg))) { return; } if (this->VariableName) { delete [] this->VariableName; } if (_arg) { this->VariableName = new char[strlen(_arg)+1]; strcpy(this->VariableName,_arg); } else { this->VariableName = NULL; } this->Modified(); if (this->VariableName) { this->SetConfigurationOption("-variable", this->VariableName); } } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetIndicatorVisibility(int ind) { if (ind != this->IndicatorVisibility) { this->IndicatorVisibility = ind; this->Modified(); this->SetConfigurationOptionAsInt( "-indicatoron", (this->IndicatorVisibility ? 1 : 0)); } this->SetInternalText(0); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetText(const char* txt) { this->SetInternalText(txt); this->SetTextOption("-text", txt); } //---------------------------------------------------------------------------- const char* vtkKWCheckButton::GetText() { return this->InternalText; } //---------------------------------------------------------------------------- int vtkKWCheckButton::GetSelectedState() { if (this->IsCreated() && this->VariableName) { #if 0 return atoi( this->Script("expr {${%s}} == {[%s cget -onvalue]}", this->VariableName, this->GetWidgetName())); #else vtksys_stl::string varvalue( Tcl_GetVar(this->GetApplication()->GetMainInterp(), this->VariableName, TCL_GLOBAL_ONLY)); vtksys_stl::string value(this->GetConfigurationOption("-onvalue")); return !strcmp(varvalue.c_str(), value.c_str()); #endif } return 0; } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetSelectedState(int s) { if (this->IsCreated() && this->GetSelectedState() != s) { int was_disabled = !this->GetEnabled(); if (was_disabled) { this->SetEnabled(1); } if (s) { this->Script("%s select", this->GetWidgetName()); } else { this->Script("%s deselect",this->GetWidgetName()); } if (was_disabled) { this->SetEnabled(0); } if (this->GetSelectedState() == s) { this->CommandCallback(); } } } //---------------------------------------------------------------------------- void vtkKWCheckButton::ToggleSelectedState() { this->SetSelectedState(this->GetSelectedState() ? 0 : 1); } //---------------------------------------------------------------------------- void vtkKWCheckButton::CreateWidget() { // Call the superclass to create the widget and set the appropriate flags if (!vtkKWWidget::CreateSpecificTkWidget(this, "checkbutton", "-highlightthickness 0 -bd 2 -padx 2 -pady 2")) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } this->Configure(); } //---------------------------------------------------------------------------- void vtkKWCheckButton::Configure() { char *command = NULL; this->SetObjectMethodCommand(&command, this, "CommandCallback"); this->SetConfigurationOption("-command", command); delete [] command; this->SetConfigurationOptionAsInt( "-indicatoron", (this->IndicatorVisibility ? 1 : 0)); this->SetTextOption("-text", this->InternalText); // Set the variable name if not set already if (!this->VariableName) { vtksys_stl::string vname(this->GetWidgetName()); vname += "Value"; this->SetVariableName(vname.c_str()); } else { this->SetConfigurationOption("-variable", this->VariableName); } } //---------------------------------------------------------------------------- void vtkKWCheckButton::CommandCallback() { int state = this->GetSelectedState(); this->InvokeCommand(state); this->InvokeEvent(vtkKWCheckButton::SelectedStateChangedEvent, &state); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetCommand(vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->Command, object, method); } //---------------------------------------------------------------------------- void vtkKWCheckButton::InvokeCommand(int state) { if (this->GetApplication() && this->Command && *this->Command) { this->Script("%s %d", this->Command, state); } } //---------------------------------------------------------------------------- void vtkKWCheckButton::GetBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWCheckButton::GetBackgroundColor() { return this->GetConfigurationOptionAsColor("-background"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- void vtkKWCheckButton::GetForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWCheckButton::GetForegroundColor() { return this->GetConfigurationOptionAsColor("-foreground"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetHighlightThickness(int width) { this->SetConfigurationOptionAsInt("-highlightthickness", width); } //---------------------------------------------------------------------------- int vtkKWCheckButton::GetHighlightThickness() { return this->GetConfigurationOptionAsInt("-highlightthickness"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::GetActiveBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWCheckButton::GetActiveBackgroundColor() { return this->GetConfigurationOptionAsColor("-activebackground"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetActiveBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWCheckButton::GetActiveForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-activeforeground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWCheckButton::GetActiveForegroundColor() { return this->GetConfigurationOptionAsColor("-activeforeground"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetActiveForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-activeforeground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWCheckButton::GetDisabledForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-disabledforeground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWCheckButton::GetDisabledForegroundColor() { return this->GetConfigurationOptionAsColor("-disabledforeground"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetDisabledForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-disabledforeground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetBorderWidth(int width) { this->SetConfigurationOptionAsInt("-bd", width); } //---------------------------------------------------------------------------- int vtkKWCheckButton::GetBorderWidth() { return this->GetConfigurationOptionAsInt("-bd"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetRelief(int relief) { this->SetConfigurationOption( "-relief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWCheckButton::SetReliefToRaised() { this->SetRelief(vtkKWOptions::ReliefRaised); }; void vtkKWCheckButton::SetReliefToSunken() { this->SetRelief(vtkKWOptions::ReliefSunken); }; void vtkKWCheckButton::SetReliefToFlat() { this->SetRelief(vtkKWOptions::ReliefFlat); }; void vtkKWCheckButton::SetReliefToRidge() { this->SetRelief(vtkKWOptions::ReliefRidge); }; void vtkKWCheckButton::SetReliefToSolid() { this->SetRelief(vtkKWOptions::ReliefSolid); }; void vtkKWCheckButton::SetReliefToGroove() { this->SetRelief(vtkKWOptions::ReliefGroove); }; //---------------------------------------------------------------------------- int vtkKWCheckButton::GetRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-relief")); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetPadX(int arg) { this->SetConfigurationOptionAsInt("-padx", arg); } //---------------------------------------------------------------------------- int vtkKWCheckButton::GetPadX() { return this->GetConfigurationOptionAsInt("-padx"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetPadY(int arg) { this->SetConfigurationOptionAsInt("-pady", arg); } //---------------------------------------------------------------------------- int vtkKWCheckButton::GetPadY() { return this->GetConfigurationOptionAsInt("-pady"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetAnchor(int anchor) { this->SetConfigurationOption( "-anchor", vtkKWOptions::GetAnchorAsTkOptionValue(anchor)); } void vtkKWCheckButton::SetAnchorToNorth() { this->SetAnchor(vtkKWOptions::AnchorNorth); }; void vtkKWCheckButton::SetAnchorToNorthEast() { this->SetAnchor(vtkKWOptions::AnchorNorthEast); }; void vtkKWCheckButton::SetAnchorToEast() { this->SetAnchor(vtkKWOptions::AnchorEast); }; void vtkKWCheckButton::SetAnchorToSouthEast() { this->SetAnchor(vtkKWOptions::AnchorSouthEast); }; void vtkKWCheckButton::SetAnchorToSouth() { this->SetAnchor(vtkKWOptions::AnchorSouth); }; void vtkKWCheckButton::SetAnchorToSouthWest() { this->SetAnchor(vtkKWOptions::AnchorSouthWest); }; void vtkKWCheckButton::SetAnchorToWest() { this->SetAnchor(vtkKWOptions::AnchorWest); }; void vtkKWCheckButton::SetAnchorToNorthWest() { this->SetAnchor(vtkKWOptions::AnchorNorthWest); }; void vtkKWCheckButton::SetAnchorToCenter() { this->SetAnchor(vtkKWOptions::AnchorCenter); }; //---------------------------------------------------------------------------- int vtkKWCheckButton::GetAnchor() { return vtkKWOptions::GetAnchorFromTkOptionValue( this->GetConfigurationOption("-anchor")); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetOffRelief(int relief) { this->SetConfigurationOption( "-offrelief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWCheckButton::SetOffReliefToRaised() { this->SetOffRelief(vtkKWOptions::ReliefRaised); }; void vtkKWCheckButton::SetOffReliefToSunken() { this->SetOffRelief(vtkKWOptions::ReliefSunken); }; void vtkKWCheckButton::SetOffReliefToFlat() { this->SetOffRelief(vtkKWOptions::ReliefFlat); }; void vtkKWCheckButton::SetOffReliefToRidge() { this->SetOffRelief(vtkKWOptions::ReliefRidge); }; void vtkKWCheckButton::SetOffReliefToSolid() { this->SetOffRelief(vtkKWOptions::ReliefSolid); }; void vtkKWCheckButton::SetOffReliefToGroove() { this->SetOffRelief(vtkKWOptions::ReliefGroove); }; //---------------------------------------------------------------------------- int vtkKWCheckButton::GetOffRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-offrelief")); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetOverRelief(int relief) { this->SetConfigurationOption( "-overrelief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWCheckButton::SetOverReliefToRaised() { this->SetOverRelief(vtkKWOptions::ReliefRaised); }; void vtkKWCheckButton::SetOverReliefToSunken() { this->SetOverRelief(vtkKWOptions::ReliefSunken); }; void vtkKWCheckButton::SetOverReliefToFlat() { this->SetOverRelief(vtkKWOptions::ReliefFlat); }; void vtkKWCheckButton::SetOverReliefToRidge() { this->SetOverRelief(vtkKWOptions::ReliefRidge); }; void vtkKWCheckButton::SetOverReliefToSolid() { this->SetOverRelief(vtkKWOptions::ReliefSolid); }; void vtkKWCheckButton::SetOverReliefToGroove() { this->SetOverRelief(vtkKWOptions::ReliefGroove); }; void vtkKWCheckButton::SetOverReliefToNone() { this->SetOverRelief(vtkKWOptions::ReliefUnknown); }; //---------------------------------------------------------------------------- int vtkKWCheckButton::GetOverRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-overrelief")); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetFont(const char *font) { this->SetConfigurationOption("-font", font); } //---------------------------------------------------------------------------- const char* vtkKWCheckButton::GetFont() { return this->GetConfigurationOption("-font"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetImageToPredefinedIcon(int icon_index) { vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImage(icon_index); this->SetImageToIcon(icon); icon->Delete(); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetImageToIcon(vtkKWIcon* icon) { if (icon) { this->SetImageToPixels( icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize()); } else { this->SetConfigurationOption("-image", ""); } } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetImageToPixels( const unsigned char* pixels, int width, int height, int pixel_size, unsigned long buffer_length) { vtkKWTkUtilities::SetImageOptionToPixels( this, pixels, width, height, pixel_size, buffer_length); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetSelectImageToPredefinedIcon(int icon_index) { vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImage(icon_index); this->SetSelectImageToIcon(icon); icon->Delete(); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetSelectImageToIcon(vtkKWIcon* icon) { if (icon) { this->SetSelectImageToPixels( icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize()); } else { this->SetConfigurationOption("-selectimage", ""); } } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetSelectImageToPixels( const unsigned char* pixels, int width, int height, int pixel_size, unsigned long buffer_length) { vtkKWTkUtilities::SetImageOptionToPixels( this, pixels, width, height, pixel_size, buffer_length, "-selectimage"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetCompoundMode(int mode) { this->SetConfigurationOption( "-compound", vtkKWOptions::GetCompoundModeAsTkOptionValue(mode)); } void vtkKWCheckButton::SetCompoundModeToNone() { this->SetCompoundMode(vtkKWOptions::CompoundModeNone); }; void vtkKWCheckButton::SetCompoundModeToLeft() { this->SetCompoundMode(vtkKWOptions::CompoundModeLeft); }; void vtkKWCheckButton::SetCompoundModeToCenter() { this->SetCompoundMode(vtkKWOptions::CompoundModeCenter); }; void vtkKWCheckButton::SetCompoundModeToRight() { this->SetCompoundMode(vtkKWOptions::CompoundModeRight); }; void vtkKWCheckButton::SetCompoundModeToTop() { this->SetCompoundMode(vtkKWOptions::CompoundModeTop); }; void vtkKWCheckButton::SetCompoundModeToBottom() { this->SetCompoundMode(vtkKWOptions::CompoundModeBottom); }; //---------------------------------------------------------------------------- int vtkKWCheckButton::GetCompoundMode() { return vtkKWOptions::GetCompoundModeFromTkOptionValue( this->GetConfigurationOption("-compound")); } //---------------------------------------------------------------------------- void vtkKWCheckButton::GetSelectColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-selectcolor", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWCheckButton::GetSelectColor() { return this->GetConfigurationOptionAsColor("-selectcolor"); } //---------------------------------------------------------------------------- void vtkKWCheckButton::SetSelectColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-selectcolor", r, g, b); } // --------------------------------------------------------------------------- void vtkKWCheckButton::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->SetState(this->GetEnabled()); } //---------------------------------------------------------------------------- void vtkKWCheckButton::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "VariableName: " << (this->VariableName ? this->VariableName : "None" ); } kwwidgets-1.0.0~cvs20100930/vtkKWColorPresetSelector.h0000644000175000017500000001656511015555476022211 0ustar domibeldomibel/*========================================================================= Copyright (c) 1998-2003 Kitware Inc. 469 Clifton Corporate Parkway, Clifton Park, NY, 12065, USA. All rights reserved. No part of this software may be reproduced, distributed, or modified, in any form or by any means, without permission in writing from Kitware Inc. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. =========================================================================*/ // .NAME vtkKWColorPresetSelector - a color preset selector. // .SECTION Description // This class is a widget that can be used to store color presets. // For example, a list of favorite colors, or a list of "recently picked" // colors. // It is used internally by the vtkKWColorPickerWidget class. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWColorPickerWidget vtkKWColorSpectrumWidget vtkKWPresetSelector #ifndef __vtkKWColorPresetSelector_h #define __vtkKWColorPresetSelector_h #include "vtkKWPresetSelector.h" class KWWidgets_EXPORT vtkKWColorPresetSelector : public vtkKWPresetSelector { public: static vtkKWColorPresetSelector* New(); vtkTypeRevisionMacro(vtkKWColorPresetSelector, vtkKWPresetSelector); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the color for a given preset. // A method is available to retrieve the Id of the preset that has // been assigned a specific color. // Return 1 on success, 0 on error (id on success, -1 otherwise) virtual void GetPresetColorAsRGB(int id, double &r, double &g, double &b); virtual void GetPresetColorAsRGB(int id, double rgb[3]); virtual int SetPresetColorAsRGB(int id, double r, double g, double b); virtual int SetPresetColorAsRGB(int id, double rgb[3]); virtual void GetPresetColorAsHSV(int id, double &h, double &s, double &v); virtual void GetPresetColorAsHSV(int id, double hsv[3]); virtual int SetPresetColorAsHSV(int id, double h, double s, double v); virtual int SetPresetColorAsHSV(int id, double hsv[3]); virtual int GetIdOfPresetWithColorAsRGB(double r, double g, double b); virtual int GetIdOfPresetWithColorAsRGB(double rgb[3]); // Description: // Set/Get the preset comment to the hexadecimal RGB representation // Return 1 on success, 0 otherwise virtual int SetPresetCommentAsHexadecimalRGB(int id); virtual int GetPresetCommentAsHexadecimalRGB(int id, int &r, int &g, int &b); virtual int HasPresetCommentAsHexadecimalRGB(int id); // Description: // Add a few default color presets (black, white, primary colors). virtual void AddDefaultColorPresets(); // Description: // Remove all duplicated colors from the list. // Return the number of duplicates removed. virtual int RemoveDuplicatedColors(); // Description: // Set/Get if the color cell (i.e. the cell representing the color // for each preset entry) is drawn as a color button (i.e. a square frame // with a background color set to the preset color, a black outline, and // some margin so that it doesn't touch the row separators) or if the whole // cell background color is used to represent the color. The former option // looks nicer, but is a tad slower to display: while it takes about the // same amount of time to insert a lot of entries (about 1200 entries per // second), displaying them is a little slower when this option is On (about // 285 vs. 400 entries per second). // Note: set this option before inserting any entries; for performance // reasons, switching from one to the other interactively is not supported. virtual void SetDrawColorCellAsColorButton(int); vtkGetMacro(DrawColorCellAsColorButton,int); vtkBooleanMacro(DrawColorCellAsColorButton,int); // Description: // Set/Get the registry key under which presets will be saved and/or // restored automatically. Note that presets are saved automatically only // when performing *user-interactions* (add/remove/update/edit). // For performance reason, adding/removing/changing a preset // programatically will not save the presets to the registry; it is up // to the user to call SavePresetsToRegistry() manually. // IMPORTANT: make sure this variable is set before calling Create(). // This goes as well for composite widgets that embed an instance of this // class. The vtkKWColorPickerWidget class, for example, uses two // color preset selectors: make sure to set their RegistryKey (if needed) // *before* calling the Create() method on the vtkKWColorPickerWidget // instance. vtkSetStringMacro(RegistryKey); vtkGetStringMacro(RegistryKey); // Description: // Save/Restore colors to/from registry, using the RegistryKey ivar as key. // Note that presets are saved automatically when performing // *user-interactions* (see RegistryKey) virtual void SavePresetsToRegistry(); virtual void RestorePresetsFromRegistry(); // Description: // Some constants //BTX static const char *ColorColumnName; //ETX protected: vtkKWColorPresetSelector(); ~vtkKWColorPresetSelector(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Create the columns. // Subclasses should override this method to add their own columns and // display their own preset fields (do not forget to call the superclass // first). virtual void CreateColumns(); // Description: // Update the preset row, i.e. add a row for that preset if it is not // displayed already, hide it if it does not match GroupFilter, and // update the table columns with the corresponding preset fields. // Subclass should override this method to display their own fields. // Return 1 on success, 0 if the row was not (or can not be) updated. // Subclasses should call the parent's UpdatePresetRow, and abort // if the result is not 1. virtual int UpdatePresetRow(int id); // Description: // Convenience methods to get the index of a given column virtual int GetColorColumnIndex(); int DrawColorCellAsColorButton; char *RegistryKey; virtual int InvokePresetAddCommand(); virtual void InvokePresetRemovedCommand(); virtual void InvokePresetUpdateCommand(int id); virtual void InvokePresetHasChangedCommand(int id); static int CompareRGBColors(double rgb1[3], double rgb2[3]); static int CompareRGBColors(double r1, double g1, double b1, double r2, double g2, double b2); private: vtkKWColorPresetSelector(const vtkKWColorPresetSelector&); // Not implemented void operator=(const vtkKWColorPresetSelector&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWVolumePropertyWidget.cxx0000644000175000017500000023317611133157756023001 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWVolumePropertyWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWVolumePropertyWidget.h" #include "vtkColorTransferFunction.h" #include "vtkDataArray.h" #include "vtkDataSet.h" #include "vtkImageData.h" #include "vtkKWCheckButton.h" #include "vtkKWColorTransferFunctionEditor.h" #include "vtkKWEntryWithLabel.h" #include "vtkKWEvent.h" #include "vtkKWFrame.h" #include "vtkKWFrameWithLabel.h" #include "vtkKWHSVColorSelector.h" #include "vtkKWHistogramSet.h" #include "vtkKWIcon.h" #include "vtkKWLabel.h" #include "vtkKWMenu.h" #include "vtkKWMenuButton.h" #include "vtkKWMenuButtonWithLabel.h" #include "vtkKWPiecewiseFunctionEditor.h" #include "vtkKWPopupButtonWithLabel.h" #include "vtkKWScalarComponentSelectionWidget.h" #include "vtkKWScaleWithEntry.h" #include "vtkKWScaleWithEntrySet.h" #include "vtkKWScaleWithEntrySetWithLabel.h" #include "vtkKWVolumeMaterialPropertyWidget.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPiecewiseFunction.h" #include "vtkPointData.h" #include "vtkVolumeProperty.h" #include "vtkKWTkUtilities.h" #include "vtkKWInternationalization.h" #include #include #define VTK_KW_VPW_INTERPOLATION_LINEAR "Linear" #define VTK_KW_VPW_INTERPOLATION_NEAREST "Nearest" #define VTK_KW_VPW_TESTING 0 //---------------------------------------------------------------------------- vtkCxxRevisionMacro(vtkKWVolumePropertyWidget, "$Revision: 1.55 $"); vtkStandardNewMacro(vtkKWVolumePropertyWidget); //---------------------------------------------------------------------------- vtkKWVolumePropertyWidget::vtkKWVolumePropertyWidget() { int i; this->VolumeProperty = NULL; this->DataSet = NULL; this->HistogramSet = NULL; this->SelectedComponent = 0; this->DisableCommands = 0; this->EnableShadingForAllComponents = 0; this->InteractiveApplyMode = 0; this->InteractiveApplyButtonVisibility = 1; this->ScalarOpacityUnitDistanceVisibility = 1; this->HSVColorSelectorVisibility = 1; this->ComponentSelectionVisibility = 1; this->InterpolationTypeVisibility = 1; this->MaterialPropertyVisibility = 1; this->GradientOpacityFunctionVisibility = 1; this->ComponentWeightsVisibility = 1; this->MaterialPropertyPosition = vtkKWVolumePropertyWidget::MaterialPropertyPositionTop; this->WholeRangeComputationMethod = vtkKWVolumePropertyWidget::WholeRangeComputationMethodData; this->UseScalarColorFunctionInScalarOpacityEditor = 0; this->VolumePropertyChangedCommand = NULL; this->VolumePropertyChangingCommand = NULL; // GUI this->EditorFrame = vtkKWFrameWithLabel::New(); this->InnerLeftFrame = vtkKWFrame::New(); this->InterpolationTypeOptionMenu = vtkKWMenuButtonWithLabel::New(); this->EnableShadingCheckButton = vtkKWCheckButton::New(); this->InteractiveApplyCheckButton = vtkKWCheckButton::New(); this->LockOpacityAndColorCheckButton = vtkKWCheckButton::New(); this->ScalarOpacityUnitDistanceScale = vtkKWScaleWithEntry::New(); this->EnableGradientOpacityOptionMenu = vtkKWMenuButton::New(); this->ComponentWeightScaleSet = vtkKWScaleWithEntrySetWithLabel::New(); this->ComponentSelectionWidget = vtkKWScalarComponentSelectionWidget::New(); this->MaterialPropertyWidget = vtkKWVolumeMaterialPropertyWidget::New(); this->ScalarOpacityFunctionEditor = vtkKWPiecewiseFunctionEditor::New(); this->GradientOpacityFunctionEditor = vtkKWPiecewiseFunctionEditor::New(); this->ScalarColorFunctionEditor = vtkKWColorTransferFunctionEditor::New(); this->BottomFrame = vtkKWFrame::New(); for (i = 0; i < VTK_MAX_VRCOMP; i++) { this->LockOpacityAndColor[i] = 0; this->WindowLevelMode[i] = 0; } this->HSVColorSelector = vtkKWHSVColorSelector::New(); } //---------------------------------------------------------------------------- vtkKWVolumePropertyWidget::~vtkKWVolumePropertyWidget() { // Commands if (this->VolumePropertyChangedCommand) { delete [] this->VolumePropertyChangedCommand; this->VolumePropertyChangedCommand = NULL; } if (this->VolumePropertyChangingCommand) { delete [] this->VolumePropertyChangingCommand; this->VolumePropertyChangingCommand = NULL; } // GUI if (this->EditorFrame) { this->EditorFrame->Delete(); this->EditorFrame = NULL; } if (this->InnerLeftFrame) { this->InnerLeftFrame->Delete(); this->InnerLeftFrame = NULL; } if (this->ComponentSelectionWidget) { this->ComponentSelectionWidget->Delete(); this->ComponentSelectionWidget = NULL; } if (this->InterpolationTypeOptionMenu) { this->InterpolationTypeOptionMenu->Delete(); this->InterpolationTypeOptionMenu = NULL; } if (this->EnableShadingCheckButton) { this->EnableShadingCheckButton->Delete(); this->EnableShadingCheckButton = NULL; } if (this->MaterialPropertyWidget) { this->MaterialPropertyWidget->Delete(); this->MaterialPropertyWidget = NULL; } if (this->InteractiveApplyCheckButton) { this->InteractiveApplyCheckButton->Delete(); this->InteractiveApplyCheckButton = NULL; } if (this->ScalarOpacityFunctionEditor) { this->ScalarOpacityFunctionEditor->Delete(); this->ScalarOpacityFunctionEditor = NULL; } if (this->ScalarOpacityUnitDistanceScale) { this->ScalarOpacityUnitDistanceScale->Delete(); this->ScalarOpacityUnitDistanceScale = NULL; } if (this->LockOpacityAndColorCheckButton) { this->LockOpacityAndColorCheckButton->Delete(); this->LockOpacityAndColorCheckButton = NULL; } if (this->ScalarColorFunctionEditor) { this->ScalarColorFunctionEditor->Delete(); this->ScalarColorFunctionEditor = NULL; } if (this->EnableGradientOpacityOptionMenu) { this->EnableGradientOpacityOptionMenu->Delete(); this->EnableGradientOpacityOptionMenu = NULL; } if (this->GradientOpacityFunctionEditor) { this->GradientOpacityFunctionEditor->Delete(); this->GradientOpacityFunctionEditor = NULL; } if (this->ComponentWeightScaleSet) { this->ComponentWeightScaleSet->Delete(); this->ComponentWeightScaleSet = NULL; } if (this->HSVColorSelector) { this->HSVColorSelector->Delete(); this->HSVColorSelector = NULL; } if (this->BottomFrame) { this->BottomFrame->Delete(); this->BottomFrame = NULL; } this->SetHistogramSet(NULL); this->SetVolumeProperty(NULL); this->SetDataSet(NULL); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); vtksys_ios::ostringstream tk_cmd; int label_width = 12; int menu_width = 6; char command[256]; vtkKWMenu *menu; // -------------------------------------------------------------- // Frame this->EditorFrame->SetParent(this); this->EditorFrame->Create(); this->EditorFrame->SetLabelText( ks_("Volume Property Editor|Title|Volume Appearance Settings")); vtkKWFrame *frame = this->EditorFrame->GetFrame(); // -------------------------------------------------------------- // Inner frame this->InnerLeftFrame->SetParent(frame); this->InnerLeftFrame->Create(); // -------------------------------------------------------------- // Component selection this->ComponentSelectionWidget->SetParent(this->InnerLeftFrame); this->ComponentSelectionWidget->Create(); this->ComponentSelectionWidget->SetSelectedComponentChangedCommand( this, "SelectedComponentCallback"); vtkKWMenuButtonWithLabel *menubuttonwl = this->ComponentSelectionWidget->GetSelectedComponentOptionMenu(); menubuttonwl->SetLabelWidth(label_width); menubuttonwl->GetWidget()->SetWidth(menu_width); // -------------------------------------------------------------- // Interpolation type if (!this->InterpolationTypeOptionMenu) { this->InterpolationTypeOptionMenu = vtkKWMenuButtonWithLabel::New(); } this->InterpolationTypeOptionMenu->SetParent(this->InnerLeftFrame); this->InterpolationTypeOptionMenu->Create(); this->InterpolationTypeOptionMenu->ExpandWidgetOff(); this->InterpolationTypeOptionMenu->SetLabelText( ks_("Volume Property Editor|Interpolation:")); this->InterpolationTypeOptionMenu->SetLabelWidth(label_width); this->InterpolationTypeOptionMenu->GetWidget()->SetWidth(menu_width); this->InterpolationTypeOptionMenu->SetBalloonHelpString( k_("Set the interpolation type used for sampling the volume.")); vtkKWMenuButton *menubutton = this->InterpolationTypeOptionMenu->GetWidget(); menu = menubutton->GetMenu(); char callback[128]; sprintf(callback, "InterpolationTypeCallback %d", VTK_LINEAR_INTERPOLATION); menu->AddRadioButton(VTK_KW_VPW_INTERPOLATION_LINEAR, this, callback); sprintf(callback, "InterpolationTypeCallback %d", VTK_NEAREST_INTERPOLATION); menu->AddRadioButton(VTK_KW_VPW_INTERPOLATION_NEAREST, this, callback); // -------------------------------------------------------------- // Enable shading this->EnableShadingCheckButton->SetParent(this->InnerLeftFrame); this->EnableShadingCheckButton->Create(); this->EnableShadingCheckButton->SetText( ks_("Volume Property Editor|Enable Shading")); this->EnableShadingCheckButton->SetBalloonHelpString( k_("Enable shading (for all components).")); this->EnableShadingCheckButton->SetCommand( this, "EnableShadingCallback"); // -------------------------------------------------------------- // Material properties : widget if (!this->MaterialPropertyWidget->GetParent()) { this->MaterialPropertyWidget->SetParent(this); } this->MaterialPropertyWidget->PopupModeOn(); this->MaterialPropertyWidget->Create(); this->MaterialPropertyWidget->GetPopupButton()->SetLabelWidth(label_width); this->MaterialPropertyWidget->GetComponentSelectionWidget() ->AllowComponentSelectionOn(); this->MaterialPropertyWidget->SetPropertyChangedCommand( this, "MaterialPropertyChangedCallback"); this->MaterialPropertyWidget->SetPropertyChangingCommand( this, "MaterialPropertyChangingCallback"); // -------------------------------------------------------------- // Interactive Apply this->InteractiveApplyCheckButton->SetParent(this->InnerLeftFrame); this->InteractiveApplyCheckButton->Create(); this->InteractiveApplyCheckButton->SetText( ks_("Volume Property Editor|Interactive Apply")); this->InteractiveApplyCheckButton->SetCommand( this, "InteractiveApplyCallback"); this->InteractiveApplyCheckButton->SetBalloonHelpString( k_("Toggle whether changes are applied to the volume window and image " "windows as nodes in the transfer functions are modified, or only " "after the mouse button is released.")); // -------------------------------------------------------------- // Scalar opacity editor if (!this->ScalarOpacityFunctionEditor->GetParent()) { this->ScalarOpacityFunctionEditor->SetParent(frame); } this->ScalarOpacityFunctionEditor->SetLabelText( ks_("Volume Property Editor|Scalar Opacity Mapping:")); this->ScalarOpacityFunctionEditor->ComputePointColorFromValueOff(); this->ScalarOpacityFunctionEditor->LockEndPointsParameterOn(); this->ScalarOpacityFunctionEditor->SetLabelPosition( vtkKWParameterValueFunctionEditor::LabelPositionTop); this->ScalarOpacityFunctionEditor->SetRangeLabelPosition( vtkKWParameterValueFunctionEditor::RangeLabelPositionTop); this->ScalarOpacityFunctionEditor->ValueRangeVisibilityOff(); this->ScalarOpacityFunctionEditor->SetValueRangeLabelVisibility( this->ScalarOpacityFunctionEditor->GetValueRangeVisibility()); this->ScalarOpacityFunctionEditor->WindowLevelModeButtonVisibilityOn(); this->ScalarOpacityFunctionEditor->Create(); this->ScalarOpacityFunctionEditor->GetParameterEntry()->SetLabelText( ks_("Volume Property Editor|Scalar|S:")); this->ScalarOpacityFunctionEditor->GetValueEntry()->SetLabelText( ks_("Volume Property Editor|Opacity|O:")); this->ScalarOpacityFunctionEditor->SetFunctionChangedCommand( this, "ScalarOpacityFunctionChangedCallback"); this->ScalarOpacityFunctionEditor->SetFunctionChangingCommand( this, "ScalarOpacityFunctionChangingCallback"); this->ScalarOpacityFunctionEditor->SetDoubleClickOnPointCommand( this, "DoubleClickOnScalarOpacityPointCallback"); this->ScalarOpacityFunctionEditor->SetWindowLevelModeChangedCommand( this, "WindowLevelModeCallback"); // -------------------------------------------------------------- // Scalar Opacity Unit Distance this->ScalarOpacityFunctionEditor->UserFrameVisibilityOn(); if (!this->ScalarOpacityUnitDistanceScale->GetParent()) { this->ScalarOpacityUnitDistanceScale->SetParent( this->ScalarOpacityFunctionEditor->GetUserFrame()); } this->ScalarOpacityUnitDistanceScale->PopupModeOn(); this->ScalarOpacityUnitDistanceScale->Create(); this->ScalarOpacityUnitDistanceScale->SetLabelText( ks_("Volume Property Editor|Unit Distance|Scale:")); this->ScalarOpacityUnitDistanceScale->SetEndCommand( this, "ScalarOpacityUnitDistanceChangedCallback"); this->ScalarOpacityUnitDistanceScale->SetEntryCommand( this, "ScalarOpacityUnitDistanceChangedCallback"); this->ScalarOpacityUnitDistanceScale->SetCommand( this, "ScalarOpacityUnitDistanceChangingCallback"); this->ScalarOpacityUnitDistanceScale->SetBalloonHelpString( k_("Set the unit distance on which the scalar opacity transfer function " "is defined.")); // -------------------------------------------------------------- // Color transfer function editor if (!this->ScalarColorFunctionEditor->GetParent()) { this->ScalarColorFunctionEditor->SetParent(frame); } this->ScalarColorFunctionEditor->SetLabelText( ks_("Volume Property Editor|Scalar Color Mapping:")); this->ScalarColorFunctionEditor->SetCanvasHeight( this->ScalarOpacityFunctionEditor->GetCanvasHeight()); this->ScalarColorFunctionEditor->LockEndPointsParameterOn(); this->ScalarColorFunctionEditor->SetPointMarginToCanvas( this->ScalarOpacityFunctionEditor->GetPointMarginToCanvas()); this->ScalarColorFunctionEditor->SetValueRangeVisibility( this->ScalarOpacityFunctionEditor->GetValueRangeVisibility()); this->ScalarColorFunctionEditor->SetValueRangeLabelVisibility( this->ScalarColorFunctionEditor->GetValueRangeVisibility()); this->ScalarColorFunctionEditor->SetLabelPosition( this->ScalarOpacityFunctionEditor->GetLabelPosition()); this->ScalarColorFunctionEditor->SetRangeLabelPosition( this->ScalarOpacityFunctionEditor->GetRangeLabelPosition()); this->ScalarColorFunctionEditor->Create(); this->ScalarColorFunctionEditor->GetParameterEntry()->SetLabelText( this->ScalarOpacityFunctionEditor->GetParameterEntry()->GetLabel() ->GetText()); this->ScalarColorFunctionEditor->SetFunctionChangedCommand( this, "RGBTransferFunctionChangedCallback"); this->ScalarColorFunctionEditor->SetFunctionChangingCommand( this, "RGBTransferFunctionChangingCallback"); this->ScalarColorFunctionEditor->SetSelectionChangedCommand( this, "RGBTransferFunctionSelectionChangedCallback"); // -------------------------------------------------------------- // Lock opacity and color this->ScalarColorFunctionEditor->UserFrameVisibilityOn(); this->LockOpacityAndColorCheckButton->SetParent( this->ScalarColorFunctionEditor->GetUserFrame()); this->LockOpacityAndColorCheckButton->Create(); this->LockOpacityAndColorCheckButton->SetPadX(0); this->LockOpacityAndColorCheckButton->SetPadY(0); this->LockOpacityAndColorCheckButton->SetHighlightThickness(0); this->LockOpacityAndColorCheckButton->IndicatorVisibilityOff(); this->LockOpacityAndColorCheckButton->SetText( ks_("Volume Property Editor|Lock Opacity And Color|Lock")); this->LockOpacityAndColorCheckButton->SetBalloonHelpString( k_("Lock the opacity and color functions together.")); this->LockOpacityAndColorCheckButton->SetCommand( this, "LockOpacityAndColorCallback"); this->LockOpacityAndColorCheckButton->SetImageToPredefinedIcon( vtkKWIcon::IconNuvola16x16ActionsEncrypted); tk_cmd << "pack " << this->LockOpacityAndColorCheckButton->GetWidgetName() << " -side left -fill both -padx 2" << endl; // -------------------------------------------------------------- // Gradient opacity editor if (!this->GradientOpacityFunctionEditor->GetParent()) { this->GradientOpacityFunctionEditor->SetParent(frame); } this->GradientOpacityFunctionEditor->SetLabelText( ks_("Volume Property Editor|Gradient Opacity Mapping:")); this->GradientOpacityFunctionEditor->ComputePointColorFromValueOn(); this->GradientOpacityFunctionEditor->LockEndPointsParameterOn(); this->GradientOpacityFunctionEditor->SetPointMarginToCanvas( this->ScalarOpacityFunctionEditor->GetPointMarginToCanvas()); this->GradientOpacityFunctionEditor->SetCanvasHeight( this->ScalarColorFunctionEditor->GetCanvasHeight()); this->GradientOpacityFunctionEditor->SetValueRangeVisibility( this->ScalarOpacityFunctionEditor->GetValueRangeVisibility()); this->GradientOpacityFunctionEditor->SetValueRangeLabelVisibility( this->GradientOpacityFunctionEditor->GetValueRangeVisibility()); this->GradientOpacityFunctionEditor->SetLabelPosition( this->ScalarOpacityFunctionEditor->GetLabelPosition()); this->GradientOpacityFunctionEditor->SetRangeLabelPosition( this->ScalarOpacityFunctionEditor->GetRangeLabelPosition()); this->GradientOpacityFunctionEditor->Create(); this->GradientOpacityFunctionEditor->GetParameterEntry()->SetLabelText( this->ScalarOpacityFunctionEditor->GetParameterEntry()->GetLabel() ->GetText()); this->GradientOpacityFunctionEditor->GetValueEntry()->SetLabelText( ks_("Volume Property Editor|Opacity|O:")); this->GradientOpacityFunctionEditor->SetFunctionChangedCommand( this, "GradientOpacityFunctionChangedCallback"); this->GradientOpacityFunctionEditor->SetFunctionChangingCommand( this, "GradientOpacityFunctionChangingCallback"); // -------------------------------------------------------------- // Enable gradient opacity this->GradientOpacityFunctionEditor->UserFrameVisibilityOn(); this->EnableGradientOpacityOptionMenu->SetParent( this->GradientOpacityFunctionEditor->GetUserFrame()); this->EnableGradientOpacityOptionMenu->Create(); this->EnableGradientOpacityOptionMenu->SetPadX(1); this->EnableGradientOpacityOptionMenu->SetPadY(0); this->EnableGradientOpacityOptionMenu->IndicatorVisibilityOff(); this->EnableGradientOpacityOptionMenu->SetBalloonHelpString( k_("Enable modulation of the opacity by the magnitude of the gradient " "according to the specified function.")); menu = this->EnableGradientOpacityOptionMenu->GetMenu(); menu->AddRadioButton( ks_("Volume Property Editor|Enable Gradient|On"), this, "EnableGradientOpacityCallback 1"); menu->AddRadioButton( ks_("Volume Property Editor|Enable Gradient|Off"), this, "EnableGradientOpacityCallback 0"); tk_cmd << "pack " << this->EnableGradientOpacityOptionMenu->GetWidgetName() << " -side left -fill both -padx 0" << endl; // -------------------------------------------------------------- // Component weights this->ComponentWeightScaleSet->SetParent(frame); this->ComponentWeightScaleSet->Create(); this->ComponentWeightScaleSet->SetLabelText( ks_("Volume Property Editor|Component Weight(s):")); this->ComponentWeightScaleSet->SetLabelPositionToTop(); vtkKWScaleWithEntrySet *scaleset = this->ComponentWeightScaleSet->GetWidget(); scaleset->PackHorizontallyOn(); scaleset->SetMaximumNumberOfWidgetsInPackingDirection(2); scaleset->SetWidgetsPadX(2); int i; char label[15]; for (i = 0; i < VTK_MAX_VRCOMP; i++) { scaleset->AddWidget(i); scaleset->HideWidget(i); vtkKWScaleWithEntry *scale = scaleset->GetWidget(i); scale->SetResolution(0.01); scale->SetRange(0.0, 1.0); sprintf(label, "%d:", i + 1); scale->SetLabelText(label); sprintf(command, "ComponentWeightChangedCallback %d", i); scale->SetEndCommand(this, command); scale->SetEntryCommand(this, command); sprintf(command, "ComponentWeightChangingCallback %d", i); scale->SetCommand(this, command); scale->SetEntryWidth(5); } // -------------------------------------------------------------- // HSV Color Selector this->HSVColorSelector->SetParent(frame); this->HSVColorSelector->Create(); this->HSVColorSelector->ModificationOnlyOn(); this->HSVColorSelector->SetHueSatWheelRadius(54); this->HSVColorSelector->SetSelectionChangedCommand( this, "HSVColorSelectionChangedCallback"); this->HSVColorSelector->SetSelectionChangingCommand( this, "HSVColorSelectionChangingCallback"); #if VTK_KW_VPW_TESTING cout << this->GetTclName() << endl; cout << "opacity: " << this->ScalarOpacityFunctionEditor->GetTclName() << endl; cout << "ctf: " << this->ScalarColorFunctionEditor->GetTclName() << endl; cout << "gradient: " << this->GradientOpacityFunctionEditor->GetTclName() << endl; cout << "hsvsel: " << this->HSVColorSelector->GetTclName() << endl; cout << "lock: " << this->LockOpacityAndColorCheckButton->GetTclName() << endl; #endif // -------------------------------------------------------------- // Bottom frame this->BottomFrame->SetParent(frame); this->BottomFrame->Create(); // Sync this->ScalarColorFunctionEditor->SynchronizeSingleSelection( this->ScalarOpacityFunctionEditor); // Pack this->Script(tk_cmd.str().c_str()); this->Pack(); // Update this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::Pack() { if (!this->IsCreated()) { return; } vtksys_ios::ostringstream tk_cmd; // Pack the frame tk_cmd << "pack " << this->EditorFrame->GetWidgetName() << " -side top -fill both -expand y -pady 0 -padx 0 -ipady 0 -ipadx 0" << endl; // Regrid the internal widgets vtkKWFrame *frame = this->EditorFrame->GetFrame(); frame->UnpackChildren(); this->InnerLeftFrame->UnpackChildren(); int row = 0; const char *colspan = " -columnspan 2 "; const char *col0 = " -column 0 "; const char *col1 = " -column 1 "; const char *pad = " -padx 2 -pady 2"; const char *pad_ed = " -padx 2 -pady 3"; vtksys_stl::string in_frame(" -in "); in_frame += frame->GetWidgetName(); /* col0 col1 +------------------------- | SC HSV | IT | | MP | | ES | | IA v | SOF -------> | CTF -------> | GOF -------> | CW -------> | BF -------> */ // Inner Frame tk_cmd << "grid " << this->InnerLeftFrame->GetWidgetName() << " -padx 0 -pady 0 -sticky nw " << col0 << " -row " << row << endl; // HSV Color Selector (HSV) if (this->HSVColorSelectorVisibility) { tk_cmd << "grid " << this->HSVColorSelector->GetWidgetName() << " -sticky nw " << col1 << " -row " << row << pad << endl; } // Select Component (SC) if (this->ComponentSelectionVisibility) { tk_cmd << "pack " << this->ComponentSelectionWidget->GetWidgetName() << " -side top -anchor nw " << pad << endl; } // Interpolation type (IT) if (this->InterpolationTypeVisibility) { tk_cmd << "pack " << this->InterpolationTypeOptionMenu->GetWidgetName() << " -side top -anchor nw " << pad << endl; } // Material Property (MP) if (!this->MaterialPropertyVisibility) { tk_cmd << "pack forget " << this->MaterialPropertyWidget->GetWidgetName() << endl; } else { if (this->MaterialPropertyPosition == vtkKWVolumePropertyWidget::MaterialPropertyPositionTop || this->MaterialPropertyPosition == vtkKWVolumePropertyWidget::MaterialPropertyPositionBottomFrame) { this->MaterialPropertyWidget->GetPopupButton()->LabelVisibilityOn(); tk_cmd << "pack " << this->MaterialPropertyWidget->GetWidgetName() << " -side top -anchor nw " << pad << " -in "; if (this->MaterialPropertyPosition == vtkKWVolumePropertyWidget::MaterialPropertyPositionTop) { tk_cmd << this->InnerLeftFrame->GetWidgetName() << endl; } else { tk_cmd << this->BottomFrame->GetWidgetName() << endl; } } else { this->MaterialPropertyWidget->GetPopupButton()->LabelVisibilityOff(); tk_cmd << "pack " << this->MaterialPropertyWidget->GetWidgetName() << " -side right -fill both -padx 2 -pady 0 -in "; if (this->MaterialPropertyPosition == vtkKWVolumePropertyWidget::MaterialPropertyPositionScalarOpacityUserFrame) { tk_cmd << this->ScalarOpacityFunctionEditor->GetUserFrame()->GetWidgetName(); } else { tk_cmd << this->ScalarColorFunctionEditor->GetUserFrame()->GetWidgetName(); } tk_cmd << endl; } } // Enable Shading (ES) if (this->MaterialPropertyVisibility) { tk_cmd << "pack " << this->EnableShadingCheckButton->GetWidgetName() << " -side top -anchor nw " << pad << endl; } // Interactive Apply (IA) if (this->InteractiveApplyButtonVisibility) { tk_cmd << "pack " << this->InteractiveApplyCheckButton->GetWidgetName() << " -side top -anchor nw " << pad << endl; } row++; // -------------------------------------------------------------- // Scalar Opacity Function (SOF) tk_cmd << "grid " << this->ScalarOpacityFunctionEditor->GetWidgetName() << " -sticky ew -column 0 -row " << row << colspan << pad_ed << in_frame.c_str(); if (!this->ScalarColorFunctionEditor->GetCanvasVisibility()) { tk_cmd << " -pady 0"; } tk_cmd << endl; row++; if (this->ScalarOpacityUnitDistanceVisibility) { tk_cmd << "pack " << this->ScalarOpacityUnitDistanceScale->GetWidgetName() << " -side right -fill both -padx 2 -pady 0" << endl; } else { tk_cmd << "pack forget " << this->ScalarOpacityUnitDistanceScale->GetWidgetName() << endl; } // Color Transfer Function (CTF) tk_cmd << "grid " << this->ScalarColorFunctionEditor->GetWidgetName() << " -sticky ew -column 0 -row " << row << colspan << pad_ed << in_frame.c_str(); if (!this->ScalarColorFunctionEditor->GetCanvasVisibility()) { tk_cmd << " -pady 0"; } tk_cmd << endl; row++; // Gradient Opacity Function (GOF) if (this->GradientOpacityFunctionVisibility) { tk_cmd << "grid " << this->GradientOpacityFunctionEditor->GetWidgetName() << " -sticky ew -column 0 -row " << row << colspan << pad_ed << in_frame.c_str() << endl; row++; } // Component weights (CW) if (this->ComponentWeightsVisibility) { tk_cmd << "grid " << this->ComponentWeightScaleSet->GetWidgetName() << " -sticky ew -column 0 -row " << row << colspan << pad << endl; row++; } tk_cmd << "grid " << this->BottomFrame->GetWidgetName() << " -sticky ew -column 0 -row " << row << colspan << endl; row++; // Make sure it can resize tk_cmd << "grid columnconfigure " << frame->GetWidgetName() << " 0 -weight 1" << endl; this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::Update() { // Update enable state this->UpdateEnableState(); // Update sub-components int has_prop = this->VolumeProperty ? 1 : 0; int nb_components = this->GetNumberOfComponents(); char hist_name[1024]; vtksys_ios::ostringstream tk_cmd; // In the dependent case, everything is in the component 0 if (!this->GetIndependentComponents() || (this->SelectedComponent < 0 || this->SelectedComponent >= nb_components)) { this->SelectedComponent = 0; } int i, has_scalar_range, tfunc_size; double scalar_range[2], tfunc_range[2]; // Component selection menu if (this->ComponentSelectionWidget) { this->ComponentSelectionWidget->SetIndependentComponents( this->GetIndependentComponents()); this->ComponentSelectionWidget->SetNumberOfComponents(nb_components); this->ComponentSelectionWidget->SetSelectedComponent( this->SelectedComponent); } // Interpolation type if (InterpolationTypeOptionMenu) { vtkKWMenuButton *m = this->InterpolationTypeOptionMenu->GetWidget(); if (has_prop) { switch (this->VolumeProperty->GetInterpolationType()) { case VTK_NEAREST_INTERPOLATION: m->SetValue(VTK_KW_VPW_INTERPOLATION_NEAREST); break; case VTK_LINEAR_INTERPOLATION: m->SetValue(VTK_KW_VPW_INTERPOLATION_LINEAR); break; default: m->SetValue("Unknown"); } } else { m->SetValue(""); } } // Lock opacity and color if (this->LockOpacityAndColorCheckButton) { int state = this->LockOpacityAndColor[this->SelectedComponent]; // If dependents or W/L, we can not lock if (this->WindowLevelMode[this->SelectedComponent] || (has_prop && !this->GetIndependentComponents())) { state = 0; this->LockOpacityAndColorCheckButton->SetEnabled(0); } this->LockOpacityAndColorCheckButton->SetSelectedState(state); } // Enable shading for all if (this->EnableShadingCheckButton) { if (has_prop) { this->EnableShadingCheckButton->SetSelectedState( this->VolumeProperty->GetShade(0)); } if (!this->EnableShadingForAllComponents) { this->EnableShadingCheckButton->SetEnabled(0); } if (EnableShadingCheckButton->IsCreated()) { if (this->EnableShadingForAllComponents) { tk_cmd << "pack " << this->EnableShadingCheckButton->GetWidgetName() << " -side top -anchor nw" << endl; } else { tk_cmd << "pack forget " << this->EnableShadingCheckButton->GetWidgetName() << endl; } } } if (this->EnableShadingForAllComponents && has_prop) { int nb_shade_comp = this->GetIndependentComponents() ? nb_components : 1; for (i = 1; i < nb_shade_comp; i++) { this->VolumeProperty->SetShade(i, this->VolumeProperty->GetShade(0)); } } // Interactive Apply if (this->InteractiveApplyCheckButton) { this->InteractiveApplyCheckButton->SetSelectedState( this->InteractiveApplyMode); } // Material Property if (this->MaterialPropertyWidget) { this->MaterialPropertyWidget->SetVolumeProperty( this->VolumeProperty); this->MaterialPropertyWidget->SetNumberOfComponents(nb_components); this->MaterialPropertyWidget->SetSelectedComponent( this->SelectedComponent); this->MaterialPropertyWidget->SetAllowEnableShading( !this->EnableShadingForAllComponents); this->MaterialPropertyWidget->Update(); if (!has_prop) { this->MaterialPropertyWidget->SetEnabled(0); } } // Scalar opacity if (this->ScalarOpacityFunctionEditor) { int scalar_field = this->GetIndependentComponents() ? this->SelectedComponent : (nb_components - 1); if (has_prop) { vtkPiecewiseFunction *ofun = this->VolumeProperty->GetScalarOpacity(this->SelectedComponent); this->ScalarOpacityFunctionEditor->SetPiecewiseFunction(ofun); has_scalar_range = this->GetDataSetAdjustedScalarRange(scalar_field, scalar_range); tfunc_range[0] = ofun->GetRange()[0]; tfunc_range[1] = ofun->GetRange()[1]; tfunc_size = this->ScalarOpacityFunctionEditor->GetFunctionSize(); if (has_scalar_range && (this->WholeRangeComputationMethod == vtkKWVolumePropertyWidget::WholeRangeComputationMethodData || !tfunc_size)) { this->ScalarOpacityFunctionEditor->SetWholeParameterRange( scalar_range); } else if (tfunc_size && (this->WholeRangeComputationMethod == vtkKWVolumePropertyWidget::WholeRangeComputationMethodFunctionPoints || !has_scalar_range)) { this->ScalarOpacityFunctionEditor->SetWholeParameterRange(tfunc_range); } else { this->ScalarOpacityFunctionEditor->SetWholeParameterRange( scalar_range[0] < tfunc_range[0] ? scalar_range[0] : tfunc_range[0], scalar_range[1] > tfunc_range[1] ? scalar_range[1] : tfunc_range[1]); } this->ScalarOpacityFunctionEditor->SetWholeValueRange(0.0, 1.0); this->ScalarOpacityFunctionEditor->SetWindowLevelMode( this->WindowLevelMode[this->SelectedComponent]); } else { this->ScalarOpacityFunctionEditor->SetPiecewiseFunction(NULL); } if (this->HistogramSet) { if (this->HistogramSet->ComputeHistogramName( this->GetDataSetScalarName(), scalar_field, NULL, hist_name)) { this->ScalarOpacityFunctionEditor->SetHistogram( this->HistogramSet->GetHistogramWithName(hist_name)); } } else { this->ScalarOpacityFunctionEditor->SetHistogram(NULL); } this->ScalarOpacityFunctionEditor->Update(); } // Scalar Opacity Unit Distance if (this->ScalarOpacityUnitDistanceScale) { double soud_range[2], soud_res; if (this->GetDataSetScalarOpacityUnitDistanceRangeAndResolution( soud_range, &soud_res)) { this->ScalarOpacityUnitDistanceScale->SetResolution(soud_res); this->ScalarOpacityUnitDistanceScale->SetRange( soud_range[0], soud_range[1]); } if (has_prop) { int old_disable = this->ScalarOpacityUnitDistanceScale->GetDisableCommands(); this->ScalarOpacityUnitDistanceScale->SetDisableCommands(1); this->ScalarOpacityUnitDistanceScale->SetValue( this->VolumeProperty->GetScalarOpacityUnitDistance( this->SelectedComponent)); this->ScalarOpacityUnitDistanceScale->SetDisableCommands(old_disable); } } // Color transfer function int no_rgb = !this->GetIndependentComponents() && nb_components > 2; if (this->ScalarColorFunctionEditor) { int scalar_field = this->GetIndependentComponents() ? this->SelectedComponent : 0; if (!no_rgb && has_prop && this->VolumeProperty->GetColorChannels(this->SelectedComponent) == 3) { vtkColorTransferFunction *cfun = this->VolumeProperty->GetRGBTransferFunction(this->SelectedComponent); this->ScalarColorFunctionEditor->SetColorTransferFunction(cfun); if (this->UseScalarColorFunctionInScalarOpacityEditor) { this->ScalarOpacityFunctionEditor->SetPointColorTransferFunction(cfun); } else { this->ScalarOpacityFunctionEditor->SetPointColorTransferFunction(NULL); } has_scalar_range = this->GetDataSetAdjustedScalarRange(scalar_field, scalar_range); cfun->GetRange(tfunc_range); tfunc_size = this->ScalarColorFunctionEditor->GetFunctionSize(); if (has_scalar_range && (this->WholeRangeComputationMethod == vtkKWVolumePropertyWidget::WholeRangeComputationMethodData || !tfunc_size)) { this->ScalarColorFunctionEditor->SetWholeParameterRange(scalar_range); } else if (tfunc_size && (this->WholeRangeComputationMethod == vtkKWVolumePropertyWidget::WholeRangeComputationMethodFunctionPoints || !has_scalar_range)) { this->ScalarColorFunctionEditor->SetWholeParameterRange(tfunc_range); } else { this->ScalarColorFunctionEditor->SetWholeParameterRange( scalar_range[0] < tfunc_range[0] ? scalar_range[0] : tfunc_range[0], scalar_range[1] > tfunc_range[1] ? scalar_range[1] : tfunc_range[1]); } } else { this->ScalarColorFunctionEditor->SetColorTransferFunction(NULL); } if (!no_rgb && this->HistogramSet) { if (this->HistogramSet->ComputeHistogramName( this->GetDataSetScalarName(), scalar_field, NULL, hist_name)) { this->ScalarColorFunctionEditor->SetHistogram( this->HistogramSet->GetHistogramWithName(hist_name)); } } else { this->ScalarColorFunctionEditor->SetHistogram(NULL); } this->ScalarColorFunctionEditor->Update(); // Disable the RGB tfunc editor if the color of the volume is set to // a gray level tfunc (not supported at the moment) int rgb_out = no_rgb || (has_prop && this->VolumeProperty->GetColorChannels(this->SelectedComponent) != 3); if (rgb_out) { this->ScalarColorFunctionEditor->SetEnabled(0); } // Try to avoid the shuffling and reshuffling of UI. if (this->ScalarColorFunctionEditor->IsCreated()) { // tk_cmd << "grid " << (rgb_out ? "remove" : "") << " " // << this->ScalarColorFunctionEditor->GetWidgetName() << endl; } } // Synchronize both if (this->ScalarOpacityFunctionEditor && this->ScalarColorFunctionEditor) { int have_funcs = (this->ScalarOpacityFunctionEditor->HasFunction() && this->ScalarColorFunctionEditor->HasFunction()); // Sync of the parameter range and the points will only happen if: // - the components are independent (since each scalar field has its own // pair color tfunc and opacity tfunc, therefore they can be displayed // on top of each other and use the same histogram) // - the components are dependent, but there are only two of them *and* // the user specifically requested that the color function is used // in the scalar opacity editor. When components are dependent, two // possibilities are considered: // * 4 (RGBA) components, in which case the color can not be edited, // so we don't need to sync both editors, only the opacity tfunc // editor will ever be displayed. // * 2 components, in which case the first component is passed through // the first color tfunc, and the second component is passed through // the first opacity tfunc. Now the be reasonably accurate, both // editors should not be merged because both scalar fields are // different (which histogram should be displayed?), and both // scalar ranges might be different as well. *But* in many cases, // the histogram of the second (opacity) scalar field is the most // interesting one, and both scalar range are, in fact, the same. // Under those assumptions both editors will indeed be sync'ed, but // only if the user gave us a hint by setting // UseScalarColorFunctionInScalarOpacityEditor to On. // UPDATE: not for now..., let's stick to the really correct way // int can_sync = this->GetIndependentComponents() || // (nb_components <= 2 && this->UseScalarColorFunctionInScalarOpacityEditor); int can_sync = this->GetIndependentComponents(); // Synchronize the parameter range if RGB and opacity are the same // scalar field if (can_sync && have_funcs) { this->ScalarColorFunctionEditor->SynchronizeVisibleParameterRange( this->ScalarOpacityFunctionEditor); } else { this->ScalarColorFunctionEditor->DoNotSynchronizeVisibleParameterRange( this->ScalarOpacityFunctionEditor); } // (un)Synchronize both opacity and color functions points if (can_sync && this->LockOpacityAndColor[this->SelectedComponent] && have_funcs) { this->ScalarColorFunctionEditor->SynchronizePoints( this->ScalarOpacityFunctionEditor); this->ScalarColorFunctionEditor->DoNotSynchronizeSingleSelection( this->ScalarOpacityFunctionEditor); this->ScalarColorFunctionEditor->SynchronizeSameSelection( this->ScalarOpacityFunctionEditor); } else { this->ScalarColorFunctionEditor->DoNotSynchronizePoints( this->ScalarOpacityFunctionEditor); this->ScalarColorFunctionEditor->DoNotSynchronizeSameSelection( this->ScalarOpacityFunctionEditor); if (have_funcs) { this->ScalarColorFunctionEditor->SynchronizeSingleSelection( this->ScalarOpacityFunctionEditor); } else { this->ScalarColorFunctionEditor->DoNotSynchronizeSingleSelection( this->ScalarOpacityFunctionEditor); } } } // Enable Gradient opacity if (this->EnableGradientOpacityOptionMenu && has_prop) { this->EnableGradientOpacityOptionMenu->SetValue( this->VolumeProperty->GetDisableGradientOpacity( this->SelectedComponent) ? ks_("Volume Property Editor|Enable Gradient|Off") : ks_("Volume Property Editor|Enable Gradient|On")); } // Gradient opacity if (this->GradientOpacityFunctionEditor) { int scalar_field = this->GetIndependentComponents() ? this->SelectedComponent : (nb_components - 1); if (has_prop) { vtkPiecewiseFunction *gfun = this->VolumeProperty->GetStoredGradientOpacity(this->SelectedComponent); this->GradientOpacityFunctionEditor->SetPiecewiseFunction(gfun); has_scalar_range = this->GetDataSetAdjustedScalarRange(scalar_field, scalar_range); if (has_scalar_range) { // WARNING: hard-coded value here according to the raycast mapper // behaviour (1/4 of the range) scalar_range[1] = 0.25 * (scalar_range[1] - scalar_range[0]); scalar_range[0] = 0.0; } tfunc_range[0] = gfun->GetRange()[0]; tfunc_range[1] = gfun->GetRange()[1]; tfunc_size = this->GradientOpacityFunctionEditor->GetFunctionSize(); if (has_scalar_range && (this->WholeRangeComputationMethod == vtkKWVolumePropertyWidget::WholeRangeComputationMethodData || !tfunc_size)) { this->GradientOpacityFunctionEditor->SetWholeParameterRange( scalar_range); } else if (tfunc_size && (this->WholeRangeComputationMethod == vtkKWVolumePropertyWidget::WholeRangeComputationMethodFunctionPoints || !has_scalar_range)) { this->GradientOpacityFunctionEditor->SetWholeParameterRange( tfunc_range); } else { this->GradientOpacityFunctionEditor->SetWholeParameterRange( scalar_range[0] < tfunc_range[0] ? scalar_range[0] : tfunc_range[0], scalar_range[1] > tfunc_range[1] ? scalar_range[1] : tfunc_range[1]); } this->GradientOpacityFunctionEditor->SetWholeValueRange(0.0, 1.0); } else { this->GradientOpacityFunctionEditor->SetPiecewiseFunction(NULL); } if (this->HistogramSet) { if (this->HistogramSet->ComputeHistogramName( this->GetDataSetScalarName(), this->GetIndependentComponents() ? this->SelectedComponent : 0, "gradient", hist_name)) { this->GradientOpacityFunctionEditor->SetHistogram( this->HistogramSet->GetHistogramWithName(hist_name)); } } else { this->GradientOpacityFunctionEditor->SetHistogram(NULL); } this->GradientOpacityFunctionEditor->Update(); } // Component weights (CW) if (this->ComponentWeightScaleSet) { vtkKWScaleWithEntrySet *scaleset = this->ComponentWeightScaleSet->GetWidget(); if (has_prop) { for (i = 0; i < VTK_MAX_VRCOMP; i++) { if (scaleset->GetWidget(i)) { int old_disable = scaleset->GetWidget(i)->GetDisableCommands(); scaleset->GetWidget(i)->SetDisableCommands(1); scaleset->GetWidget(i)->SetValue( this->VolumeProperty->GetComponentWeight(i)); scaleset->GetWidget(i)->SetDisableCommands(old_disable); } } } if (this->ComponentWeightScaleSet->IsCreated()) { if (scaleset->GetNumberOfVisibleWidgets() != nb_components) { for (i = 0; i < VTK_MAX_VRCOMP; i++) { scaleset->SetWidgetVisibility(i, (i < nb_components ? 1 : 0)); } } int scales_out = !this->GetIndependentComponents(); if (scales_out) { this->ComponentWeightScaleSet->SetEnabled(0); } if (this->ComponentWeightScaleSet->IsCreated()) { tk_cmd << "grid " << (scales_out ? "remove" : "") << " " << this->ComponentWeightScaleSet->GetWidgetName() << endl; } } } // HSV Color Selector if (this->HSVColorSelector) { if (no_rgb) { this->HSVColorSelector->SetEnabled(0); } else { this->UpdateHSVColorSelectorFromScalarColorFunctionEditor(); } this->HSVColorSelector->Update(); } // Execute (if any) if (tk_cmd.str() != "") { this->Script(tk_cmd.str().c_str()); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->EditorFrame); this->PropagateEnableState(this->InnerLeftFrame); this->PropagateEnableState(this->ComponentSelectionWidget); this->PropagateEnableState(this->InterpolationTypeOptionMenu); this->PropagateEnableState(this->InteractiveApplyCheckButton); this->PropagateEnableState(this->ScalarOpacityFunctionEditor); this->PropagateEnableState(this->ScalarOpacityUnitDistanceScale); this->PropagateEnableState(this->EnableShadingCheckButton); this->PropagateEnableState(this->MaterialPropertyWidget); this->PropagateEnableState(this->LockOpacityAndColorCheckButton); this->PropagateEnableState(this->ScalarColorFunctionEditor); this->PropagateEnableState(this->EnableGradientOpacityOptionMenu); this->PropagateEnableState(this->GradientOpacityFunctionEditor); this->PropagateEnableState(this->ComponentWeightScaleSet); this->PropagateEnableState(this->HSVColorSelector); this->PropagateEnableState(this->BottomFrame); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetVolumeProperty( vtkVolumeProperty *arg) { if (this->VolumeProperty == arg) { return; } if (this->VolumeProperty) { this->VolumeProperty->UnRegister(this); } this->VolumeProperty = arg; if (this->VolumeProperty) { this->VolumeProperty->Register(this); } this->Modified(); this->Update(); } //---------------------------------------------------------------------------- int vtkKWVolumePropertyWidget::GetIndependentComponents() { return (this->VolumeProperty && this->VolumeProperty->GetIndependentComponents()); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetDataSet( vtkDataSet *arg) { if (this->DataSet == arg) { return; } if (this->DataSet) { this->DataSet->UnRegister(this); } this->DataSet = arg; if (this->DataSet) { this->DataSet->Register(this); } this->Modified(); this->Update(); } // --------------------------------------------------------------------------- int vtkKWVolumePropertyWidget::GetNumberOfComponents() { if (this->DataSet) { vtkDataArray *scalars = this->DataSet->GetPointData()->GetScalars(); if (scalars) { return scalars->GetNumberOfComponents(); } } return VTK_MAX_VRCOMP; } // --------------------------------------------------------------------------- int vtkKWVolumePropertyWidget::GetDataSetScalarRange( int comp, double range[2]) { if (this->DataSet) { vtkDataArray *scalars = this->DataSet->GetPointData()->GetScalars(); if (scalars) { scalars->GetRange(range, comp); return 1; } } return 0; } // --------------------------------------------------------------------------- int vtkKWVolumePropertyWidget::GetDataSetAdjustedScalarRange( int comp, double range[2]) { if (this->DataSet) { vtkDataArray *scalars = this->DataSet->GetPointData()->GetScalars(); if (scalars) { return vtkMath::GetAdjustedScalarRange(scalars, comp, range); } } return 0; } // --------------------------------------------------------------------------- const char* vtkKWVolumePropertyWidget::GetDataSetScalarName() { if (this->DataSet) { vtkDataArray *scalars = this->DataSet->GetPointData()->GetScalars(); if (scalars) { return scalars->GetName(); } } return NULL; } // --------------------------------------------------------------------------- int vtkKWVolumePropertyWidget::GetDataSetScalarOpacityUnitDistanceRangeAndResolution( double range[2], double *resolution) { vtkImageData *img = vtkImageData::SafeDownCast(this->DataSet); if (img) { double *spacing = img->GetSpacing(); double avg_spacing = (spacing[0] + spacing[1] + spacing[2]) / 3.0; double small_spacing = avg_spacing / 10.0; *resolution = small_spacing; range[0] = small_spacing; range[1] = avg_spacing * 10; return 1; } return 0; } // --------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetHistogramSet(vtkKWHistogramSet *arg) { if (this->HistogramSet == arg) { return; } if (this->HistogramSet) { this->HistogramSet->UnRegister(this); } this->HistogramSet = arg; if (this->HistogramSet) { this->HistogramSet->Register(this); } this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetEnableShadingForAllComponents(int arg) { if (this->EnableShadingForAllComponents == arg) { return; } this->EnableShadingForAllComponents = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetComponentSelectionVisibility(int arg) { if (this->ComponentSelectionVisibility == arg) { return; } this->ComponentSelectionVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetHSVColorSelectorVisibility(int arg) { if (this->HSVColorSelectorVisibility == arg) { return; } this->HSVColorSelectorVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetInteractiveApplyButtonVisibility(int arg) { if (this->InteractiveApplyButtonVisibility == arg) { return; } this->InteractiveApplyButtonVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetScalarOpacityUnitDistanceVisibility(int arg) { if (this->ScalarOpacityUnitDistanceVisibility == arg) { return; } this->ScalarOpacityUnitDistanceVisibility = arg; if (this->ScalarOpacityUnitDistanceVisibility) { this->ScalarOpacityFunctionEditor->UserFrameVisibilityOn(); } this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetInterpolationTypeVisibility(int arg) { if (this->InterpolationTypeVisibility == arg) { return; } this->InterpolationTypeVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetMaterialPropertyVisibility(int arg) { if (this->MaterialPropertyVisibility == arg) { return; } this->MaterialPropertyVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetMaterialPropertyPosition(int arg) { if (arg < vtkKWVolumePropertyWidget::MaterialPropertyPositionTop) { arg = vtkKWVolumePropertyWidget::MaterialPropertyPositionTop; } else if (arg > vtkKWVolumePropertyWidget::MaterialPropertyPositionScalarColorUserFrame) { arg = vtkKWVolumePropertyWidget::MaterialPropertyPositionScalarColorUserFrame; } if (this->MaterialPropertyPosition == arg) { return; } this->MaterialPropertyPosition = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetMaterialPropertyPositionToTop() { this->SetMaterialPropertyPosition( vtkKWVolumePropertyWidget::MaterialPropertyPositionTop); }; //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetMaterialPropertyPositionToBottomFrame() { this->SetMaterialPropertyPosition( vtkKWVolumePropertyWidget::MaterialPropertyPositionBottomFrame); }; //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetMaterialPropertyPositionToScalarOpacityUserFrame() { this->SetMaterialPropertyPosition( vtkKWVolumePropertyWidget::MaterialPropertyPositionScalarOpacityUserFrame); }; //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetMaterialPropertyPositionToScalarColorUserFrame() { this->SetMaterialPropertyPosition( vtkKWVolumePropertyWidget::MaterialPropertyPositionScalarColorUserFrame); }; //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetWholeRangeComputationMethod(int arg) { if (arg < vtkKWVolumePropertyWidget::WholeRangeComputationMethodData) { arg = vtkKWVolumePropertyWidget::WholeRangeComputationMethodData; } else if (arg > vtkKWVolumePropertyWidget::WholeRangeComputationMethodDataAndFunctionPoints) { arg = vtkKWVolumePropertyWidget::WholeRangeComputationMethodDataAndFunctionPoints; } if (this->WholeRangeComputationMethod == arg) { return; } this->WholeRangeComputationMethod = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetWholeRangeComputationMethodToData() { this->SetWholeRangeComputationMethod( vtkKWVolumePropertyWidget::WholeRangeComputationMethodData); }; //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetWholeRangeComputationMethodToFunctionPoints() { this->SetWholeRangeComputationMethod( vtkKWVolumePropertyWidget::WholeRangeComputationMethodFunctionPoints); }; //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetWholeRangeComputationMethodToDataAndFunctionPoints() { this->SetWholeRangeComputationMethod( vtkKWVolumePropertyWidget::WholeRangeComputationMethodDataAndFunctionPoints); }; //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetGradientOpacityFunctionVisibility(int arg) { if (this->GradientOpacityFunctionVisibility == arg) { return; } this->GradientOpacityFunctionVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetComponentWeightsVisibility(int arg) { if (this->ComponentWeightsVisibility == arg) { return; } this->ComponentWeightsVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetSelectedComponent(int arg) { if (this->SelectedComponent == arg || arg < 0 || arg >= this->GetNumberOfComponents()) { return; } this->SelectedComponent = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetWindowLevel(double window, double level) { if (this->ScalarOpacityFunctionEditor) { this->ScalarOpacityFunctionEditor->SetWindowLevel(window, level); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetInteractiveWindowLevel( double window, double level) { if (this->ScalarOpacityFunctionEditor) { this->ScalarOpacityFunctionEditor->SetInteractiveWindowLevel( window, level); } } //---------------------------------------------------------------------------- int vtkKWVolumePropertyWidget::IsInWindowLevelMode() { int res = 0; if (this->ScalarOpacityFunctionEditor && this->ScalarOpacityFunctionEditor->GetWindowLevelMode()) { res = 1; } return res; } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetUseScalarColorFunctionInScalarOpacityEditor(int arg) { if (this->UseScalarColorFunctionInScalarOpacityEditor == arg) { return; } this->UseScalarColorFunctionInScalarOpacityEditor = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::MergeScalarOpacityAndColorEditors() { this->UseScalarColorFunctionInScalarOpacityEditor = 1; if (this->ScalarOpacityFunctionEditor) { this->ScalarOpacityFunctionEditor->SetLabelText( "Scalar Opacity And Color Mapping:"); this->ScalarOpacityFunctionEditor->WindowLevelModeButtonVisibilityOff(); this->ScalarOpacityFunctionEditor->ParameterRangeVisibilityOff(); this->ScalarOpacityFunctionEditor->ComputePointColorFromValueOn(); } if (this->ScalarColorFunctionEditor) { this->ScalarColorFunctionEditor->LabelVisibilityOff(); this->ScalarColorFunctionEditor->ParameterRangeLabelVisibilityOff(); this->ScalarColorFunctionEditor->PointEntriesVisibilityOff(); this->ScalarColorFunctionEditor->CanvasVisibilityOff(); this->ScalarColorFunctionEditor->HistogramLogModeOptionMenuVisibilityOff(); this->ScalarColorFunctionEditor->ColorSpaceOptionMenuVisibilityOff(); this->ScalarColorFunctionEditor->UserFrameVisibilityOff(); if (this->ScalarOpacityFunctionEditor) { this->ScalarColorFunctionEditor->SetLockEndPointsParameter( this->ScalarOpacityFunctionEditor->GetLockEndPointsParameter()); } } for (int i = 0; i < VTK_MAX_VRCOMP; i++) { this->LockOpacityAndColor[i] = 1; } this->Pack(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::InvokeObjectMethodCommand(const char *command) { if (!this->DisableCommands) { this->Superclass::InvokeObjectMethodCommand(command); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetVolumePropertyChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->VolumePropertyChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::InvokeVolumePropertyChangedCommand() { this->InvokeObjectMethodCommand(this->VolumePropertyChangedCommand); this->InvokeEvent(vtkKWEvent::VolumePropertyChangedEvent, NULL); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SetVolumePropertyChangingCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->VolumePropertyChangingCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::InvokeVolumePropertyChangingCommand() { this->InvokeObjectMethodCommand(this->VolumePropertyChangingCommand); this->InvokeEvent(vtkKWEvent::VolumePropertyChangingEvent, NULL); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::SelectedComponentCallback(int n) { this->SelectedComponent = n; this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::InterpolationTypeCallback(int type) { if (this->VolumeProperty && this->VolumeProperty->GetInterpolationType()!= type) { this->VolumeProperty->SetInterpolationType(type); this->InvokeVolumePropertyChangedCommand(); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::EnableShadingCallback(int state) { if (!this->VolumeProperty || !this->EnableShadingForAllComponents) { return; } unsigned long mtime = this->VolumeProperty->GetMTime(); // Set the first component this->VolumeProperty->SetShade(0, state ? 1 : 0); // Update the others int nb_shade_comp = this->GetIndependentComponents() ? this->GetNumberOfComponents() : 1; for (int i = 1; i < nb_shade_comp; i++) { this->VolumeProperty->SetShade(i, this->VolumeProperty->GetShade(0)); } // Was something modified ? if (this->VolumeProperty->GetMTime() > mtime) { this->InvokeVolumePropertyChangedCommand(); } this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::LockOpacityAndColorCallback(int state) { this->LockOpacityAndColor[this->SelectedComponent] = state; this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::EnableGradientOpacityCallback(int val) { if (this->EnableGradientOpacityOptionMenu && this->VolumeProperty) { this->VolumeProperty->SetDisableGradientOpacity( this->SelectedComponent, val ? 0 : 1); this->InvokeVolumePropertyChangedCommand(); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::MaterialPropertyChangedCallback() { this->InvokeVolumePropertyChangedCommand(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::MaterialPropertyChangingCallback() { if (this->InteractiveApplyMode) { this->InvokeVolumePropertyChangingCommand(); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::InteractiveApplyCallback(int state) { this->SetInteractiveApplyMode(state ? 1 : 0); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::ScalarOpacityFunctionChangedCallback() { if (this->ScalarOpacityFunctionEditor && this->ScalarOpacityFunctionEditor->GetWindowLevelMode()) { double args[2]; args[0] = this->ScalarOpacityFunctionEditor->GetWindow(); args[1] = this->ScalarOpacityFunctionEditor->GetLevel(); this->InvokeEvent(vtkKWEvent::WindowLevelChangedEvent, args); } this->InvokeVolumePropertyChangedCommand(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::ScalarOpacityFunctionChangingCallback() { if (this->ScalarOpacityFunctionEditor && this->ScalarOpacityFunctionEditor->GetWindowLevelMode()) { double args[2]; args[0] = this->ScalarOpacityFunctionEditor->GetWindow(); args[1] = this->ScalarOpacityFunctionEditor->GetLevel(); this->InvokeEvent(vtkKWEvent::WindowLevelChangingEvent, args); } if (this->InteractiveApplyMode) { this->InvokeVolumePropertyChangingCommand(); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::DoubleClickOnScalarOpacityPointCallback(int id) { // If we are using the color tfunc in the scalar opacity function editor, // try to modify the color if (!this->UseScalarColorFunctionInScalarOpacityEditor || !this->ScalarOpacityFunctionEditor || !this->ScalarColorFunctionEditor || (this->ScalarOpacityFunctionEditor->GetPointColorTransferFunction() != this->ScalarColorFunctionEditor->GetColorTransferFunction())) { return; } // Query the parameter of the point in the scalar opacity editor, and // find the corresponding point in the color transfer function editor double soe_parameter; int sce_id; if (!this->ScalarOpacityFunctionEditor->GetFunctionPointParameter( id, &soe_parameter) || !this->ScalarColorFunctionEditor->GetFunctionPointId( soe_parameter, &sce_id)) { return; } // Change the point color double rgb[3]; if (!this->ScalarColorFunctionEditor->FunctionPointValueIsLocked(sce_id) && this->ScalarColorFunctionEditor->GetPointColorAsRGB(sce_id, rgb) && vtkKWTkUtilities::QueryUserForColor( this->GetApplication(), this, NULL, rgb[0], rgb[1], rgb[2], &rgb[0], &rgb[1], &rgb[2])) { unsigned long mtime = this->ScalarColorFunctionEditor->GetFunctionMTime(); this->ScalarColorFunctionEditor->SetPointColorAsRGB(sce_id, rgb); if (this->ScalarColorFunctionEditor->GetFunctionMTime() > mtime) { this->RGBTransferFunctionChangedCallback(); } } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::ScalarOpacityUnitDistanceChangedCallback( double value) { if (!this->VolumeProperty) { return; } this->VolumeProperty->SetScalarOpacityUnitDistance( this->SelectedComponent, value); this->InvokeVolumePropertyChangedCommand(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::ScalarOpacityUnitDistanceChangingCallback( double value) { if (!this->VolumeProperty) { return; } if (this->InteractiveApplyMode) { this->VolumeProperty->SetScalarOpacityUnitDistance( this->SelectedComponent, value); this->InvokeVolumePropertyChangingCommand(); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::WindowLevelModeCallback(int mode) { this->WindowLevelMode[this->SelectedComponent] = mode; this->Update(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::RGBTransferFunctionChangedCallback() { this->UpdateHSVColorSelectorFromScalarColorFunctionEditor(); if (this->UseScalarColorFunctionInScalarOpacityEditor && this->ScalarOpacityFunctionEditor) { this->ScalarOpacityFunctionEditor->Update(); } this->InvokeVolumePropertyChangedCommand(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::RGBTransferFunctionChangingCallback() { this->UpdateHSVColorSelectorFromScalarColorFunctionEditor(); if (this->UseScalarColorFunctionInScalarOpacityEditor && this->ScalarOpacityFunctionEditor) { this->ScalarOpacityFunctionEditor->Update(); } if (this->InteractiveApplyMode) { this->InvokeVolumePropertyChangingCommand(); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::RGBTransferFunctionSelectionChangedCallback() { this->UpdateHSVColorSelectorFromScalarColorFunctionEditor(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::UpdateHSVColorSelectorFromScalarColorFunctionEditor() { if (!this->ScalarColorFunctionEditor || !this->HSVColorSelector) { return; } /* Here is the deal: - select a point in the scalar color mapping function, - using the HSV wheel/color selector, select a color, like yellow, and a value around 50% , - now drop the value to 0% (black), - the HS cursor will jump automatically to the center, where H = S = 0. Why ? Even if the color is selected in the HSV color selector, at the end of the day the transfer function stores that color in RGB internally using vtkMath::HSVToRGB. In vtkMath::HSVToRGB, all R, G, B components are multiplied by V. Thus, if V = 0 then RGB = (0, 0, 0), i.e. black, whatever the values of HS. Since the HSV color selector is automatically updated to match the color of the selected point in the tfunc, it converts RGB (0, 0, 0) back to HSV, and loses the HS information (thus jumping back to the center). Among the possible hacks to volve this issue, we could have checked if the value was 0.0, and set it to something like 0.0001, which would still be very dark and would keep the HS close enough. I'm not confident with that hack, and I have the feeling that even a close-enough-black on screen could be not-that-close when printing (for example). Instead, I did the following, under the assumption that if the user sets the V to 0, he really wants a "black", whatever the HS: I look at the HSV of the selected tfunc point, and the HSV selected in the HSV color selector. If both have the same V = 0, and lead to the same RGB, I do not update the HSV color selector with the current selected point color. This allows the users to play with V while keeping the HS in the color selector, but the correct value is stored in the tfunc. */ if (this->ScalarColorFunctionEditor->HasSelection()) { double tfunc_hsv[3]; if (this->ScalarColorFunctionEditor->GetPointColorAsHSV( this->ScalarColorFunctionEditor->GetSelectedPoint(), tfunc_hsv)) { int ok = 1; if (this->HSVColorSelector->HasSelection()) { double *sel_hsv = this->HSVColorSelector->GetSelectedColor(); if (sel_hsv[2] == 0.0 && tfunc_hsv[2] == 0.0) { double tfunc_rgb[3], sel_rgb[3]; vtkMath::HSVToRGB(tfunc_hsv, tfunc_rgb); vtkMath::HSVToRGB(sel_hsv, sel_rgb); if (tfunc_rgb[0] == sel_rgb[0] && tfunc_rgb[1] == sel_rgb[1] && tfunc_rgb[2] == sel_rgb[2]) { ok = 0; } } } if (ok) { this->HSVColorSelector->SetSelectedColor(tfunc_hsv); } } } else { this->HSVColorSelector->ClearSelection(); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::GradientOpacityFunctionChangedCallback() { this->InvokeVolumePropertyChangedCommand(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::GradientOpacityFunctionChangingCallback() { if (this->InteractiveApplyMode) { this->InvokeVolumePropertyChangingCommand(); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::HSVColorSelectionChangedCallback( double h, double s, double v) { if (!this->ScalarColorFunctionEditor || !this->ScalarColorFunctionEditor->HasFunction() || !this->ScalarColorFunctionEditor->HasSelection()) { return; } this->ScalarColorFunctionEditor->SetPointColorAsHSV( this->ScalarColorFunctionEditor->GetSelectedPoint(), h, s, v); if (this->UseScalarColorFunctionInScalarOpacityEditor && this->ScalarOpacityFunctionEditor) { this->ScalarOpacityFunctionEditor->Update(); } this->InvokeVolumePropertyChangedCommand(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::HSVColorSelectionChangingCallback( double h, double s, double v) { if (!this->ScalarColorFunctionEditor || !this->ScalarColorFunctionEditor->HasFunction() || !this->ScalarColorFunctionEditor->HasSelection()) { return; } unsigned long mtime = this->ScalarColorFunctionEditor->GetColorTransferFunction()->GetMTime(); this->ScalarColorFunctionEditor->SetPointColorAsHSV( this->ScalarColorFunctionEditor->GetSelectedPoint(), h, s, v); if (this->ScalarColorFunctionEditor->GetColorTransferFunction()->GetMTime() > mtime) { if (this->UseScalarColorFunctionInScalarOpacityEditor && this->ScalarOpacityFunctionEditor) { this->ScalarOpacityFunctionEditor->Update(); } if (this->InteractiveApplyMode) { this->InvokeVolumePropertyChangingCommand(); } } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::ComponentWeightChangedCallback( int index, double value) { if (!this->VolumeProperty) { return; } this->VolumeProperty->SetComponentWeight(index, value); double args[2]; args[0] = index; args[1] = value; this->InvokeEvent(vtkKWEvent::ScalarComponentWeightChangedEvent, args); this->InvokeVolumePropertyChangedCommand(); } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::ComponentWeightChangingCallback( int index, double value) { this->VolumeProperty->SetComponentWeight(index, value); double args[2]; args[0] = index; args[1] = value; this->InvokeEvent(vtkKWEvent::ScalarComponentWeightChangingEvent, args); if (this->InteractiveApplyMode) { this->InvokeVolumePropertyChangingCommand(); } } //---------------------------------------------------------------------------- void vtkKWVolumePropertyWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "SelectedComponent: " << this->SelectedComponent << endl; os << indent << "DisableCommands: " << (this->DisableCommands ? "On" : "Off") << endl; os << indent << "EnableShadingForAllComponents: " << (this->EnableShadingForAllComponents ? "On" : "Off") << endl; os << indent << "ComponentSelectionVisibility: " << (this->ComponentSelectionVisibility ? "On" : "Off") << endl; os << indent << "InteractiveApplyMode: " << (this->InteractiveApplyMode ? "On" : "Off") << endl; os << indent << "InteractiveApplyButtonVisibility: " << (this->InteractiveApplyButtonVisibility ? "On" : "Off") << endl; os << indent << "ScalarOpacityUnitDistanceVisibility: " << (this->ScalarOpacityUnitDistanceVisibility ? "On" : "Off") << endl; os << indent << "HSVColorSelectorVisibility: " << (this->HSVColorSelectorVisibility ? "On" : "Off") << endl; os << indent << "InterpolationTypeVisibility: " << (this->InterpolationTypeVisibility ? "On" : "Off") << endl; os << indent << "MaterialPropertyPosition: " << this->MaterialPropertyPosition << endl; os << indent << "WholeRangeComputationMethod: " << this->WholeRangeComputationMethod << endl; os << indent << "MaterialPropertyVisibility: " << (this->MaterialPropertyVisibility ? "On" : "Off") << endl; os << indent << "GradientOpacityFunctionVisibility: " << (this->GradientOpacityFunctionVisibility ? "On" : "Off") << endl; os << indent << "ComponentWeightsVisibility: " << (this->ComponentWeightsVisibility ? "On" : "Off") << endl; os << indent << "ScalarOpacityFunctionEditor: "; os << indent << "UseScalarColorFunctionInScalarOpacityEditor: " << (this->UseScalarColorFunctionInScalarOpacityEditor ? "On" : "Off") << endl; if (this->ScalarOpacityFunctionEditor) { os << endl; this->ScalarOpacityFunctionEditor->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "ScalarColorFunctionEditor: "; if (this->ScalarColorFunctionEditor) { os << endl; this->ScalarColorFunctionEditor->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "GradientOpacityFunctionEditor: "; if (this->GradientOpacityFunctionEditor) { os << endl; this->GradientOpacityFunctionEditor->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "ScalarOpacityUnitDistanceScale: "; if (this->ScalarOpacityUnitDistanceScale) { os << endl; this->ScalarOpacityUnitDistanceScale->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "VolumeProperty: "; if (this->VolumeProperty) { os << endl; this->VolumeProperty->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "DataSet: "; if (this->DataSet) { os << endl; this->DataSet->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "HistogramSet: "; if (this->HistogramSet) { os << endl; this->HistogramSet->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "HSVColorSelector: "; if (this->HSVColorSelector) { os << endl; this->HSVColorSelector->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWUserInterfaceManager.cxx0000644000175000017500000003065511131233223022626 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWUserInterfaceManager.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWUserInterfaceManager.h" #include "vtkKWWidget.h" #include "vtkKWUserInterfacePanel.h" #include "vtkObjectFactory.h" #include #include #include //---------------------------------------------------------------------------- vtkCxxRevisionMacro(vtkKWUserInterfaceManager, "$Revision: 1.24 $"); //---------------------------------------------------------------------------- class vtkKWUserInterfaceManagerInternals { public: typedef vtksys_stl::list PanelsContainer; typedef vtksys_stl::list::iterator PanelsContainerIterator; typedef vtksys_stl::map PanelsIdHistoryContainer; typedef vtksys_stl::map::iterator PanelsIdHistoryIterator; PanelsContainer Panels; PanelsIdHistoryContainer PanelsIdHistory; }; //---------------------------------------------------------------------------- vtkKWUserInterfaceManager::vtkKWUserInterfaceManager() { this->IdCounter = 0; this->ManagerIsCreated = 0; this->Internals = new vtkKWUserInterfaceManagerInternals; } //---------------------------------------------------------------------------- vtkKWUserInterfaceManager::~vtkKWUserInterfaceManager() { // Delete all panels this->RemoveAllPanels(); if (this->Internals) { delete this->Internals; } } //---------------------------------------------------------------------------- vtkKWUserInterfaceManager::PanelSlot* vtkKWUserInterfaceManager::GetPanelSlot(vtkKWUserInterfacePanel *panel) { if (this->Internals && panel) { vtkKWUserInterfaceManagerInternals::PanelsContainerIterator it = this->Internals->Panels.begin(); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator end = this->Internals->Panels.end(); for (; it != end; ++it) { if (*it && (*it)->Panel == panel) { return *it; } } } return NULL; } //---------------------------------------------------------------------------- vtkKWUserInterfaceManager::PanelSlot* vtkKWUserInterfaceManager::GetPanelSlot(int id) { if (this->Internals) { vtkKWUserInterfaceManagerInternals::PanelsContainerIterator it = this->Internals->Panels.begin(); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator end = this->Internals->Panels.end(); for (; it != end; ++it) { if (*it && (*it)->Id == id) { return *it; } } } return NULL; } //---------------------------------------------------------------------------- vtkKWUserInterfaceManager::PanelSlot* vtkKWUserInterfaceManager::GetPanelSlot(const char *panel_name) { if (this->Internals && panel_name) { vtkKWUserInterfaceManagerInternals::PanelsContainerIterator it = this->Internals->Panels.begin(); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator end = this->Internals->Panels.end(); for (; it != end; ++it) { if (*it && (*it)->Panel && (*it)->Panel->GetName() && !strcmp((*it)->Panel->GetName(), panel_name)) { return *it; } } } return NULL; } //---------------------------------------------------------------------------- vtkKWUserInterfaceManager::PanelSlot* vtkKWUserInterfaceManager::GetNthPanelSlot(int rank) { if (this->Internals && rank >= 0 && rank < this->GetNumberOfPanels()) { vtkKWUserInterfaceManagerInternals::PanelsContainerIterator it = this->Internals->Panels.begin(); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator end = this->Internals->Panels.end(); for (; it != end; ++it) { if (*it && !rank--) { return *it; } } } return NULL; } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManager::HasPanel(vtkKWUserInterfacePanel *panel) { return this->GetPanelSlot(panel) ? 1 : 0; } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManager::GetPanelId(vtkKWUserInterfacePanel *panel) { vtkKWUserInterfaceManager::PanelSlot *panel_slot = this->GetPanelSlot(panel); if (!panel_slot) { return -1; } return panel_slot->Id; } //---------------------------------------------------------------------------- vtkKWUserInterfacePanel* vtkKWUserInterfaceManager::GetPanel(int id) { vtkKWUserInterfaceManager::PanelSlot *panel_slot = this->GetPanelSlot(id); if (!panel_slot) { return NULL; } return panel_slot->Panel; } //---------------------------------------------------------------------------- vtkKWUserInterfacePanel* vtkKWUserInterfaceManager::GetPanel( const char *panel_name) { vtkKWUserInterfaceManager::PanelSlot *panel_slot = this->GetPanelSlot(panel_name); if (!panel_slot) { return NULL; } return panel_slot->Panel; } //---------------------------------------------------------------------------- vtkKWUserInterfacePanel* vtkKWUserInterfaceManager::GetNthPanel(int rank) { vtkKWUserInterfaceManager::PanelSlot *panel_slot = this->GetNthPanelSlot(rank); if (!panel_slot) { return NULL; } return panel_slot->Panel; } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManager::Create() { // Set the application if (this->IsCreated()) { vtkErrorMacro("The manager is already created"); return; } this->ManagerIsCreated = 1; } // --------------------------------------------------------------------------- int vtkKWUserInterfaceManager::IsCreated() { return (this->GetApplication() != NULL && this->ManagerIsCreated); } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManager::SetEnabled(int arg) { if (this->Internals) { vtkKWUserInterfaceManagerInternals::PanelsContainerIterator it = this->Internals->Panels.begin(); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator end = this->Internals->Panels.end(); for (; it != end; ++it) { if (*it && (*it)->Panel) { (*it)->Panel->SetEnabled(arg); (*it)->Panel->Update(); } } } } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManager::Update() { if (this->Internals) { vtkKWUserInterfaceManagerInternals::PanelsContainerIterator it = this->Internals->Panels.begin(); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator end = this->Internals->Panels.end(); for (; it != end; ++it) { if (*it && (*it)->Panel) { (*it)->Panel->Update(); } } } } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManager::UpdateEnableState() { if (this->Internals) { vtkKWUserInterfaceManagerInternals::PanelsContainerIterator it = this->Internals->Panels.begin(); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator end = this->Internals->Panels.end(); for (; it != end; ++it) { if (*it && (*it)->Panel) { (*it)->Panel->UpdateEnableState(); } } } } // ---------------------------------------------------------------------------- int vtkKWUserInterfaceManager::GetNumberOfPanels() { return this->Internals ? (int)this->Internals->Panels.size() : 0; } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManager::AddPanel(vtkKWUserInterfacePanel *panel) { if (!panel) { vtkErrorMacro("Can not add a NULL panel to the manager."); return -1; } // Don't allow duplicates (return silently though) if (this->HasPanel(panel)) { return this->GetPanelId(panel); } // Add the panel slot to the manager vtkKWUserInterfaceManager::PanelSlot *panel_slot = new vtkKWUserInterfaceManager::PanelSlot; this->Internals->Panels.push_back(panel_slot); // Each panel has a unique ID in the manager lifetime panel_slot->Panel = panel; // If the panel had been added to the manager in the past, re-use the same // ID. This is important for some subclasses for example which use that // ID to track some internal widgets per panel. vtkKWUserInterfaceManagerInternals::PanelsIdHistoryIterator it = this->Internals->PanelsIdHistory.find(panel_slot->Panel); if (it == this->Internals->PanelsIdHistory.end()) { panel_slot->Id = this->IdCounter++; this->Internals->PanelsIdHistory[panel_slot->Panel] = panel_slot->Id; } else { panel_slot->Id = it->second; } // For convenience, make sure the panel use this instance. // Note that vtkKWUserInterfacePanel::SetUserInterfaceManager also // calls the current method for convenience. panel_slot->Panel->SetUserInterfaceManager(this); // Use the same application (for convenience) if (!this->GetApplication() && panel->GetApplication()) { this->SetApplication(panel->GetApplication()); } panel_slot->Panel->Register(this); this->NumberOfPanelsChanged(); return panel_slot->Id; } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManager::RemovePanel(vtkKWUserInterfacePanel *panel) { if (!panel) { vtkErrorMacro("Can not remove a NULL panel from the manager."); return 0; } // Silently returns if the panel has been removed already if (!this->HasPanel(panel)) { return 1; } // Remove the page widgets from the interface this->RemovePageWidgets(panel); // Find the panel in the manager vtkKWUserInterfaceManager::PanelSlot *panel_slot = this->GetPanelSlot(panel); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator pos = vtksys_stl::find(this->Internals->Panels.begin(), this->Internals->Panels.end(), panel_slot); if (pos == this->Internals->Panels.end()) { vtkErrorMacro("Error while removing a panel from the manager " "(can not find the panel)."); return 0; } // Remove the panel from the container this->Internals->Panels.erase(pos); // For convenience, we had made sure the panel use this instance as manager // in the AddPanel() method. panel_slot->Panel->SetUserInterfaceManager(NULL); panel_slot->Panel->UnRegister(this); // Delete the panel slot delete panel_slot; this->NumberOfPanelsChanged(); return 1; } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManager::RemoveAllPanels() { while (this->GetNumberOfPanels()) { this->RemovePanel(this->GetNthPanel(0)); } } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManager::ShowAllPanels() { if (this->Internals) { vtkKWUserInterfaceManagerInternals::PanelsContainerIterator it = this->Internals->Panels.begin(); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator end = this->Internals->Panels.end(); for (; it != end; ++it) { if (*it && (*it)->Panel) { this->ShowPanel((*it)->Panel); } } } } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManager::HideAllPanels() { if (this->Internals) { vtkKWUserInterfaceManagerInternals::PanelsContainerIterator it = this->Internals->Panels.begin(); vtkKWUserInterfaceManagerInternals::PanelsContainerIterator end = this->Internals->Panels.end(); for (; it != end; ++it) { if (*it && (*it)->Panel) { this->HidePanel((*it)->Panel); } } } } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManager::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWDragAndDropTargetSet.cxx0000644000175000017500000004524311044115427022553 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWDragAndDropTargetSet.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWDragAndDropTargetSet.h" #include "vtkObjectFactory.h" #include "vtkKWCoreWidget.h" #include "vtkKWTkUtilities.h" #include #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWDragAndDropTargetSet ); vtkCxxRevisionMacro(vtkKWDragAndDropTargetSet, "$Revision: 1.16 $"); //---------------------------------------------------------------------------- class vtkKWDragAndDropTargetSetInternals { public: typedef vtksys_stl::list TargetsContainer; typedef vtksys_stl::list::iterator TargetsContainerIterator; TargetsContainer Targets; }; //---------------------------------------------------------------------------- vtkKWDragAndDropTargetSet::TargetSlot::TargetSlot() { this->Target = NULL; this->StartCommand = NULL; this->PerformCommand = NULL; this->EndCommand = NULL; } //---------------------------------------------------------------------------- vtkKWDragAndDropTargetSet::TargetSlot::~TargetSlot() { this->Target = NULL; this->SetStartCommand(NULL); this->SetPerformCommand(NULL); this->SetEndCommand(NULL); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::TargetSlot::SetStartCommand(const char *arg) { if ((this->StartCommand == NULL && arg == NULL) || (this->StartCommand && arg && (!strcmp(this->StartCommand,arg)))) { return; } if (this->StartCommand) { delete [] this->StartCommand; } if (arg) { this->StartCommand = new char[strlen(arg) + 1]; strcpy(this->StartCommand, arg); } else { this->StartCommand = NULL; } } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::TargetSlot::SetPerformCommand(const char *arg) { if ((this->PerformCommand == NULL && arg == NULL) || (this->PerformCommand && arg && (!strcmp(this->PerformCommand,arg)))) { return; } if (this->PerformCommand) { delete [] this->PerformCommand; } if (arg) { this->PerformCommand = new char[strlen(arg) + 1]; strcpy(this->PerformCommand, arg); } else { this->PerformCommand = NULL; } } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::TargetSlot::SetEndCommand(const char *arg) { if ((this->EndCommand == NULL && arg == NULL) || (this->EndCommand && arg && (!strcmp(this->EndCommand,arg)))) { return; } if (this->EndCommand) { delete [] this->EndCommand; } if (arg) { this->EndCommand = new char[strlen(arg) + 1]; strcpy(this->EndCommand, arg); } else { this->EndCommand = NULL; } } //---------------------------------------------------------------------------- vtkKWDragAndDropTargetSet::vtkKWDragAndDropTargetSet() { this->Enable = 1; this->Source = NULL; this->SourceAnchor = NULL; this->StartCommand = NULL; this->PerformCommand = NULL; this->EndCommand = NULL; this->Internals = new vtkKWDragAndDropTargetSetInternals; } //---------------------------------------------------------------------------- vtkKWDragAndDropTargetSet::~vtkKWDragAndDropTargetSet() { this->Source = NULL; this->SourceAnchor = NULL; if (this->StartCommand) { delete [] this->StartCommand; this->StartCommand = NULL; } if (this->PerformCommand) { delete [] this->PerformCommand; this->PerformCommand = NULL; } if (this->EndCommand) { delete [] this->EndCommand; this->EndCommand = NULL; } this->DeleteAllTargets(); delete this->Internals; } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::DeleteAllTargets() { if (this->Internals) { vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator it = this->Internals->Targets.begin(); vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator end = this->Internals->Targets.end(); for (; it != end; ++it) { if (*it) { delete *it; } } } } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::SetEnable(int arg) { if (this->Enable == arg) { return; } this->Enable = arg; this->Modified(); if (arg) { this->AddBindings(); } else { this->RemoveBindings(); } } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::SetSource(vtkKWWidget *arg) { if (this->Source == arg) { return; } this->RemoveBindings(); this->Source = arg; this->Modified(); this->AddBindings(); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::SetSourceAnchor(vtkKWWidget *arg) { if (this->SourceAnchor == arg) { return; } this->RemoveBindings(); this->SourceAnchor = arg; this->Modified(); this->AddBindings(); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::InvokeCommandWithCoordinates( const char *command, int x, int y) { if (command && *command) { this->Script("%s %d %d", command, x, y); } } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::SetStartCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->StartCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::InvokeStartCommand(int x, int y) { this->InvokeCommandWithCoordinates(this->StartCommand, x, y); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::SetPerformCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->PerformCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::InvokePerformCommand(int x, int y) { this->InvokeCommandWithCoordinates(this->PerformCommand, x, y); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::SetEndCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->EndCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::InvokeEndCommand(int x, int y) { this->InvokeCommandWithCoordinates(this->EndCommand, x, y); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::AddBindings() { if (!this->GetApplication()) { vtkErrorMacro("Error! Application not set!"); return; } vtkKWWidget *anchor = this->SourceAnchor ? this->SourceAnchor : this->Source; if (!anchor || !anchor->IsCreated()) { return; } anchor->AddBinding("", this, "StartCallback %X %Y"); anchor->AddBinding("", this, "PerformCallback %X %Y"); anchor->AddBinding("", this, "EndCallback %X %Y"); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::RemoveBindings() { if (!this->GetApplication()) { vtkErrorMacro("Error! Application not set!"); return; } vtkKWWidget *anchor = this->SourceAnchor ? this->SourceAnchor : this->Source; if (!anchor || !anchor->IsCreated()) { return; } anchor->RemoveBinding(""); anchor->RemoveBinding(""); anchor->RemoveBinding(""); } //---------------------------------------------------------------------------- vtkKWDragAndDropTargetSet::TargetSlot* vtkKWDragAndDropTargetSet::GetTarget(vtkKWWidget *widget) { if (this->Internals) { vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator it = this->Internals->Targets.begin(); vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator end = this->Internals->Targets.end(); for (; it != end; ++it) { if (*it && (*it)->Target == widget) { return (*it); } } } return NULL; } //---------------------------------------------------------------------------- int vtkKWDragAndDropTargetSet::AddTarget(vtkKWWidget *widget) { vtkKWDragAndDropTargetSet::TargetSlot *found = this->GetTarget(widget); if (found) { vtkErrorMacro("The Drag & Drop target already exists."); return 0; } vtkKWDragAndDropTargetSet::TargetSlot *target_slot = new vtkKWDragAndDropTargetSet::TargetSlot; this->Internals->Targets.push_back(target_slot); target_slot->Target = widget; return 1; } //---------------------------------------------------------------------------- int vtkKWDragAndDropTargetSet::RemoveTarget(vtkKWWidget *widget) { vtkKWDragAndDropTargetSet::TargetSlot *found = this->GetTarget(widget); if (!found) { return 0; } vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator pos = vtksys_stl::find(this->Internals->Targets.begin(), this->Internals->Targets.end(), found); if (pos == this->Internals->Targets.end()) { vtkErrorMacro("Error while searching for a Drag & Drop target."); return 0; } this->Internals->Targets.erase(pos); delete found; return 1; } //---------------------------------------------------------------------------- int vtkKWDragAndDropTargetSet::HasTarget(vtkKWWidget *widget) { vtkKWDragAndDropTargetSet::TargetSlot *found = this->GetTarget(widget); return found ? 1 : 0; } //---------------------------------------------------------------------------- int vtkKWDragAndDropTargetSet::GetNumberOfTargets() { return this->Internals ? (int)this->Internals->Targets.size() : 0; } //---------------------------------------------------------------------------- int vtkKWDragAndDropTargetSet::SetTargetStartCommand(vtkKWWidget *target, vtkObject *object, const char *method) { if (!target || !object || !method || !method[0]) { return 0; } vtkKWDragAndDropTargetSet::TargetSlot *found = this->GetTarget(target); if (!found) { this->AddTarget(target); } found = this->GetTarget(target); if (!found) { return 0; } char *command = NULL; this->SetObjectMethodCommand(&command, object, method); found->SetStartCommand(command); delete [] command; return 1; } //---------------------------------------------------------------------------- int vtkKWDragAndDropTargetSet::SetTargetPerformCommand(vtkKWWidget *target, vtkObject *object, const char *method) { if (!target || !object || !method || !method[0]) { return 0; } vtkKWDragAndDropTargetSet::TargetSlot *found = this->GetTarget(target); if (!found) { this->AddTarget(target); } found = this->GetTarget(target); if (!found) { return 0; } char *command = NULL; this->SetObjectMethodCommand(&command, object, method); found->SetPerformCommand(command); delete [] command; return 1; } //---------------------------------------------------------------------------- int vtkKWDragAndDropTargetSet::SetTargetEndCommand(vtkKWWidget *target, vtkObject *object, const char *method) { if (!target || !object || !method || !method[0]) { return 0; } vtkKWDragAndDropTargetSet::TargetSlot *found = this->GetTarget(target); if (!found) { this->AddTarget(target); } found = this->GetTarget(target); if (!found) { return 0; } char *command = NULL; this->SetObjectMethodCommand(&command, object, method); found->SetEndCommand(command); delete [] command; return 1; } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::StartCallback(int x, int y) { if (!this->Enable) { return; } this->InvokeStartCommand(x, y); if (this->Internals && this->GetNumberOfTargets()) { // Set the cursor and invert foreground/background to better show what // is dragged vtkKWWidget *anchor = this->SourceAnchor ? this->SourceAnchor : this->Source; if (anchor && anchor->IsCreated()) { vtkKWTkUtilities::SetTopLevelMouseCursor(anchor, "hand2"); vtkKWCoreWidget *anchor_as_core = vtkKWCoreWidget::SafeDownCast(anchor); if (anchor_as_core->HasConfigurationOption("-fg") && anchor_as_core->HasConfigurationOption("-bg")) { double fr, fg, fb, br, bg, bb; anchor_as_core->GetConfigurationOptionAsColor("-fg", &fr, &fg, &fb); anchor_as_core->GetConfigurationOptionAsColor("-bg", &br, &bg, &bb); anchor_as_core->SetConfigurationOptionAsColor("-fg", br, bg, bb); anchor_as_core->SetConfigurationOptionAsColor("-bg", fr, fg, fb); } } // Call each target's StartCommand vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator it = this->Internals->Targets.begin(); vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator end = this->Internals->Targets.end(); for (; it != end; ++it) { if (*it && (*it)->StartCommand && *(*it)->StartCommand) { if (this->Source && !this->Source->GetApplication()) { vtkErrorMacro("Error! Source's application not set!"); continue; } if (this->SourceAnchor && !this->SourceAnchor->GetApplication()) { vtkErrorMacro("Error! SourceAnchor's application not set!"); continue; } this->Script("%s %d %d %s %s", (*it)->StartCommand, x, y, this->Source ? this->Source->GetTclName() : "", this->SourceAnchor ? this->SourceAnchor->GetTclName():""); } } } } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::PerformCallback(int x, int y) { if (!this->Enable) { return; } this->InvokePerformCommand(x, y); if (this->Internals && this->GetNumberOfTargets()) { // Call each target's PerformCommand vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator it = this->Internals->Targets.begin(); vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator end = this->Internals->Targets.end(); for (; it != end; ++it) { if (*it && (*it)->PerformCommand && *(*it)->PerformCommand) { if (this->Source && !this->Source->GetApplication()) { vtkErrorMacro("Error! Source's application not set!"); continue; } if (this->SourceAnchor && !this->SourceAnchor->GetApplication()) { vtkErrorMacro("Error! SourceAnchor's application not set!"); continue; } this->Script("%s %d %d %s %s", (*it)->PerformCommand, x, y, this->Source ? this->Source->GetTclName() : "", this->SourceAnchor ? this->SourceAnchor->GetTclName():""); } } } } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::EndCallback(int x, int y) { if (!this->Enable) { return; } if (this->Internals && this->GetNumberOfTargets()) { // Reset the cursor and the background/foreground colors vtkKWWidget *anchor = this->SourceAnchor ? this->SourceAnchor : this->Source; if (anchor && anchor->IsCreated()) { vtkKWTkUtilities::SetTopLevelMouseCursor(anchor, NULL); vtkKWCoreWidget *anchor_as_core = vtkKWCoreWidget::SafeDownCast(anchor); if (anchor_as_core->HasConfigurationOption("-fg") && anchor_as_core->HasConfigurationOption("-bg")) { double fr, fg, fb, br, bg, bb; anchor_as_core->GetConfigurationOptionAsColor("-fg", &fr, &fg, &fb); anchor_as_core->GetConfigurationOptionAsColor("-bg", &br, &bg, &bb); anchor_as_core->SetConfigurationOptionAsColor("-fg", br, bg, bb); anchor_as_core->SetConfigurationOptionAsColor("-bg", fr, fg, fb); } } // Find if the cursor is in a target, and call its EndCommand vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator it = this->Internals->Targets.begin(); vtkKWDragAndDropTargetSetInternals::TargetsContainerIterator end = this->Internals->Targets.end(); for (; it != end; ++it) { if (*it && (*it)->EndCommand && *(*it)->EndCommand && (*it)->Target && (*it)->Target->IsCreated() && vtkKWTkUtilities::ContainsCoordinates((*it)->Target, x, y)) { if (this->Source && !this->Source->GetApplication()) { vtkErrorMacro("Error! Source's application not set!"); continue; } if (this->SourceAnchor && !this->SourceAnchor->GetApplication()) { vtkErrorMacro("Error! SourceAnchor's application not set!"); continue; } this->Script("%s %d %d %s %s %s", (*it)->EndCommand, x, y, this->Source ? this->Source->GetTclName() : "", this->SourceAnchor ? this->SourceAnchor->GetTclName():"", (*it)->Target->GetTclName()); } } } this->InvokeEndCommand(x, y); } //---------------------------------------------------------------------------- void vtkKWDragAndDropTargetSet::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Enable: " << (this->Enable ? "On" : "Off") << endl; os << indent << "Source: " << this->Source << endl; os << indent << "SourceAnchor: " << this->SourceAnchor << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWSpinButtons.h0000644000175000017500000001201210424463540020507 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWSpinButtons.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWSpinButtons - A set of spin-buttons. // .SECTION Description // This widget implements a small set of two buttons that can be used // to switch to the next or previous value of an external variable through // callbacks. // The buttons can be set to display up/down or left/right arrows, and laid // out vertically or horizontally. // The 'previous' button is mapped to the up/left arrow, the 'next' button // is mapped to the 'down/right' arrow. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. #ifndef __vtkKWSpinButtons_h #define __vtkKWSpinButtons_h #include "vtkKWCompositeWidget.h" class vtkKWPushButton; class KWWidgets_EXPORT vtkKWSpinButtons : public vtkKWCompositeWidget { public: static vtkKWSpinButtons* New(); vtkTypeRevisionMacro(vtkKWSpinButtons,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the buttons vtkGetObjectMacro(PreviousButton, vtkKWPushButton); vtkGetObjectMacro(NextButton, vtkKWPushButton); // Description: // Specifies the commands to associate to the next and previous // buttons. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetPreviousCommand(vtkObject *object, const char *method); virtual void SetNextCommand(vtkObject *object, const char *method); // Description: // Set/Get the arrow orientation of the spin buttons. // If set to horizontal, left/right arrows will be used. If set to // vertical, up/down arrows will be used. //BTX enum { ArrowOrientationHorizontal = 0, ArrowOrientationVertical }; //ETX virtual void SetArrowOrientation(int); vtkGetMacro(ArrowOrientation, int); virtual void SetArrowOrientationToHorizontal() { this->SetArrowOrientation( vtkKWSpinButtons::ArrowOrientationHorizontal); }; virtual void SetArrowOrientationToVertical() { this->SetArrowOrientation( vtkKWSpinButtons::ArrowOrientationVertical); }; // Description: // Set/Get the layout of the spin buttons. // If set to horizontal, the 'previous' button is packed to the // left of the 'next' button. If set to vertical, the 'previous' button // is packed on top of the 'next' button. //BTX enum { LayoutOrientationHorizontal = 0, LayoutOrientationVertical }; //ETX virtual void SetLayoutOrientation(int); vtkGetMacro(LayoutOrientation, int); virtual void SetLayoutOrientationToHorizontal() { this->SetLayoutOrientation( vtkKWSpinButtons::LayoutOrientationHorizontal); }; virtual void SetLayoutOrientationToVertical() { this->SetLayoutOrientation( vtkKWSpinButtons::LayoutOrientationVertical); }; // Description: // Set/Get the padding that will be applied around each buttons. // (default to 0). virtual void SetButtonsPadX(int); vtkGetMacro(ButtonsPadX, int); virtual void SetButtonsPadY(int); vtkGetMacro(ButtonsPadY, int); // Description: // Set the buttons width/height. // No effects if called before Create() virtual void SetButtonsWidth(int w); virtual int GetButtonsWidth(); virtual void SetButtonsHeight(int h); virtual int GetButtonsHeight(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); protected: vtkKWSpinButtons(); ~vtkKWSpinButtons(); // Description: // Create the widget. virtual void CreateWidget(); vtkKWPushButton *PreviousButton; vtkKWPushButton *NextButton; int ArrowOrientation; int LayoutOrientation; int ButtonsPadX; int ButtonsPadY; virtual void Pack(); virtual void UpdateArrowOrientation(); private: vtkKWSpinButtons(const vtkKWSpinButtons&); // Not implemented void operator=(const vtkKWSpinButtons&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWWidgetsVersion.h0000644000175000017500000000447111332747227021213 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetsVersion.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWWidgetsVersion - Versioning class for KWWidgets // .SECTION Description // Holds methods for defining/determining the current KWWidgets version // (major, minor, build). // .SECTION Caveats // This file will change frequently to update the VTK_SOURCE_VERSION which // timestamps a particular source release. #ifndef __vtkKWWidgetsVersion_h #define __vtkKWWidgetsVersion_h #include "vtkKWWidgets.h" // Needed for export symbols directives #include "vtkObject.h" #define KWWidgets_SOURCE_VERSION "KWWidgets version " KWWidgets_VERSION ", KWWidgets source $Revision: 1.1211 $, $Date: 2010-02-05 07:53:59 $ (GMT)" class KWWidgets_EXPORT vtkKWWidgetsVersion : public vtkObject { public: static vtkKWWidgetsVersion *New(); vtkTypeRevisionMacro(vtkKWWidgetsVersion,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Return the major, minor and patch version of the KWWidgets library. static int GetKWWidgetsMajorVersion() { return KWWidgets_MAJOR_VERSION; } static int GetKWWidgetsMinorVersion() { return KWWidgets_MINOR_VERSION; } static int GetKWWidgetsPatchVersion() { return KWWidgets_PATCH_VERSION; } // Description: // Return the version of the KWWidgets library (as an aggregation of // the major, minor and patch version). static const char *GetKWWidgetsVersion() { return KWWidgets_VERSION; } // Description: // Return a string with an identifier which timestamps a particular source // tree. static const char *GetKWWidgetsSourceVersion() { return KWWidgets_SOURCE_VERSION; } protected: vtkKWWidgetsVersion() {}; ~vtkKWWidgetsVersion() {}; private: vtkKWWidgetsVersion(const vtkKWWidgetsVersion&); // Not implemented. void operator=(const vtkKWWidgetsVersion&); // Not implemented. }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWSplashScreen.cxx0000644000175000017500000002352211123736772021203 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWSplashScreen.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWSplashScreen.h" #include "vtkKWApplication.h" #include "vtkKWCanvas.h" #include "vtkKWIcon.h" #include "vtkObjectFactory.h" #include "vtkKWResourceUtilities.h" #include "vtkKWTkUtilities.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWSplashScreen ); vtkCxxRevisionMacro(vtkKWSplashScreen, "$Revision: 1.43 $"); //---------------------------------------------------------------------------- vtkKWSplashScreen::vtkKWSplashScreen() { this->Canvas = vtkKWCanvas::New(); this->ImageName = NULL; this->ProgressMessageVerticalOffset = -12; this->DisplayPosition = vtkKWTopLevel::DisplayPositionScreenCenter; this->HideDecoration = 1; this->Discard = 0; } //---------------------------------------------------------------------------- vtkKWSplashScreen::~vtkKWSplashScreen() { if (this->Canvas) { this->Canvas->Delete(); this->Canvas = NULL; } this->SetImageName(NULL); } //---------------------------------------------------------------------------- void vtkKWSplashScreen::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Create and pack the canvas this->Canvas->SetParent(this); this->Canvas->Create(); this->Canvas->SetBorderWidth(0); this->Canvas->SetHighlightThickness(0); this->Script("pack %s -side top -fill both -expand y", this->Canvas->GetWidgetName()); this->Canvas->AddBinding("", this, "ButtonPressCallback"); // Insert the image this->Script("%s create image 0 0 -tags image -anchor nw", this->Canvas->GetWidgetName()); // Insert the text this->Script("%s create text 0 0 -tags msg -fill #666666 -anchor c", this->Canvas->GetWidgetName()); this->UpdateImageInCanvas(); this->UpdateProgressMessagePosition(); } //---------------------------------------------------------------------------- void vtkKWSplashScreen::Display() { this->Discard = 0; this->Superclass::Display(); } //---------------------------------------------------------------------------- void vtkKWSplashScreen::ButtonPressCallback() { this->Withdraw(); this->Discard = 1; } //---------------------------------------------------------------------------- void vtkKWSplashScreen::UpdateCanvasSize() { // Resize the canvas according to the image if (this->IsCreated() && this->ImageName) { vtkKWApplication *app = this->GetApplication(); this->Canvas->SetWidth( vtkKWTkUtilities::GetPhotoWidth(app, this->ImageName)); this->Canvas->SetHeight( vtkKWTkUtilities::GetPhotoHeight(app, this->ImageName)); this->UpdateProgressMessagePosition(); } } //---------------------------------------------------------------------------- void vtkKWSplashScreen::UpdateProgressMessagePosition() { if (this->IsCreated()) { int width = this->Canvas->GetWidth(); int height = this->Canvas->GetHeight(); double x = (double)width * 0.5; double y = (this->ProgressMessageVerticalOffset < 0 ? height + ProgressMessageVerticalOffset : ProgressMessageVerticalOffset); this->Script("%s coords msg %lf %d", this->Canvas->GetWidgetName(), x, (int)y); } } //---------------------------------------------------------------------------- void vtkKWSplashScreen::UpdateImageInCanvas() { if (this->Canvas && this->Canvas->IsCreated()) { const char *res = this->Canvas->Script( "%s itemconfigure image -image {%s}", this->Canvas->GetWidgetName(), this->ImageName ? this->ImageName : ""); this->UpdateCanvasSize(); if (res && *res) { vtkErrorMacro("Error setting ImageName: " << res); } } } //---------------------------------------------------------------------------- void vtkKWSplashScreen::SetImageName(const char* _arg) { if (this->ImageName == NULL && _arg == NULL) { return; } if (this->ImageName && _arg && (!strcmp(this->ImageName, _arg))) { return; } if (this->ImageName) { delete [] this->ImageName; } if (_arg) { this->ImageName = new char[strlen(_arg)+1]; strcpy(this->ImageName, _arg); } else { this->ImageName = NULL; } this->Modified(); this->UpdateImageInCanvas(); } //---------------------------------------------------------------------------- int vtkKWSplashScreen::ReadImage(const char *filename) { int width, height, pixel_size; unsigned char *image_buffer = NULL; // Try to load the image if (!vtkKWResourceUtilities::ReadImage( filename, &width, &height, &pixel_size, &image_buffer)) { vtkErrorMacro("Error reading image: " << (filename ? filename : "")); return 0; } this->SetImageToPixels(image_buffer, width, height, pixel_size); delete [] image_buffer; return 1; } //---------------------------------------------------------------------------- void vtkKWSplashScreen::SetImageToPredefinedIcon(int icon_index) { vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImage(icon_index); this->SetImageToIcon(icon); icon->Delete(); } //---------------------------------------------------------------------------- void vtkKWSplashScreen::SetImageToIcon(vtkKWIcon* icon) { if (icon) { this->SetImageToPixels( icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize()); } else { this->SetImageToPixels(NULL, 0, 0, 0); } } //---------------------------------------------------------------------------- void vtkKWSplashScreen::SetImageToPixels(const unsigned char* pixels, int width, int height, int pixel_size, unsigned long buffer_length) { if (!pixels || !width || !height || !pixel_size) { this->SetImageName(NULL); return; } // If no image name, make up one vtksys_stl::string new_image_name; if (!this->ImageName) { new_image_name = this->GetTclName(); new_image_name += "Photo"; } const char *image_name = (this->ImageName ? this->ImageName : new_image_name.c_str()); // Update the Tk image (or create it if it did not exist) int res = vtkKWTkUtilities::UpdatePhoto( this->GetApplication(), image_name, pixels, width, height, pixel_size, buffer_length); if (!res) { vtkErrorMacro("Error updating photo: " << image_name); } // Assign the new image name (now that it has been created) // This will update the canvas as well if (new_image_name.size()) { this->SetImageName(new_image_name.c_str()); } else { this->UpdateImageInCanvas(); } } //---------------------------------------------------------------------------- void vtkKWSplashScreen::SetProgressMessage(const char *txt) { if (!this->IsCreated() || !txt) { return; } const char *val = this->ConvertInternalStringToTclString( txt, vtkKWCoreWidget::ConvertStringEscapeInterpretable); this->Script("%s itemconfigure msg -text \"%s\"", this->Canvas->GetWidgetName(), (val ? val : "")); if (!this->IsMapped() && !this->Discard) { this->Display(); } // As much as call to 'update' are evil, this is the only way to bring // the splashscreen up-to-date and in front. 'update idletasks' will not // do the trick because this code is usually executed during initialization // or creation of the UI, not in the event loop this->GetApplication()->ProcessPendingEvents(); } //---------------------------------------------------------------------------- void vtkKWSplashScreen::SetProgressMessageVerticalOffset(int _arg) { if (this->ProgressMessageVerticalOffset == _arg) { return; } this->ProgressMessageVerticalOffset = _arg; this->Modified(); this->UpdateProgressMessagePosition(); } //---------------------------------------------------------------------------- int vtkKWSplashScreen::GetRequestedWidth() { if (this->IsCreated() && this->ImageName) { return vtkKWTkUtilities::GetPhotoWidth(this->GetApplication(), this->ImageName); } return this->Superclass::GetRequestedWidth(); } //---------------------------------------------------------------------------- int vtkKWSplashScreen::GetRequestedHeight() { if (this->IsCreated() && this->ImageName) { return vtkKWTkUtilities::GetPhotoHeight(this->GetApplication(), this->ImageName); } return this->Superclass::GetRequestedHeight(); } // --------------------------------------------------------------------------- void vtkKWSplashScreen::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->Canvas); } //---------------------------------------------------------------------------- void vtkKWSplashScreen::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "ProgressMessageVerticalOffset: " << this->ProgressMessageVerticalOffset << endl; os << indent << "ImageName: " << (this->ImageName ? this->ImageName : "(none)") << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWKeyBindingsWidget.h0000644000175000017500000000621511260666417021610 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWKeyBindingsWidget.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWKeyBindingsWidget - a key bindings widget. // .SECTION Description // This widget can be used to display key bindings stored in a key bindings // manager class (vtkKWKeyBindingsManager). // .SECTION See Also // vtkKWKeyBindingsManager #ifndef __vtkKWKeyBindingsWidget_h #define __vtkKWKeyBindingsWidget_h #include "vtkKWCompositeWidget.h" class vtkKWMultiColumnListWithScrollbars; class vtkKWKeyBindingsWidgetInternals; class vtkKWToolbar; class vtkKWPushButton; class vtkKWLoadSaveButton; class vtkKWTextWithScrollbars; class vtkKWFrameWithLabel; class vtkKWKeyBindingsManager; class KWWidgets_EXPORT vtkKWKeyBindingsWidget : public vtkKWCompositeWidget { public: static vtkKWKeyBindingsWidget* New(); vtkTypeRevisionMacro(vtkKWKeyBindingsWidget,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the key bindings manager. vtkGetObjectMacro(KeyBindingsManager,vtkKWKeyBindingsManager); virtual void SetKeyBindingsManager(vtkKWKeyBindingsManager *mgr); // Description: // Write all keybindings to a stream or text file (tab delimited). // Return 1 on success, 0 otherwise virtual int WriteKeyBindingsToStream(ostream& os); virtual int WriteKeyBindingsToFile(const char *filename); // Description: // Expose a few internals vtkGetObjectMacro(Toolbar, vtkKWToolbar); vtkGetObjectMacro(SaveButton, vtkKWLoadSaveButton); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object // is updated and propagated to its internal parts/subwidgets. // This will, for example, enable/disable parts of the widget UI, // enable/disable the visibility of 3D widgets, etc. virtual void UpdateEnableState(); virtual void Update(); // Description: // Callback, do NOT use. virtual void SelectionChangedCallback(); virtual void WriteKeyBindingsToFileCallback(); protected: vtkKWKeyBindingsWidget(); ~vtkKWKeyBindingsWidget(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Member variables vtkKWKeyBindingsWidgetInternals *Internals; vtkKWMultiColumnListWithScrollbars *KeyBindingsList; vtkKWToolbar *Toolbar; vtkKWLoadSaveButton *SaveButton; vtkKWFrameWithLabel *DetailFrame; vtkKWTextWithScrollbars *DetailText; vtkKWKeyBindingsManager *KeyBindingsManager; private: vtkKWKeyBindingsWidget(const vtkKWKeyBindingsWidget&); // Not implemented void operator=(const vtkKWKeyBindingsWidget&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWLogDialog.cxx0000644000175000017500000000476611103623416020447 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWLogDialog.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWLogDialog.h" #include "vtkKWLogWidget.h" #include "vtkKWApplication.h" #include "vtkObjectFactory.h" #include "vtkKWPushButton.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWLogDialog ); vtkCxxRevisionMacro(vtkKWLogDialog, "$Revision: 1.5 $"); //---------------------------------------------------------------------------- vtkKWLogDialog::vtkKWLogDialog() { this->LogWidget = vtkKWLogWidget::New(); this->Options = vtkKWMessageDialog::YesDefault | vtkKWMessageDialog::Resizable; this->Modal = 0; } //---------------------------------------------------------------------------- vtkKWLogDialog::~vtkKWLogDialog() { if (this->LogWidget) { this->LogWidget->Delete(); } } //---------------------------------------------------------------------------- void vtkKWLogDialog::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); this->SetMinimumSize(400, 450); this->SetSize(650, 550); vtksys_stl::string title; if (this->GetApplication()->GetName()) { title += this->GetApplication()->GetName(); title += ": "; } title += "Log Viewer"; this->SetTitle(title.c_str()); // Record viewer if (!this->LogWidget) { this->LogWidget = vtkKWLogWidget::New(); } this->LogWidget->SetParent(this->GetBottomFrame()); this->LogWidget->Create(); this->Script("pack %s -anchor nw -fill both -expand true -padx 2 -pady 2", this->LogWidget->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWLogDialog::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); if(this->LogWidget) { this->LogWidget->PrintSelf(os, indent); } } kwwidgets-1.0.0~cvs20100930/vtkKWDirectoryPresetSelector.cxx0000644000175000017500000004662011016276031023431 0ustar domibeldomibel/*========================================================================= Copyright (c) 1998-2003 Kitware Inc. 469 Clifton Corporate Parkway, Clifton Park, NY, 12065, USA. All rights reserved. No part of this software may be reproduced, distributed, or modified, in any form or by any means, without permission in writing from Kitware Inc. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. =========================================================================*/ #include "vtkKWDirectoryPresetSelector.h" #include "vtkObjectFactory.h" #include "vtkKWMultiColumnList.h" #include "vtkKWMultiColumnListWithScrollbars.h" #include "vtkKWInternationalization.h" #include "vtkKWIcon.h" #include "vtkKWFileBrowserDialog.h" #include #include #include #include #include const char *vtkKWDirectoryPresetSelector::DirectoryColumnName = "Directory"; const char *vtkKWDirectoryPresetSelector::DirectoryEnabledColumnName = "DirectoryEnabled"; //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWDirectoryPresetSelector); vtkCxxRevisionMacro(vtkKWDirectoryPresetSelector, "$Revision: 1.2 $"); //---------------------------------------------------------------------------- vtkKWDirectoryPresetSelector::vtkKWDirectoryPresetSelector() { vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImage(vtkKWIcon::IconFolderXP); icon->TrimTop(); icon->TrimRight(); this->SetPresetButtonsBaseIcon(icon); icon->Delete(); this->SelectSpinButtonsVisibility = 0; this->UniqueDirectories = 0; this->FileBrowserDialog = vtkKWFileBrowserDialog::New(); this->MaximumDirectoryLength = 0; } //---------------------------------------------------------------------------- vtkKWDirectoryPresetSelector::~vtkKWDirectoryPresetSelector() { if (this->FileBrowserDialog) { this->FileBrowserDialog->Delete(); this->FileBrowserDialog = NULL; } } //---------------------------------------------------------------------------- void vtkKWDirectoryPresetSelector::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro("vtkKWDirectoryPresetSelector already created"); return; } // Call the superclass, this will set the application and // create the pushbutton. this->Superclass::CreateWidget(); this->FileBrowserDialog->SetParent(this); this->FileBrowserDialog->ChooseDirectoryOn(); this->FileBrowserDialog->SaveDialogOff(); this->SetCommentColumnVisibility(0); this->SetPresetAddCommand(this, "AddDirectoryCallback"); vtkKWMultiColumnList *list = this->PresetList->GetWidget(); list->SetRowSpacing(1); } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::SetPresetDirectory( int id, const char *val) { return this->SetPresetUserSlotAsString(id, "Directory", val); } //---------------------------------------------------------------------------- const char* vtkKWDirectoryPresetSelector::GetPresetDirectory(int id) { return this->GetPresetUserSlotAsString(id, "Directory"); } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::SetPresetDirectoryEnabled( int id, int val) { return this->SetPresetUserSlotAsInt(id, "DirectoryEnabled", val); } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::GetPresetDirectoryEnabled(int id) { return this->GetPresetUserSlotAsInt(id, "DirectoryEnabled"); } //---------------------------------------------------------------------------- void vtkKWDirectoryPresetSelector::CreateColumns() { this->Superclass::CreateColumns(); vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int col; // DirectoryEnabled col = list->InsertColumn(this->GetCommentColumnIndex(), NULL); list->SetColumnName(col, vtkKWDirectoryPresetSelector::DirectoryEnabledColumnName); list->SetColumnResizable(col, 0); list->SetColumnStretchable(col, 0); list->SetColumnEditable(col, 1); list->SetColumnFormatCommandToEmptyOutput(col); list->SetColumnWidth(col, 3); // Directory col = list->InsertColumn( col + 1, ks_("Directory Preset Selector|Column|Directory")); list->SetColumnName(col, vtkKWDirectoryPresetSelector::DirectoryColumnName); list->SetColumnResizable(col, 1); list->SetColumnStretchable(col, 1); list->SetColumnEditable(col, 1); } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::GetDirectoryColumnIndex() { return this->PresetList ? this->PresetList->GetWidget()->GetColumnIndexWithName( vtkKWDirectoryPresetSelector::DirectoryColumnName) : -1; } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::GetDirectoryEnabledColumnIndex() { return this->PresetList ? this->PresetList->GetWidget()->GetColumnIndexWithName( vtkKWDirectoryPresetSelector::DirectoryEnabledColumnName) : -1; } //---------------------------------------------------------------------------- void vtkKWDirectoryPresetSelector::SetDirectoryEnabledColumnVisibility(int arg) { if (this->PresetList) { this->PresetList->GetWidget()->SetColumnVisibility( this->GetDirectoryEnabledColumnIndex(), arg); } } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::GetDirectoryEnabledColumnVisibility() { if (this->PresetList) { return this->PresetList->GetWidget()->GetColumnVisibility( this->GetDirectoryEnabledColumnIndex()); } return 0; } //---------------------------------------------------------------------------- void vtkKWDirectoryPresetSelector::SetMaximumDirectoryLength(int arg) { if (this->MaximumDirectoryLength == arg) { return; } this->MaximumDirectoryLength = arg; this->Modified(); } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::UpdatePresetRow(int id) { if (!this->Superclass::UpdatePresetRow(id)) { return 0; } int row = this->GetPresetRow(id); if (row < 0) { return 0; } vtkKWMultiColumnList *list = this->PresetList->GetWidget(); list->SetCellTextAsInt( row, this->GetDirectoryEnabledColumnIndex(), this->GetPresetDirectoryEnabled(id)); list->SetCellWindowCommandToCheckButton( row, this->GetDirectoryEnabledColumnIndex()); if (this->MaximumDirectoryLength > 0) { vtksys_stl::string cropped( vtksys::SystemTools::CropString( this->GetPresetDirectory(id), this->MaximumDirectoryLength)); list->SetCellText( row, this->GetDirectoryColumnIndex(), cropped.c_str()); } else { list->SetCellText( row, this->GetDirectoryColumnIndex(), this->GetPresetDirectory(id)); } return 1; } //--------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::AddDirectoryCallback() { if (!this->FileBrowserDialog->IsCreated()) { this->FileBrowserDialog->Create(); } this->FileBrowserDialog->MultipleSelectionOn(); this->FileBrowserDialog->SetFileName(NULL); this->FileBrowserDialog->Invoke(); vtksys_stl::list paths; int i; for (i = 0; i < this->FileBrowserDialog->GetNumberOfFileNames(); i++) { const char *filename = this->FileBrowserDialog->GetNthFileName(i); if (filename) { paths.push_back(filename); } } paths.sort(); vtksys_stl::list::reverse_iterator it = paths.rbegin(); vtksys_stl::list::reverse_iterator end = paths.rend(); int id = -1; for (; it != end; it++) { if (!this->UniqueDirectories || !this->HasPresetWithDirectory((*it).c_str())) { id = this->InsertPreset(-1); if (id >= 0) { this->SetPresetDirectory(id, (*it).c_str()); this->SetPresetDirectoryEnabled(id, 1); } } } this->SelectPreset(id); return id; } //--------------------------------------------------------------------------- const char* vtkKWDirectoryPresetSelector::PresetCellEditStartCallback( int row, int col, const char *text) { if (col == this->GetDirectoryColumnIndex()) { int id = this->GetIdOfPresetAtRow(row); vtksys_stl::string cell_contents(this->GetPresetDirectory(id)); vtkKWMultiColumnList *list = this->PresetList->GetWidget(); list->CancelEditing(); if (!this->FileBrowserDialog->IsCreated()) { this->FileBrowserDialog->Create(); } this->FileBrowserDialog->MultipleSelectionOff(); this->FileBrowserDialog->SetFileName(cell_contents.c_str()); this->FileBrowserDialog->SetLastPath(cell_contents.c_str()); this->FileBrowserDialog->Invoke(); const char *filename = this->FileBrowserDialog->GetFileName(); if (filename) { vtksys_stl::string validated_contents( list->EditEndCallback(NULL, row, col, filename)); if (strcmp(validated_contents.c_str(), cell_contents.c_str())) { this->SetPresetDirectory(id, validated_contents.c_str()); this->UpdatePresetRow(id); list->CellUpdatedCallback(); } } return NULL; } return text; } //--------------------------------------------------------------------------- const char* vtkKWDirectoryPresetSelector::PresetCellEditEndCallback( int, int, const char *text) { this->PresetList->GetWidget()->SeeColumn( this->GetDirectoryEnabledColumnIndex()); return text; } //--------------------------------------------------------------------------- void vtkKWDirectoryPresetSelector::PresetCellUpdatedCallback( int row, int col, const char *text) { int id = this->GetIdOfPresetAtRow(row); if (this->HasPreset(id)) { if (col == this->GetDirectoryEnabledColumnIndex()) { this->SetPresetDirectoryEnabled(id, atoi(text)); this->InvokePresetHasChangedCommand(id); return; } else if (col == this->GetDirectoryColumnIndex()) { // not use the text, it might be cropped this->InvokePresetHasChangedCommand(id); return; } } this->Superclass::PresetCellUpdatedCallback(row, col, text); } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::AddEnabledPresetDirectoriesFromDelimitedString( const char *from_str, const char from_delim) { if (!from_str || !*from_str) { return 0; } int count = 0; vtksys_stl::vector from_paths; vtksys::SystemTools::Split(from_str, from_paths, from_delim); vtksys_stl::vector::iterator from_it = from_paths.begin(); vtksys_stl::vector::iterator from_end = from_paths.end(); for (; from_it != from_end; from_it++) { const char *dir = (*from_it).c_str(); if (*dir && (!this->UniqueDirectories || !this->HasPresetWithDirectory(dir))) { int id = this->AddPreset(); if (id >= 0) { this->SetPresetDirectory(id, dir); this->SetPresetDirectoryEnabled(id, 1); ++count; } } } return count; } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::GetEnabledPresetDirectoriesToDelimitedString( char **to_str, const char to_delim) { if (!to_str) { return 0; } int count = 0; vtksys_ios::ostringstream to_stream; int i, nb_presets = this->GetNumberOfPresets(); for (i = 0; i < nb_presets; i++) { int id = this->GetIdOfNthPreset(i); if (id >= 0 && this->GetPresetDirectoryEnabled(id)) { const char *dir = this->GetPresetDirectory(id); if (dir && *dir) { ++count; if (to_stream.str().size()) { to_stream << to_delim; } to_stream << dir; } } } if (count) { *to_str = new char[to_stream.str().size() + 1]; strcpy(*to_str, to_stream.str().c_str()); } return count; } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::AddPresetDirectoriesFromDelimitedString( const char *from_str, const char from_delim) { if (!from_str || !*from_str) { return 0; } int count = 0; vtksys_stl::vector from_paths; vtksys::SystemTools::Split(from_str, from_paths, from_delim); vtksys_stl::vector::iterator from_it = from_paths.begin(); vtksys_stl::vector::iterator from_end = from_paths.end(); for (; from_it != from_end; from_it++) { vtksys_stl::string dir((*from_it)); ++from_it; if (from_it == from_end) { break; } int enabled = atoi((*from_it).c_str()); if (dir.size() && (!this->UniqueDirectories || !this->HasPresetWithDirectory(dir.c_str()))) { int id = this->AddPreset(); if (id >= 0) { this->SetPresetDirectory(id, dir.c_str()); this->SetPresetDirectoryEnabled(id, enabled); ++count; } } } return count; } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::GetPresetDirectoriesToDelimitedString( char **to_str, const char to_delim) { if (!to_str) { return 0; } int count = 0; vtksys_ios::ostringstream to_stream; int i, nb_presets = this->GetNumberOfPresets(); for (i = 0; i < nb_presets; i++) { int id = this->GetIdOfNthPreset(i); if (id >= 0) { const char *dir = this->GetPresetDirectory(id); if (dir && *dir) { ++count; if (to_stream.str().size()) { to_stream << to_delim; } to_stream << dir << to_delim << this->GetPresetDirectoryEnabled(id); } } } if (count) { *to_str = new char[to_stream.str().size() + 1]; strcpy(*to_str, to_stream.str().c_str()); } return count; } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::GetEnabledPresetDirectoriesFromPresetDirectories( char **to_str, const char to_delim, const char *from_str, const char from_delim) { if (!from_str || !*from_str || !to_str) { return 0; } int count = 0; vtksys_ios::ostringstream to_stream; vtksys_stl::vector from_paths; vtksys::SystemTools::Split(from_str, from_paths, from_delim); vtksys_stl::vector::iterator from_it = from_paths.begin(); vtksys_stl::vector::iterator from_end = from_paths.end(); for (; from_it != from_end; from_it++) { vtksys_stl::string dir((*from_it)); ++from_it; if (from_it == from_end) { break; } int enabled = atoi((*from_it).c_str()); if (dir.size() && enabled) { ++count; if (to_stream.str().size()) { to_stream << to_delim; } to_stream << dir; } } if (count) { *to_str = new char[to_stream.str().size() + 1]; strcpy(*to_str, to_stream.str().c_str()); } return count; } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::UpdatePresetDirectoriesFromEnabledPresetDirectories( char **update_str, const char update_delim, const char *from_str, const char from_delim) { if (!from_str || !*from_str || !update_str) { return 0; } int count = 0; vtksys_ios::ostringstream update_stream; vtksys_stl::vector update_paths; if (*update_str) { vtksys::SystemTools::Split(*update_str, update_paths, update_delim); } vtksys_stl::vector from_paths; vtksys::SystemTools::Split(from_str, from_paths, from_delim); vtksys_stl::vector::iterator update_it = update_paths.begin(); vtksys_stl::vector::iterator update_end = update_paths.end(); for (; update_it != update_end; update_it++) { vtksys_stl::string dir((*update_it)); ++update_it; if (update_it == update_end) { break; } int enabled = atoi((*update_it).c_str()); vtksys_stl::vector::iterator found = vtksys_stl::find( from_paths.begin(), from_paths.end(), dir); if (enabled) { // if we have an enabled path not found in the new list, skip it, it // should not be part of the updated list if (found == from_paths.end()) { ++count; continue; } // otherwise it was found, therefore enabled in both lists, so remove it // from the new list, since we do not need to add it at the end from_paths.erase(found); } else { // if we have a disabled path found in the new list, enable it instead if (found != from_paths.end()) { ++count; enabled = 1; } } if (update_stream.str().size()) { update_stream << update_delim; } update_stream << dir << update_delim << update_delim; } // Now add the remaining (as enabled) vtksys_stl::vector::iterator from_it = from_paths.begin(); vtksys_stl::vector::iterator from_end = from_paths.end(); for (; from_it != from_end; from_it++) { if (update_stream.str().size()) { update_stream << update_delim; } update_stream << (*from_it).c_str() << update_delim << (int)1; ++count; } if (count) { *update_str = new char[update_stream.str().size() + 1]; strcpy(*update_str, update_stream.str().c_str()); } return count; } //---------------------------------------------------------------------------- void vtkKWDirectoryPresetSelector::SetUniqueDirectories(int arg) { if (this->UniqueDirectories == arg) { return; } this->UniqueDirectories = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- int vtkKWDirectoryPresetSelector::HasPresetWithDirectory( const char *directory) { if (!directory || !*directory) { return 0; } int i, nb_presets = this->GetNumberOfPresets(); for (i = 0; i < nb_presets; i++) { int id = this->GetIdOfNthPreset(i); const char *dir = this->GetPresetDirectory(id); if (dir && !strcmp(dir, directory)) { return 1; } } return 0; } //---------------------------------------------------------------------------- void vtkKWDirectoryPresetSelector::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "FileBrowserDialog: " << this->FileBrowserDialog << endl; os << indent << "MaximumDirectoryLength: " << this->MaximumDirectoryLength << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWLabel.cxx0000644000175000017500000004104511153573110017614 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWLabel.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWLabel.h" #include "vtkObjectFactory.h" #include "vtkKWTkUtilities.h" #include "vtkKWIcon.h" #include "vtkKWOptions.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWLabel ); vtkCxxRevisionMacro(vtkKWLabel, "$Revision: 1.57 $"); //---------------------------------------------------------------------------- vtkKWLabel::vtkKWLabel() { this->Text = NULL; this->AdjustWrapLengthToWidth = 0; this->Icon = NULL; } //---------------------------------------------------------------------------- vtkKWLabel::~vtkKWLabel() { if (this->Text) { delete [] this->Text; this->Text = NULL; } if (this->Icon) { this->Icon->Delete(); this->Icon = NULL; } } //---------------------------------------------------------------------------- void vtkKWLabel::SetText(const char* _arg) { if (this->Text == NULL && _arg == NULL) { return; } if (this->Text && _arg && (!strcmp(this->Text, _arg))) { return; } if (this->Text) { delete [] this->Text; } if (_arg) { this->Text = new char[strlen(_arg) + 1]; strcpy(this->Text, _arg); } else { this->Text = NULL; } this->Modified(); this->UpdateText(); } //---------------------------------------------------------------------------- void vtkKWLabel::UpdateText() { if (this->IsCreated()) { // NULL is handled correctly as "" this->SetTextOption("-text", this->Text); // Whatever the label, -image always takes precedence, unless it's empty // so change it accordingly if (this->Text && *this->Text) { this->SetConfigurationOption("-image", NULL); } } } //---------------------------------------------------------------------------- void vtkKWLabel::CreateWidget() { // Call the superclass to set the appropriate flags then create manually if (!vtkKWWidget::CreateSpecificTkWidget(this, "label", "-justify left -highlightthickness 0")) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } this->UpdateText(); // Set bindings (if any) this->UpdateBindings(); // Icon if (this->Icon) { this->SetImageToPixels( this->Icon->GetData(), this->Icon->GetWidth(), this->Icon->GetHeight(), this->Icon->GetPixelSize()); } } //---------------------------------------------------------------------------- void vtkKWLabel::SetWidth(int width) { this->SetConfigurationOptionAsInt("-width", width); } //---------------------------------------------------------------------------- int vtkKWLabel::GetWidth() { return this->GetConfigurationOptionAsInt("-width"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetHeight(int height) { this->SetConfigurationOptionAsInt("-height", height); } //---------------------------------------------------------------------------- int vtkKWLabel::GetHeight() { return this->GetConfigurationOptionAsInt("-height"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetAdjustWrapLengthToWidth(int v) { if (this->AdjustWrapLengthToWidth == v) { return; } this->AdjustWrapLengthToWidth = v; this->Modified(); this->UpdateBindings(); } //---------------------------------------------------------------------------- void vtkKWLabel::AdjustWrapLengthToWidthCallback() { if (!this->IsCreated() || !this->AdjustWrapLengthToWidth) { return; } // Get the widget width and the current wraplength int wraplength = atoi(this->GetWrapLength()); int width; vtkKWTkUtilities::GetWidgetSize(this, &width, NULL); // Adjust the wraplength to width (within a tolerance so that it does // not put too much stress on the GUI). if (width < (wraplength - 5) || width > (wraplength + 5)) { this->SetConfigurationOptionAsInt("-wraplength", width - 5); } } //---------------------------------------------------------------------------- void vtkKWLabel::SetFont(const char *font) { this->SetConfigurationOption("-font", font); } //---------------------------------------------------------------------------- const char* vtkKWLabel::GetFont() { return this->GetConfigurationOption("-font"); } //---------------------------------------------------------------------------- void vtkKWLabel::UpdateBindings() { if (!this->IsCreated()) { return; } if (this->AdjustWrapLengthToWidth) { this->SetBinding("", this, "AdjustWrapLengthToWidthCallback"); } else { this->RemoveBinding(""); } } //---------------------------------------------------------------------------- void vtkKWLabel::SetJustification(int justification) { this->SetConfigurationOption( "-justify", vtkKWOptions::GetJustificationAsTkOptionValue(justification)); } void vtkKWLabel::SetJustificationToLeft() { this->SetJustification(vtkKWOptions::JustificationLeft); }; void vtkKWLabel::SetJustificationToCenter() { this->SetJustification(vtkKWOptions::JustificationCenter); }; void vtkKWLabel::SetJustificationToRight() { this->SetJustification(vtkKWOptions::JustificationRight); }; //---------------------------------------------------------------------------- int vtkKWLabel::GetJustification() { return vtkKWOptions::GetJustificationFromTkOptionValue( this->GetConfigurationOption("-justify")); } //---------------------------------------------------------------------------- void vtkKWLabel::GetBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWLabel::GetBackgroundColor() { return this->GetConfigurationOptionAsColor("-background"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- void vtkKWLabel::GetForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWLabel::GetForegroundColor() { return this->GetConfigurationOptionAsColor("-foreground"); } //---------------------------------------------------------------------------- void vtkKWLabel::GetDefaultForegroundColor(double *r, double *g, double *b) { this->GetDefaultConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWLabel::GetDefaultForegroundColor() { return this->GetDefaultConfigurationOptionAsColor("-foreground"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWLabel::SetHighlightThickness(int width) { this->SetConfigurationOptionAsInt("-highlightthickness", width); } //---------------------------------------------------------------------------- int vtkKWLabel::GetHighlightThickness() { return this->GetConfigurationOptionAsInt("-highlightthickness"); } //---------------------------------------------------------------------------- void vtkKWLabel::GetActiveBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWLabel::GetActiveBackgroundColor() { return this->GetConfigurationOptionAsColor("-activebackground"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetActiveBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWLabel::GetActiveForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-activeforeground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWLabel::GetActiveForegroundColor() { return this->GetConfigurationOptionAsColor("-activeforeground"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetActiveForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-activeforeground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWLabel::GetDisabledForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-disabledforeground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWLabel::GetDisabledForegroundColor() { return this->GetConfigurationOptionAsColor("-disabledforeground"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetDisabledForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-disabledforeground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWLabel::SetBorderWidth(int width) { this->SetConfigurationOptionAsInt("-bd", width); } //---------------------------------------------------------------------------- int vtkKWLabel::GetBorderWidth() { return this->GetConfigurationOptionAsInt("-bd"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetRelief(int relief) { this->SetConfigurationOption( "-relief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWLabel::SetReliefToRaised() { this->SetRelief(vtkKWOptions::ReliefRaised); }; void vtkKWLabel::SetReliefToSunken() { this->SetRelief(vtkKWOptions::ReliefSunken); }; void vtkKWLabel::SetReliefToFlat() { this->SetRelief(vtkKWOptions::ReliefFlat); }; void vtkKWLabel::SetReliefToRidge() { this->SetRelief(vtkKWOptions::ReliefRidge); }; void vtkKWLabel::SetReliefToSolid() { this->SetRelief(vtkKWOptions::ReliefSolid); }; void vtkKWLabel::SetReliefToGroove() { this->SetRelief(vtkKWOptions::ReliefGroove); }; //---------------------------------------------------------------------------- int vtkKWLabel::GetRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-relief")); } //---------------------------------------------------------------------------- void vtkKWLabel::SetPadX(int arg) { this->SetConfigurationOptionAsInt("-padx", arg); } //---------------------------------------------------------------------------- int vtkKWLabel::GetPadX() { return this->GetConfigurationOptionAsInt("-padx"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetPadY(int arg) { this->SetConfigurationOptionAsInt("-pady", arg); } //---------------------------------------------------------------------------- int vtkKWLabel::GetPadY() { return this->GetConfigurationOptionAsInt("-pady"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetWrapLength(const char *wraplength) { this->SetConfigurationOption("-wraplength", wraplength); } //---------------------------------------------------------------------------- const char* vtkKWLabel::GetWrapLength() { return this->GetConfigurationOption("-wraplength"); } //---------------------------------------------------------------------------- void vtkKWLabel::SetAnchor(int anchor) { this->SetConfigurationOption( "-anchor", vtkKWOptions::GetAnchorAsTkOptionValue(anchor)); } void vtkKWLabel::SetAnchorToNorth() { this->SetAnchor(vtkKWOptions::AnchorNorth); }; void vtkKWLabel::SetAnchorToNorthEast() { this->SetAnchor(vtkKWOptions::AnchorNorthEast); }; void vtkKWLabel::SetAnchorToEast() { this->SetAnchor(vtkKWOptions::AnchorEast); }; void vtkKWLabel::SetAnchorToSouthEast() { this->SetAnchor(vtkKWOptions::AnchorSouthEast); }; void vtkKWLabel::SetAnchorToSouth() { this->SetAnchor(vtkKWOptions::AnchorSouth); }; void vtkKWLabel::SetAnchorToSouthWest() { this->SetAnchor(vtkKWOptions::AnchorSouthWest); }; void vtkKWLabel::SetAnchorToWest() { this->SetAnchor(vtkKWOptions::AnchorWest); }; void vtkKWLabel::SetAnchorToNorthWest() { this->SetAnchor(vtkKWOptions::AnchorNorthWest); }; void vtkKWLabel::SetAnchorToCenter() { this->SetAnchor(vtkKWOptions::AnchorCenter); }; //---------------------------------------------------------------------------- int vtkKWLabel::GetAnchor() { return vtkKWOptions::GetAnchorFromTkOptionValue( this->GetConfigurationOption("-anchor")); } //---------------------------------------------------------------------------- void vtkKWLabel::SetImageToPredefinedIcon(int icon_index) { if (!this->Icon) { this->Icon = vtkKWIcon::New(); } this->Icon->SetImage(icon_index); this->SetImageToIcon(this->Icon); } //---------------------------------------------------------------------------- void vtkKWLabel::SetImageToIcon(vtkKWIcon* icon) { if (this->IsCreated()) { if (icon) { this->SetImageToPixels( icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize()); } else { this->SetConfigurationOption("-image", ""); } } else { if (icon) { if (!this->Icon) { this->Icon = vtkKWIcon::New(); } this->Icon->SetImage(icon); } else { if (this->Icon) { this->Icon->SetImage((vtkKWIcon*)NULL); } } } } //---------------------------------------------------------------------------- void vtkKWLabel::SetImageToPixels(const unsigned char* pixels, int width, int height, int pixel_size, unsigned long buffer_length) { vtkKWTkUtilities::SetImageOptionToPixels( this, pixels, width, height, pixel_size, buffer_length); } //---------------------------------------------------------------------------- void vtkKWLabel::SetCompoundMode(int mode) { this->SetConfigurationOption( "-compound", vtkKWOptions::GetCompoundModeAsTkOptionValue(mode)); } void vtkKWLabel::SetCompoundModeToNone() { this->SetCompoundMode(vtkKWOptions::CompoundModeNone); }; void vtkKWLabel::SetCompoundModeToLeft() { this->SetCompoundMode(vtkKWOptions::CompoundModeLeft); }; void vtkKWLabel::SetCompoundModeToCenter() { this->SetCompoundMode(vtkKWOptions::CompoundModeCenter); }; void vtkKWLabel::SetCompoundModeToRight() { this->SetCompoundMode(vtkKWOptions::CompoundModeRight); }; void vtkKWLabel::SetCompoundModeToTop() { this->SetCompoundMode(vtkKWOptions::CompoundModeTop); }; void vtkKWLabel::SetCompoundModeToBottom() { this->SetCompoundMode(vtkKWOptions::CompoundModeBottom); }; //---------------------------------------------------------------------------- int vtkKWLabel::GetCompoundMode() { return vtkKWOptions::GetCompoundModeFromTkOptionValue( this->GetConfigurationOption("-compound")); } //--------------------------------------------------------------------------- void vtkKWLabel::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->SetState(this->GetEnabled()); } //---------------------------------------------------------------------------- void vtkKWLabel::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "AdjustWrapLengthToWidth: " << (this->AdjustWrapLengthToWidth ? "On" : "Off") << endl; os << indent << "Text: "; if (this->Text) { os << this->Text << endl; } else { os << "(none)" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWWidgetWithLabel.h0000644000175000017500000001422110454520665021247 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetWithLabel.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWWidgetWithLabel - an abstract class widget with a label // .SECTION Description // This class implements a superclass for composite widgets that need // to associate a label (vtkKWLabel) to a widget (say, a // vtkKWEntry for example). This superclass provides a GetLabel() method // to retrieve the internal vtkKWLabel. Each subclass provides a GetWidget() // method that can be used to retrieve the internal widget associated to // to this label in the composite (say, a vtkKWEntry). // // Be aware that most subclasses of vtkKWWidgetWithLabel are // generated automatically out of the vtkKWWidgetWithLabelSubclass template // located in the Templates directory. Therefore, even though the source code // for those vtkKWWidgetWithLabel subclasses does not exist in the KWWidgets // repository, they are still generated automatically and documented in the // API online; check the vtkKWWidgetWithLabel API online for its subclasses, // as well as the \subpage kwwidgets_autogenerated_page page. // Classes related to the same template can be // found in the \ref kwwidgets_autogenerated_widget_with_label_group section. // .SECTION See Also // vtkKWCheckButtonWithLabel vtkKWEntryWithLabel vtkKWComboBoxWithLabel vtkKWMenuButtonWithLabel vtkKWMessageWithLabel vtkKWPushButtonWithLabel vtkKWScaleWithLabel vtkKWSpinBoxWithLabel #ifndef __vtkKWWidgetWithLabel_h #define __vtkKWWidgetWithLabel_h #include "vtkKWCompositeWidget.h" class vtkKWLabel; class KWWidgets_EXPORT vtkKWWidgetWithLabel : public vtkKWCompositeWidget { public: static vtkKWWidgetWithLabel* New(); vtkTypeRevisionMacro(vtkKWWidgetWithLabel, vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the internal label visibility (On by default). // IMPORTANT: if you know you may not show the label, try to // set that flag as early as possible (ideally, before calling Create()) // in order to lower the footprint of the widget: the label will not be // allocated and created if there is no need to show it. // Later on, you can still use that option to show the label: it will be // allocated and created on the fly. virtual void SetLabelVisibility(int); vtkBooleanMacro(LabelVisibility, int); vtkGetMacro(LabelVisibility, int); // Description: // Get the internal label. // IMPORTANT: the internal label is "lazy created", i.e. it is neither // allocated nor created until GetLabel() is called. This allows // for a lower footprint and faster UI startup. Therefore, do *not* use // GetLabel() to check if the label exists, as it will automatically // allocate the label. Use HasLabel() instead. virtual vtkKWLabel* GetLabel(); virtual int HasLabel(); // Description: // Set/Get the contents label. // IMPORTANT: SetLabelText will create the label on the fly, use it only if // you are confident that you will indeed display the label. virtual void SetLabelText(const char *); const char* GetLabelText(); // Description: // Set/Get the label width. // IMPORTANT: this method will create the label on the fly, use it only if // you are confident that you will indeed display the label. virtual void SetLabelWidth(int width); virtual int GetLabelWidth(); // Description: // If supported, set the label position in regards to the rest of // the composite widget. Check the subclass for more information about // what the Default position is, and if specific positions are supported. //BTX enum { LabelPositionDefault = 0, LabelPositionTop, LabelPositionBottom, LabelPositionLeft, LabelPositionRight }; //ETX virtual void SetLabelPosition(int); vtkGetMacro(LabelPosition, int); virtual void SetLabelPositionToDefault() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionDefault); }; virtual void SetLabelPositionToTop() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionTop); }; virtual void SetLabelPositionToBottom() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionBottom); }; virtual void SetLabelPositionToLeft() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionLeft); }; virtual void SetLabelPositionToRight() { this->SetLabelPosition(vtkKWWidgetWithLabel::LabelPositionRight); }; // Description: // Set the string that enables balloon help for this widget. // Override to pass down to children. virtual void SetBalloonHelpString(const char *str); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); protected: vtkKWWidgetWithLabel(); ~vtkKWWidgetWithLabel(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Label visibility int LabelVisibility; // Description: // Label position int LabelPosition; // Description: // Create the label virtual void CreateLabel(); // Description: // Pack or repack the widget. To be implemented by subclasses. virtual void Pack() {}; private: // Description: // Internal label // In 'private:' to allow lazy evaluation. GetLabel() will create the // label if it does not exist. This allow the object to remain lightweight. vtkKWLabel *Label; vtkKWWidgetWithLabel(const vtkKWWidgetWithLabel&); // Not implemented void operator=(const vtkKWWidgetWithLabel&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWColorSwatchesWidget.h0000644000175000017500000001321111220763055022144 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWColorSwatchesWidget.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWColorSwatchesWidget - a color swatches widget. // .SECTION Description // This class displays a list of color swatches. // Different color swatches collections can be created independently. // .SECTION See Also // vtkKWColorPickerWidget #ifndef __vtkKWColorSwatchesWidget_h #define __vtkKWColorSwatchesWidget_h #include "vtkKWCompositeWidget.h" class vtkKWColorSwatchesWidgetInternals; class vtkKWFrameSet; class vtkKWColorPresetSelector; class KWWidgets_EXPORT vtkKWColorSwatchesWidget : public vtkKWCompositeWidget { public: static vtkKWColorSwatchesWidget* New(); vtkTypeRevisionMacro(vtkKWColorSwatchesWidget,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Add a swatches collection (the name can not be empty) // Return unique ID (>= 0) of the collection, or -1 on error. virtual int AddCollection(const char *name); // Description: // Remove a swatches collection given its ID, or all collections // Return 1 on success, 0 otherwise virtual int RemoveCollection(int collection_id); virtual void RemoveAllCollections(); // Description: // Get the unique ID of a swatches collection given its name // Return -1 on error. virtual int GetCollectionId(const char *name); // Description: // Add a swatch to a collection, given the unique ID of the collection, // the name of the swatch (can be empty) and its RGB value. // Return 1 on success, 0 on error. virtual int AddRGBSwatch( int collection_id, const char *name, double rgb[3]); virtual int AddRGBSwatch( int collection_id, const char *name, double r, double g, double b); // Description: // Set/Get the swatches representation. //BTX enum { RepresentationFrames = 0, RepresentationList = 1 }; //ETX virtual void SetSwatchesRepresentation(int); vtkGetMacro(SwatchesRepresentation, int); virtual void SetSwatchesRepresentationToFrames(); virtual void SetSwatchesRepresentationToList(); // Description: // Set/Get the swatch size in pixels. // Only relevant if SwatchesRepresentation is RepresentationFrames. vtkGetMacro(SwatchSize, int); virtual void SetSwatchSize(int); // Description: // Set/Get the maximum number of swatches packed horizontally (per row). // Only relevant if SwatchesRepresentation is RepresentationFrames. virtual void SetMaximumNumberOfSwatchesPerRow(int); virtual int GetMaximumNumberOfSwatchesPerRow(); // Description: // Set/Get the padding between each swatch. // Only relevant if SwatchesRepresentation is RepresentationFrames. virtual void SetSwatchesPadding(int); virtual int GetSwatchesPadding(); // Description: // Get the internal color swatches preset list virtual vtkKWColorPresetSelector* GetSwatchesColorPresetSelector(); // Description: // Create the default collections virtual void AddDefaultCollections(); // Description: // Specifies a command to associate with the widget. This command is // invoked when a swatch is selected. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - swatch rgb value: double r, double g, double b virtual void SetSwatchSelectedCommand(vtkObject *object, const char *method); // Description: // Callbacks. Internal, do not use. virtual void SwatchSelectedCallback(double r, double g, double b); virtual void CollectionSelectedCallback(const char*); virtual void PopulateCollectionsCallback(); virtual void PopulateSwatchesCallback(); virtual void SwatchesColorPresetApplyCallback(int id); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); protected: vtkKWColorSwatchesWidget(); ~vtkKWColorSwatchesWidget(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Callbacks. Internal, do not use. char *SwatchSelectedCommand; virtual void InvokeSwatchSelectedCommand(double r, double g, double b); // Description: // Populate the swatches frame and collectio combo virtual void PopulateCollections(); virtual void PopulateSwatches(); virtual void PopulateSwatchesAsFrames(); virtual void PopulateSwatchesAsList(); virtual void SchedulePopulateCollections(); virtual void SchedulePopulateSwatches(); // Description: // Pack virtual void Pack(); int SwatchSize; int SwatchesRepresentation; vtkKWColorSwatchesWidgetInternals *Internals; private: vtkKWColorSwatchesWidget(const vtkKWColorSwatchesWidget&); // Not implemented void operator=(const vtkKWColorSwatchesWidget&); // Not Implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWApplication.h0000644000175000017500000006475411305012214020471 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWApplication.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWApplication - an application class // .SECTION Description // vtkKWApplication is the overall class that represents the entire // application. It is also responsible for managing the vtkKWWindowBase(s) // associated to the application. #ifndef __vtkKWApplication_h #define __vtkKWApplication_h #include "vtkKWObject.h" #include "vtkTcl.h" // Needed for Tcl_Interp #include "vtkTk.h" // Needed for Tk_Window class vtkKWApplicationInternals; class vtkKWBalloonHelpManager; class vtkKWColorPickerDialog; class vtkKWLabel; class vtkKWLogDialog; class vtkKWMessageDialog; class vtkKWOptionDataBase; class vtkKWRegistryHelper; class vtkKWSplashScreen; class vtkKWTclInteractor; class vtkKWTextWithScrollbars; class vtkKWTheme; class vtkKWTopLevel; class vtkKWWidget; class vtkKWWindowBase; class KWWidgets_EXPORT vtkKWApplication : public vtkKWObject { public: static vtkKWApplication* New(); vtkTypeRevisionMacro(vtkKWApplication,vtkKWObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Override vtkKWObject's method. A vtkKWObject is associated to a // vtkKWApplication. Even if vtkKWApplication is a subclass of // vtkKWObject, an application's application is actually 'itself', // and it can not be reset. virtual vtkKWApplication *GetApplication() { return this; } virtual void SetApplication (vtkKWApplication*); // Description: // Start running the application, with or without arguments, and enter the // event loop. The application will exit the event loop once every // windows has been closed. // As a convenience, if one (or more) window has been added to the // application (using AddWindow()), and none of them has been mapped // on the screen yet, the application will automatically display the first // window by calling its Display() method. virtual void Start(); virtual void Start(int argc, char *argv[]); // Description: // This method is invoked when the user exits the app // Return 1 if the app exited successfully, 0 otherwise (for example, // if some dialogs are still up, or the user did not confirm, etc). virtual int Exit(); // Description: // Set/Get if a confirmation dialog should be displayed before the // application exits. vtkSetMacro(PromptBeforeExit, int); vtkGetMacro(PromptBeforeExit, int); vtkBooleanMacro(PromptBeforeExit, int); // Description: // Set/Get the value returned by the application at exit. // This can be used from scripts to set an error status vtkSetMacro(ExitStatus, int); vtkGetMacro(ExitStatus, int); // Description: // Get when application is exiting (set to 1 as soon as Exit() is called). vtkGetMacro(InExit, int); // Description: // Set/Get if the error log should be sent.emailed before application exits. vtkSetMacro(SendErrorLogBeforeExit, int); vtkGetMacro(SendErrorLogBeforeExit, int); vtkBooleanMacro(SendErrorLogBeforeExit, int); // Description: // Add, remove (i.e. close), or retrieve a window to/from this application. // Note that AddWindow() will increase the reference count of the window // that is added, RemoveWindow() will decrease it. Once the last window is // closed, Exit() is called. // Return 1 if successful, 0 otherwise virtual int AddWindow(vtkKWWindowBase *w); virtual int RemoveWindow(vtkKWWindowBase *); virtual vtkKWWindowBase* GetNthWindow(int rank); // Description: // Get the number of windows, the number of windows mapped on screen. virtual int GetNumberOfWindows(); virtual int GetNumberOfWindowsMapped(); // Description: // Set/Get the application name. // Also check the LimitedEditionModeName variable if you plan on running // the application in limited edition mode. vtkSetStringMacro(Name); vtkGetStringMacro(Name); // Description: // Get the major and minor application version. vtkSetMacro(MajorVersion, int); vtkGetMacro(MajorVersion, int); vtkSetMacro(MinorVersion, int); vtkGetMacro(MinorVersion, int); // Description: // Set/Get the application version name - this usually is the application // name postfixed with the version number (major/minor). // If it has not been set, it will use the value of Name and append // the major/minor version. vtkSetStringMacro(VersionName); virtual const char* GetVersionName(); // Description: // Set/Get the application release name - this is the release of the // application version (if any), typically: beta1, beta2, final, patch1, etc. vtkSetStringMacro(ReleaseName); vtkGetStringMacro(ReleaseName); // Description: // Get the "pretty" name of the application. // This is typically used for windows or dialogs title, About boxes, etc. // It combines the application name, its version, and other relevant // informations (like its limited edition mode). virtual const char* GetPrettyName(); // Description: // Get the most recent version this application was ever launched, if known. // Each time this application is closed, its version is automatically saved // to the registry (provided that this version is the most recent). // Use this method to retrieve which most recent version was ever launched // by your user. This can be used by newer application to detect if some // migration is needed to upgrade from an older version. // Returns 0 if no most recent version was ever recorded, or if it can not // be parsed. virtual int GetMostRecentVersionLaunched(int *major, int *minor); // Descrition: // Set/Get if the application is running in limited edition mode. // This can be used throughout the whole UI to enable or disable // features on the fly. Make sure it is *not* wrapped ! //BTX virtual void SetLimitedEditionMode(int arg); vtkBooleanMacro(LimitedEditionMode, int); vtkGetMacro(LimitedEditionMode, int); //ETX // Descrition: // Return the limited edition mode and optionally warn the user ; // if the limited edition mode is true, display a popup warning stating // that 'feature' is not available in this mode. virtual int GetLimitedEditionModeAndWarn(const char *feature); // Descrition: // Set/Get the name of the application when it runs in limited edition mode. // This is used by GetPrettyName() for example, instead of the Name variable. // If it has not been set, it will use the value of Name and append // the "Limited Edition" to it. vtkSetStringMacro(LimitedEditionModeName); virtual const char *GetLimitedEditionModeName(); // Descrition: // Set/Get if the application is running in release/production mode. // This should be set as soon as possible, before creating any UI. // The release mode (as opposed to debug/development mode) can be used // to prevent the output window from showing up, to disable the support of // specific file formats that should only be used during development, to // remove the Tcl Command Prompt, etc. //BTX virtual void SetReleaseMode(int); vtkBooleanMacro(ReleaseMode, int); vtkGetMacro(ReleaseMode, int); //ETX // Description: // Set/Get the directory in which the application is supposed // to be installed. virtual const char *GetInstallationDirectory(); vtkSetStringMacro(InstallationDirectory); // Description: // Set/Get the directory in which the application can store // user data. // On Windows, this is usually: // C:\Documents and Settings\\My Documents\NameOfTheApplication // On Unix/MacOSX, this is usually: // $HOME/.NameOfTheApplication (ex: /users/barre/.VolView) virtual const char* GetUserDataDirectory(); vtkSetStringMacro(UserDataDirectory); // Description: // Load and evaluate a Tcl script from a file. // Return 1 if successful, 0 otherwise virtual int LoadScript(const char* filename); // Description: // Run an AppleScript provided as a string (don't forget to escape the // quotes). Only on Apple platforms. // Return 1 if successful, 0 otherwise #ifdef __APPLE__ //BTX static int RunAppleScript(const char *text); //ETX #endif // Description: // Set/Get the "exit after load script" flag. If this flag is set, then // the application will automatically Exit() after a call to LoadScript(). // This is mainly used for testing purposes. Even though a Tcl script // can end with an explicit call to Exit on the application Tcl object, // this call may never be reached it the script contains an error. Setting // this variable will make sure the application will exit anyway. vtkSetClampMacro(ExitAfterLoadScript, int, 0, 1); vtkBooleanMacro(ExitAfterLoadScript, int); vtkGetMacro(ExitAfterLoadScript, int); // Description: // Set/Get the print quality. vtkGetMacro(PrintTargetDPI, double); vtkSetMacro(PrintTargetDPI, double); // Description: // Get the Registry object. //BTX vtkKWRegistryHelper *GetRegistryHelper(); //ETX // Description: // Set/Get the registry application version name - this usually is the // application name postfixed with the *major* version number. The minor // version is not used so that application settings are maintained // between minor version changes. // It is typically used as the master key to store registry settings // (ex: VolView 3, ParaView1, etc.) vtkSetStringMacro(RegistryVersionName); virtual const char* GetRegistryVersionName(); // Description: // Set/Get the current registry level. // When setting/retrieving a value in/from the registry a 'level' has // to be provided as part of the parameters. If this level is greater // than the current registry level, the operation will be ignored. // Set the registry level to -1 means to ignore all the registry operations. vtkSetClampMacro(RegistryLevel, int, -1, 10); vtkGetMacro(RegistryLevel, int); // Description: // Set/Get/Delete/Query a registry value for the application. // When storing multiple arguments, separate them with spaces. // Note that if the 'level' is greater than the current registry level, // the operation will be ignored. //BTX virtual int SetRegistryValue( int level, const char* subkey, const char* key, const char* format, ...); //ETX virtual int GetRegistryValue( int level, const char* subkey, const char* key, char* value); virtual int DeleteRegistryValue( int level, const char* subkey, const char* key); virtual int HasRegistryValue( int level, const char* subkey, const char* key); // Description: // Retrieve a value from the registry and convert it to a type // (boolean, float, int). // Return 0 if the value was not found. // For GetBooleanRegistryValue(), perform a boolean check of the value in // the registry. If the value at the key is equal to 'trueval', then return // true, otherwise return false. virtual float GetFloatRegistryValue( int level, const char* subkey, const char* key); virtual int GetIntRegistryValue( int level, const char* subkey, const char* key); virtual int GetBooleanRegistryValue( int level, const char* subkey, const char* key, const char* trueval); // Description: // Save/retrieve color to/from the registry. // If the color does not exist, it will retrieve -1, -1 ,-1 and return 0 // (1 if success). // Note that the subkey used here is "Colors". virtual void SaveColorRegistryValue( int level, const char *key, double rgb[3]); virtual int RetrieveColorRegistryValue( int level, const char *key, double rgb[3]); // Descrition: // Save/Retrieve the application settings to/from registry. // Do not call that method before the application name is known and the // proper registry level set (if any). virtual void RestoreApplicationSettingsFromRegistry(); virtual void SaveApplicationSettingsToRegistry(); // Description: // Get the database option object. //BTX vtkKWOptionDataBase *GetOptionDataBase(); //ETX // Description: // Set/Get if this application supports a splash screen vtkSetMacro(SupportSplashScreen, int); vtkGetMacro(SupportSplashScreen, int); vtkBooleanMacro(SupportSplashScreen, int); // Description: // Set/Get if this application should show the splash screen at startup vtkGetMacro(SplashScreenVisibility, int); vtkSetMacro(SplashScreenVisibility, int); vtkBooleanMacro(SplashScreenVisibility, int); // Description: // Retrieve the splash screen object // This will also create the splash screen widget itself. virtual vtkKWSplashScreen* GetSplashScreen(); // Description: // Set/Get if the user interface geometry should be saved (to the registry, // for example). // This is more like a hint that many widgets can query to check if // they should save their own geometry (and restore it on startup). vtkGetMacro(SaveUserInterfaceGeometry, int); vtkSetMacro(SaveUserInterfaceGeometry, int); vtkBooleanMacro(SaveUserInterfaceGeometry, int); // Description: // Get/Set the internal character encoding of the application. virtual void SetCharacterEncoding(int val); vtkGetMacro(CharacterEncoding, int); // Description: // Get if we have some logic to check for application update online and // perform that check. virtual int HasCheckForUpdates(); virtual void CheckForUpdates(); // Description: // Get/Set the current theme. This will install the theme automatically. virtual void SetTheme(vtkKWTheme *theme); vtkGetObjectMacro(Theme, vtkKWTheme); // Description: // Get if we have some logic to report feedback by email and // email that feedback. // Set/Get the email address to send that feedback to. virtual int CanEmailFeedback(); virtual void EmailFeedback(); vtkSetStringMacro(EmailFeedbackAddress); vtkGetStringMacro(EmailFeedbackAddress); // Description: // Send email (win32 only for the moment, use MAPI). virtual int SendEmail( const char *to, const char *subject, const char *message, const char *attachment_filename, const char *extra_error_msg = NULL); // Description: // Add email feedback body and subject to output stream. // Override this function in subclasses (and/or call the superclass) to // add more information. virtual void AddEmailFeedbackBody(ostream &); virtual void AddEmailFeedbackSubject(ostream &); // Description: // Display the on-line help for this application. // Optionally provide a master window this dialog should be the slave of. virtual void DisplayHelpDialog(vtkKWTopLevel *master); // Description: // Set/Get the help starting page. // If set to a CHM/HTML page, it will be opened automatically on Windows. vtkGetStringMacro(HelpDialogStartingPage); vtkSetStringMacro(HelpDialogStartingPage); // Description: // Display the on-line tutorial for this application. // Optionally provide a master window this dialog should be the slave of. virtual void DisplayTutorial(vtkKWTopLevel *master); // Description: // Set/Get the tutorial starting page. // If set to a CHM/HTML page, it will be opened automatically on Windows. vtkGetStringMacro(TutorialStartingPage); vtkSetStringMacro(TutorialStartingPage); // Description: // Display the about dialog for this application. // Optionally provide a master window this dialog should be the slave of. virtual void DisplayAboutDialog(vtkKWTopLevel *master); // Description: // Return the Balloon Help helper object. virtual vtkKWBalloonHelpManager *GetBalloonHelpManager(); // Description: // Return the appplication-wide color picker dialog. Redefine this method // in your application sub-class to provide a customized color picker. virtual vtkKWColorPickerDialog *GetColorPickerDialog(); // Description: // Evaluate Tcl script/code and perform argument substitutions. //BTX virtual const char* Script(const char* format, ...); int EvaluateBooleanExpression(const char* format, ...); //ETX // Description: // Get the interpreter being used by this application static Tcl_Interp *GetMainInterp(); // Description: // Initialize Tcl/Tk // Return NULL on error (eventually provides an ostream where detailed // error messages will be stored). // One method takes argc/argv and will create an internal Tcl interpreter // on the fly, the other takes a Tcl interpreter and uses it afterward // (this is mainly intended for initialization as a Tcl package) //BTX static Tcl_Interp *InitializeTcl(int argc, char *argv[], ostream *err = 0); static Tcl_Interp *InitializeTcl(Tcl_Interp *interp, ostream *err = 0); //ETX // Description: // Call RegisterDialogUp to notify the application that a modal dialog is up, // and UnRegisterDialogUp when it is not anymore. IsDialogUp will return // if any dialog is up. // The parameter to pass is a pointer to the dialog/toplevel/widget that is // being registered/unregistered. If there is no such widget (say, if you // are calling a builtin Tk function that creates and pops-up a dialog), pass // the adress of the class that is invoking that call. // This is used to help preventing a window or an // application to exit while a dialog is still up. This is usually not // a problem on Win32, since a modal dialog will prevent the user from // interacting with the window and exit it, but this is not the case for // other operating system where the window manager is independent from the // window contents itself. In any case, inheriting from a vtkKWTopLevel // or vtkKWDialog should take care of calling this function for you. virtual void RegisterDialogUp(vtkKWWidget *ptr); virtual void UnRegisterDialogUp(vtkKWWidget *ptr); virtual int IsDialogUp(); // Description: // Open a link (media). // On Win32, use ShellExecute to trigger the default viewers. int OpenLink(const char *link); // Description: // Explore link. // On Win32, this will launch the Explorer, open it in the directory // of the link, and eventually select that link itself in the directory. int ExploreLink(const char *link); // Description: // Process/update pending events. This method brings the // application "up to date" by entering the event loop repeatedly until // all pending events (including idle callbacks) have been processed. virtual void ProcessPendingEvents(); // Description: // Process/update idle tasks. This causes operations that are normally // deferred, such as display updates and window layout calculations, to be // performed immediately. virtual void ProcessIdleTasks(); // Description: // Install the Tcl background error callback. Individual applications // can define a background error command if they wish to handle background // errors. A background error is one that occurs in an event handler or // some other command that didn't originate with the application. For // example, if an error occurs while executing a command specified with // asynchronously. The default implementation is to feed the Tcl error // message to a vtkErrorMacro. virtual void InstallTclBgErrorCallback(); // Description: // Popup a warning/error/information/debug message. virtual void WarningMessage(const char* message); virtual void ErrorMessage(const char* message); virtual void DebugMessage(const char* message); virtual void InformationMessage(const char* message); // Description: // Display the warning/error/information/debug message log dialog. // Optionally provide a master window this dialog should be the slave of. virtual void DisplayLogDialog(vtkKWTopLevel *master); virtual vtkKWLogDialog* GetLogDialog(); // Description: // Get/display the tcl interactor. // Optionally provide a master window this dialog should be the slave of. virtual void DisplayTclInteractor(vtkKWTopLevel *master); virtual vtkKWTclInteractor* GetTclInteractor(); // Description: // Add system information to a stream. // Will be used to report system info in the About dialog, or the Feedback // email... virtual void AddSystemInformation(ostream &); // Description: // Some constants //BTX static const char *ExitDialogName; static const char *SendErrorLogDialogName; static const char *BalloonHelpVisibilityRegKey; static const char *SaveUserInterfaceGeometryRegKey; static const char *SplashScreenVisibilityRegKey; static const char *PrintTargetDPIRegKey; static const char *MostRecentVersionLaunchedRegKey; //ETX // Description: // Callbacks. Internal, do not use. virtual void TclBgErrorCallback(const char* message); // Description: // Put a string into the environment of the form var=value static int PutEnv(const char* value); protected: vtkKWApplication(); ~vtkKWApplication(); // Description: // Do one tcl event and enter the event loop, allowing the application // interface to actually run. virtual void DoOneTclEvent(); // Description: // User data directory char *UserDataDirectory; char *EmailFeedbackAddress; // Description: // Create email message dialog (in case of error). virtual void CreateEmailMessageDialog( vtkKWMessageDialog *dlg, const char *to, const char *subject, const char *message, const char *attachment_filename); // Description: // Help starting page char *HelpDialogStartingPage; // Description: // Tutorial starting page char *TutorialStartingPage; // Description: // Display an on-line help page. // Used by DisplayHelpDialog() and DisplayTutorial() // Optionally provide a master window this dialog should be the slave of. virtual void DisplayHelpPage(const char *page, vtkKWTopLevel *master); // Description: // Display the exit dialog. // Optionally provide a master window this dialog should be the slave of. // Return 1 if the user wants to exit, 0 otherwise virtual int DisplayExitDialog(vtkKWTopLevel *master); // Description: // Value that is set after exit (status), flag stating that // Exit was called, flag stating if application should exit after load script int ExitStatus; int InExit; int ExitAfterLoadScript; int PromptBeforeExit; int SendErrorLogBeforeExit; // Description: // Send the error log (prompt first). virtual int SendErrorLog(); // Description: // Number of dialog that are up. See Un/RegisterDialogUp(). int DialogUp; // Description: // Registry level. If a call to Set/GetRegistryValue uses a level above // this ivar, the operation is ignored. int RegistryLevel; // Description: // Flag stating if application supports splash screen, and shows it int SupportSplashScreen; int SplashScreenVisibility; virtual void CreateSplashScreen() {}; // Description: // Flag stating if the UI geometry should be saved before exiting int SaveUserInterfaceGeometry; // Description: // About dialog, add text and copyrights to the about dialog. // Override this function in subclasses (and/or call the superclass) to // add more information. virtual void ConfigureAboutDialog(); virtual void AddAboutText(ostream &); virtual void AddAboutCopyrights(ostream &); vtkKWMessageDialog *AboutDialog; vtkKWLabel *AboutDialogImage; vtkKWTextWithScrollbars *AboutRuntimeInfo; // Description: // Character encoding (is passed to Tcl) int CharacterEncoding; // Description: // Print DPI double PrintTargetDPI; // Description: // Current theme vtkKWTheme *Theme; // Description: // Give a change to the application to parse the command-line arguments // and set some variables accordingly. Subclasses that do not intend // to call their super's Start(argc, argv) should make sure they // call their super's ParseCommandLineArguments. virtual void ParseCommandLineArguments(int argc, char *argv[]); // Description: // Check for an argument (example: --foo, /C, -bar, etc). // Return VTK_OK if found and set 'index' to the position of the // argument in argv[]. // Return VTK_ERROR if not found. static int CheckForArgument( int argc, char* argv[], const char *arg, int &index); // Description: // Check for a valued argument (example: --foo=bar, /C=bar, -bar=foo, etc). // Return VTK_OK if found and set 'index' to the position of the // argument in argv[], 'value_pos' to the position right after the '=' // in that argument. // Return VTK_ERROR if not found. static int CheckForValuedArgument( int argc, char* argv[], const char *arg, int &index, int &value_pos); // Description: // Try to find the path to the online updater (for example, WiseUpdt.exe) // and output that path to the ostream passed as parameter. virtual int GetCheckForUpdatesPath(ostream &path); // Description: // Deallocate/delete/reparent some internal objects in order to solve // reference loops that would prevent this instance from being deleted. virtual void PrepareForDelete(); // PIMPL Encapsulation for STL containers vtkKWApplicationInternals *Internals; // Description: // Initialize VTK's Tcl packages // Return NULL on error (eventually provides an ostream where detailed // error messages will be stored). //BTX static Tcl_Interp *InitializeVTK(Tcl_Interp *interp, ostream *err = 0); //ETX // Description: // Log dialog vtkKWLogDialog *LogDialog; virtual int CreateLogDialog(); // Description: // Install/restore output window virtual void InstallOutputWindow(); virtual void RestoreOutputWindow(); // Description: // Tcl interactor. vtkKWTclInteractor *TclInteractor; // Description: // Color picker dialog vtkKWColorPickerDialog *ColorPickerDialog; private: vtkKWRegistryHelper *RegistryHelper; vtkKWOptionDataBase *OptionDataBase; vtkKWSplashScreen *SplashScreen; vtkKWBalloonHelpManager *BalloonHelpManager; // Description: // Application name and version char *Name; char *VersionName; char *ReleaseName; int MajorVersion; int MinorVersion; char *PrettyName; vtkSetStringMacro(PrettyName); char *RegistryVersionName; // Description: // Limited edition mode, name of the application when in limited edition mode int LimitedEditionMode; char *LimitedEditionModeName; // Description: // Release mode int ReleaseMode; // Description: // Application installation directory char *InstallationDirectory; virtual void FindInstallationDirectory(); vtkKWApplication(const vtkKWApplication&); // Not implemented. void operator=(const vtkKWApplication&); // Not implemented. }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWCornerAnnotationEditor.cxx0000644000175000017500000004472311001741713023233 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWCornerAnnotationEditor.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWCornerAnnotationEditor.h" #include "vtkCornerAnnotation.h" #include "vtkKWCheckButton.h" #include "vtkKWEvent.h" #include "vtkKWFrame.h" #include "vtkKWLabel.h" #include "vtkKWFrameWithLabel.h" #include "vtkKWInternationalization.h" #include "vtkKWPopupButtonWithLabel.h" #include "vtkKWTextWithLabel.h" #include "vtkKWPopupButton.h" #include "vtkKWRenderWidget.h" #include "vtkKWScaleWithEntry.h" #include "vtkKWText.h" #include "vtkKWTextPropertyEditor.h" #include "vtkObjectFactory.h" #include "vtkProperty2D.h" #include "vtkTextProperty.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWCornerAnnotationEditor ); vtkCxxRevisionMacro(vtkKWCornerAnnotationEditor, "$Revision: 1.25 $"); //---------------------------------------------------------------------------- vtkKWCornerAnnotationEditor::vtkKWCornerAnnotationEditor() { this->AnnotationChangedEvent = vtkKWEvent::ViewAnnotationChangedEvent; // CornerAnnotation will either point to: // - InternalCornerAnnotation in vtkKWView mode, or // - vtkKWRenderWidget::GetCornerAnnotation() in vtkKWRenderWidget mode. this->CornerAnnotation = NULL; this->RenderWidget = NULL; // If in vtkKWView mode, we need to create and maintain the corner prop and // composite // GUI this->PopupTextProperty = 0; this->CornerFrame = vtkKWFrame::New(); this->PropertiesFrame = vtkKWFrame::New(); this->MaximumLineHeightScale = vtkKWScaleWithEntry::New(); this->TextPropertyWidget = vtkKWTextPropertyEditor::New(); this->TextPropertyPopupButton = NULL; for (int i = 0; i < 4; i++) { this->CornerText[i] = vtkKWTextWithLabel::New(); } } //---------------------------------------------------------------------------- vtkKWCornerAnnotationEditor::~vtkKWCornerAnnotationEditor() { // GUI if (this->CornerFrame) { this->CornerFrame->Delete(); this->CornerFrame = NULL; } for (int i = 0; i < 4; i++) { if (this->CornerText[i]) { this->CornerText[i]->Delete(); this->CornerText[i] = NULL; } } if (this->PropertiesFrame) { this->PropertiesFrame->Delete(); this->PropertiesFrame = NULL; } if (this->MaximumLineHeightScale) { this->MaximumLineHeightScale->Delete(); this->MaximumLineHeightScale = NULL; } if (this->TextPropertyWidget) { this->TextPropertyWidget->Delete(); this->TextPropertyWidget = NULL; } if (this->TextPropertyPopupButton) { this->TextPropertyPopupButton->Delete(); this->TextPropertyPopupButton = NULL; } // CornerAnnotation was either pointing to: // - InternalCornerAnnotation in vtkKWView mode, or // - vtkKWRenderWidget::GetCornerAnnotation() in vtkKWRenderWidget mode. this->RenderWidget = NULL; // If in vtkKWView mode, we createed and maintained the corner prop and // composite } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::SetRenderWidget(vtkKWRenderWidget *_arg) { if (this->RenderWidget == _arg) { return; } this->RenderWidget = _arg; // We are now in vtkKWRenderWidget mode, the corner prop points to the // vtkKWRenderWidget's corner prop if (this->RenderWidget != NULL) { this->CornerAnnotation = this->RenderWidget->GetCornerAnnotation(); } else { this->CornerAnnotation = NULL; } this->Modified(); // Update the GUI. Test if it is alive because we might be in the middle // of destructing the whole GUI if (this->IsAlive()) { this->Update(); } } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::Close() { this->SetVisibility(0); } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::CreateWidget() { // Create the superclass widgets if (this->IsCreated()) { vtkErrorMacro("CornerAnnotation already created"); return; } this->Superclass::CreateWidget(); int popup_text_property = this->PopupTextProperty && !this->PopupMode; // -------------------------------------------------------------- // If in popup mode, modify the popup button if (this->PopupMode) { this->PopupButton->SetText(ks_("Corner Annotation Editor|Edit...")); } // -------------------------------------------------------------- // Edit the labeled frame this->Frame->SetLabelText(ks_("Corner Annotation Editor|Corner annotation")); // -------------------------------------------------------------- // Edit the check button (Annotation visibility) this->CheckButton->SetText( ks_("Corner Annotation Editor|Display corner annotation")); this->CheckButton->SetBalloonHelpString( k_("Toggle the visibility of the corner annotation text")); // -------------------------------------------------------------- // Corners text this->CornerFrame->SetParent(this->Frame->GetFrame()); this->CornerFrame->Create(); this->Script("pack %s -side top -padx 2 -expand t -fill x -anchor nw", this->CornerFrame->GetWidgetName()); char buffer[50]; int i; for (i = 0; i < 4; i++) { this->CornerText[i]->SetParent(this->CornerFrame); this->CornerText[i]->Create(); this->CornerText[i]->SetLabelPositionToTop(); vtkKWText *text = this->CornerText[i]->GetWidget(); text->SetHeight(3); text->SetWidth(25); text->SetWrapToNone(); sprintf(buffer, "CornerTextCallback %i", i); text->SetBinding("", this, buffer); text->SetBinding("", this, buffer); } this->CornerText[0]->GetLabel()->SetText( ks_("Corner Annotation Editor|Corner|Lower left:")); this->CornerText[0]->SetBalloonHelpString( k_("Set the lower left corner annotation. The text will automatically " "scale to fit within the allocated space")); this->CornerText[1]->GetLabel()->SetText( ks_("Corner Annotation Editor|Corner|Lower right:")); this->CornerText[1]->SetBalloonHelpString( k_("Set the lower right corner annotation. The text will automatically " "scale to fit within the allocated space")); this->CornerText[2]->GetLabel()->SetText( ks_("Corner Annotation Editor|Corner|Upper left:")); this->CornerText[2]->SetBalloonHelpString( k_("Set the upper left corner annotation. The text will automatically " "scale to fit within the allocated space")); this->CornerText[3]->GetLabel()->SetText( ks_("Corner Annotation Editor|Corner|Upper right:")); this->CornerText[3]->SetBalloonHelpString( k_("Set the upper right corner annotation. The text will automatically " "scale to fit within the allocated space")); this->Script("grid %s %s -row 0 -sticky news -padx 2 -pady 0 -ipady 0", this->CornerText[2]->GetWidgetName(), this->CornerText[3]->GetWidgetName()); this->Script("grid %s %s -row 1 -sticky news -padx 2 -pady 0 -ipady 0", this->CornerText[0]->GetWidgetName(), this->CornerText[1]->GetWidgetName()); this->Script("grid columnconfigure %s 0 -weight 1", this->CornerFrame->GetWidgetName()); this->Script("grid columnconfigure %s 1 -weight 1", this->CornerFrame->GetWidgetName()); // -------------------------------------------------------------- // Properties frame this->PropertiesFrame->SetParent(this->Frame->GetFrame()); this->PropertiesFrame->Create(); this->Script("pack %s -side top -padx 2 -expand t -fill both -anchor nw", this->PropertiesFrame->GetWidgetName()); // -------------------------------------------------------------- // Maximum line height this->MaximumLineHeightScale->SetParent(this->PropertiesFrame); this->MaximumLineHeightScale->PopupModeOn(); this->MaximumLineHeightScale->Create(); this->MaximumLineHeightScale->SetRange(0.01, 0.2); this->MaximumLineHeightScale->SetResolution(0.01); this->MaximumLineHeightScale->EntryVisibilityOn(); this->MaximumLineHeightScale->SetEntryPositionToTop(); this->MaximumLineHeightScale->SetLabelPositionToTop(); this->MaximumLineHeightScale->SetLabelText("Max line height:"); this->MaximumLineHeightScale->SetEntryWidth(5); this->MaximumLineHeightScale->SetBalloonHelpString( k_("Set the maximum height of a line of text as a percentage of the " "vertical area allocated to this scaled text actor.")); this->MaximumLineHeightScale->SetCommand( this, "MaximumLineHeightCallback"); this->MaximumLineHeightScale->SetEndCommand( this, "MaximumLineHeightEndCallback"); this->MaximumLineHeightScale->SetEntryCommand( this, "MaximumLineHeightEndCallback"); this->Script("pack %s -padx 2 -pady 2 -side %s -anchor w -fill y", this->MaximumLineHeightScale->GetWidgetName(), (popup_text_property ? "left" : "top")); // -------------------------------------------------------------- // Text property : popup button if needed if (popup_text_property) { if (!this->TextPropertyPopupButton) { this->TextPropertyPopupButton = vtkKWPopupButtonWithLabel::New(); } this->TextPropertyPopupButton->SetParent(this->PropertiesFrame); this->TextPropertyPopupButton->Create(); this->TextPropertyPopupButton->GetLabel()->SetText( ks_("Corner Annotation Editor|Text properties:")); this->TextPropertyPopupButton->GetWidget()->SetText( ks_("Corner Annotation Editor|Edit...")); vtkKWFrame *popupframe = this->TextPropertyPopupButton->GetWidget()->GetPopupFrame(); popupframe->SetBorderWidth(2); popupframe->SetReliefToGroove(); this->Script("pack %s -padx 2 -pady 2 -side left -anchor w", this->TextPropertyPopupButton->GetWidgetName()); this->TextPropertyWidget->SetParent( this->TextPropertyPopupButton->GetWidget()->GetPopupFrame()); } else { this->TextPropertyWidget->SetParent(this->PropertiesFrame); } // -------------------------------------------------------------- // Text property this->TextPropertyWidget->LongFormatOn(); this->TextPropertyWidget->LabelOnTopOn(); this->TextPropertyWidget->LabelVisibilityOn(); this->TextPropertyWidget->Create(); this->TextPropertyWidget->GetLabel()->SetText( ks_("Corner Annotation Editor|Text properties:")); this->TextPropertyWidget->SetChangedCommand(this, "TextPropertyCallback"); this->Script("pack %s -padx 2 -pady %d -side top -anchor nw -fill y", this->TextPropertyWidget->GetWidgetName(), this->TextPropertyWidget->GetLongFormat() ? 0 : 2); // -------------------------------------------------------------- // Update the GUI according to the Ivar value (i.e. the corner prop, etc.) this->Update(); } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::Update() { this->Superclass::Update(); if (!this->IsCreated()) { return; } // Corners text for (int i = 0; i < 4; i++) { if (this->CornerText[i]) { this->CornerText[i]->GetWidget()->SetText( this->CornerAnnotation ? this->CornerAnnotation->GetText(i) : ""); } } // Maximum line height if (this->MaximumLineHeightScale && this->CornerAnnotation) { this->MaximumLineHeightScale->SetValue( this->CornerAnnotation->GetMaximumLineHeight()); } // Text property if (this->TextPropertyWidget) { this->TextPropertyWidget->SetTextProperty( this->CornerAnnotation ? this->CornerAnnotation->GetTextProperty():NULL); this->TextPropertyWidget->SetActor2D(this->CornerAnnotation); this->TextPropertyWidget->Update(); } if (this->CheckButton && this->CornerAnnotation) { this->CheckButton->SetSelectedState( this->CornerAnnotation->GetVisibility()); } } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::Render() { if (this->RenderWidget) { this->RenderWidget->Render(); } } //---------------------------------------------------------------------------- int vtkKWCornerAnnotationEditor::GetVisibility() { // Note that the visibility here is based on the real visibility of the // annotation, not the state of the checkbutton return (this->CornerAnnotation && this->CornerAnnotation->GetVisibility() && this->RenderWidget && this->RenderWidget->HasViewProp(this->CornerAnnotation)) ? 1 : 0; } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::SetVisibility(int state) { // In vtkKWView mode, add/remove the composite // In vtkKWRenderWidget mode, add/remove the prop int old_visibility = this->GetVisibility(); if (this->CornerAnnotation) { if (state) { this->CornerAnnotation->VisibilityOn(); if (this->RenderWidget) { this->RenderWidget->SetCornerAnnotationVisibility(state); } } else { this->CornerAnnotation->VisibilityOff(); if (this->RenderWidget) { this->RenderWidget->SetCornerAnnotationVisibility(state); } } } if (old_visibility != this->GetVisibility()) { this->Update(); this->Render(); this->SendChangedEvent(); } } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::CheckButtonCallback(int state) { this->SetVisibility(state ? 1 : 0); } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::SetMaximumLineHeight(float v) { if (!this->CornerAnnotation || this->CornerAnnotation->GetMaximumLineHeight() == v) { return; } this->CornerAnnotation->SetMaximumLineHeight(v); this->Update(); if (this->GetVisibility()) { this->Render(); } this->SendChangedEvent(); } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::MaximumLineHeightCallback(double value) { this->SetMaximumLineHeight(value); } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::MaximumLineHeightEndCallback(double value) { this->SetMaximumLineHeight(value); } //---------------------------------------------------------------------------- double *vtkKWCornerAnnotationEditor::GetTextColor() { if (this->TextPropertyWidget) { return this->TextPropertyWidget->GetColor(); } return NULL; } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::SetTextColor(double r, double g, double b) { // The following call with eventually trigger the TextPropertyCallback // (see Create()). double *rgb = this->GetTextColor(); if (rgb && (rgb[0] != r || rgb[1] != g || rgb[2] != b) && this->TextPropertyWidget) { this->TextPropertyWidget->SetColor(r, g, b); } } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::TextPropertyCallback() { if (this->GetVisibility()) { this->Render(); } this->SendChangedEvent(); } //---------------------------------------------------------------------------- const char *vtkKWCornerAnnotationEditor::GetCornerText(int i) { if (this->CornerAnnotation) { return (const char*)this->CornerAnnotation->GetText(i); } return NULL; } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::SetCornerText(const char *text, int corner) { if (this->CornerAnnotation && (!this->GetCornerText(corner) || strcmp(this->GetCornerText(corner), text))) { this->CornerAnnotation->SetText(corner, text); this->Update(); if (this->GetVisibility()) { this->Render(); } this->SendChangedEvent(); } } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::CornerTextCallback(int i) { if (this->IsCreated() && this->CornerText[i]) { this->SetCornerText(this->CornerText[i]->GetWidget()->GetText(), i); } } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::UpdateEnableState() { this->Superclass::UpdateEnableState(); //int enabled = this->RenderWidget ? this->GetEnabled() : 0; int enabled = this->GetEnabled(); if (this->CornerFrame) { this->CornerFrame->SetEnabled(enabled); } int i; for (i = 0; i < 4; i++) { if (this->CornerText[i]) { this->CornerText[i]->SetEnabled(enabled); } } if (this->PropertiesFrame) { this->PropertiesFrame->SetEnabled(enabled); } if (this->MaximumLineHeightScale) { this->MaximumLineHeightScale->SetEnabled(enabled); } if (this->TextPropertyWidget) { this->TextPropertyWidget->SetEnabled(enabled); } if (this->TextPropertyPopupButton) { this->TextPropertyPopupButton->SetEnabled(enabled); } } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::SendChangedEvent() { if (!this->CornerAnnotation) { return; } this->InvokeEvent(this->AnnotationChangedEvent, NULL); } //---------------------------------------------------------------------------- void vtkKWCornerAnnotationEditor::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "AnnotationChangedEvent: " << this->AnnotationChangedEvent << endl; os << indent << "CornerAnnotation: " << this->GetCornerAnnotation() << endl; os << indent << "RenderWidget: " << this->GetRenderWidget() << endl; os << indent << "TextPropertyWidget: " << this->TextPropertyWidget << endl; os << indent << "MaximumLineHeightScale: " << this->MaximumLineHeightScale << endl; os << indent << "PopupTextProperty: " << (this->PopupTextProperty ? "On" : "Off") << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWBalloonHelpManager.h0000644000175000017500000000712510756660473021736 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWBalloonHelpManager.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWBalloonHelpManager - a "balloon help " manager class // .SECTION Description // vtkKWBalloonHelpManager is a class that provides functionality // to display balloon help (tooltips) for an application. // An instance of this class is created in the vtkKWApplication class. // When the balloon help string of a vtkKWWidget is set, the balloon help // manager instance of the widget's application is called to set up // bindings automatically for this widget (see AddBindings()). These bindings // will trigger the manager callbacks to display the balloon help string // appropriately. // .SECTION See Also // vtkKWApplication vtkKWWidget #ifndef __vtkKWBalloonHelpManager_h #define __vtkKWBalloonHelpManager_h #include "vtkKWObject.h" class vtkKWTopLevel; class vtkKWLabel; class vtkKWWidget; class KWWidgets_EXPORT vtkKWBalloonHelpManager : public vtkKWObject { public: static vtkKWBalloonHelpManager* New(); vtkTypeRevisionMacro(vtkKWBalloonHelpManager,vtkKWObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get balloon help visibility for all the widgets bound to this helper. virtual void SetVisibility(int); vtkGetMacro(Visibility, int); vtkBooleanMacro(Visibility, int); // Description: // Set the delay for the balloon help in milliseconds. vtkSetClampMacro(Delay, int, 0, 15000); vtkGetMacro(Delay, int); // Description: // Add/remove bindings for a given widget, effectively providing balloon help // feature for this widget. // On the widget side, one has to set the balloon help string or image. virtual void AddBindings(vtkKWWidget *widget); virtual void RemoveBindings(vtkKWWidget *widget); // Description: // Set/Get if the balloon help is not displayed when the widget Enabled // state is Off. vtkSetMacro(IgnoreIfNotEnabled, int); vtkGetMacro(IgnoreIfNotEnabled, int); vtkBooleanMacro(IgnoreIfNotEnabled, int); // Description: // Callbacks. Internal, do not use. virtual void TriggerCallback(vtkKWWidget *widget); virtual void DisplayCallback(vtkKWWidget *widget); virtual void CancelCallback(); virtual void WithdrawCallback(); protected: vtkKWBalloonHelpManager(); ~vtkKWBalloonHelpManager(); int Visibility; int IgnoreIfNotEnabled; int Delay; vtkKWTopLevel *TopLevel; vtkKWLabel *Label; // Description: // The widget which balloon help is currently being displayed or pending. vtkKWWidget *CurrentWidget; virtual void SetCurrentWidget(vtkKWWidget *widget); // Description: // The Id of the Tk 'after' timer that will display the balloon help // after some delay. char *AfterTimerId; vtkSetStringMacro(AfterTimerId); // Description: // Create the UI. virtual void CreateBalloon(); // Description: // Return true if the application is exiting, i.e. if it is not safe // to perform anything (balloon help is an asynchronous process) virtual int ApplicationInExit(); private: vtkKWBalloonHelpManager(const vtkKWBalloonHelpManager&); // Not implemented. void operator=(const vtkKWBalloonHelpManager&); // Not implemented. }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWStateMachineCluster.h0000644000175000017500000000533510526410341022132 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWStateMachineCluster.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWStateMachineCluster - a state machine cluster. // .SECTION Description // This class is the basis for a state machine cluster, i.e. a means // to logically group states together. Clusters are not used by the // state machine per se, they are just a convenient way to group states // logically together, and can be used by state machine writers // (see vtkKWStateMachineDOTWriter) to display clusters as groups. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWStateMachine vtkKWStateMachineState #ifndef __vtkKWStateMachineCluster_h #define __vtkKWStateMachineCluster_h #include "vtkKWObject.h" class vtkKWStateMachineState; class vtkKWStateMachineClusterInternals; class KWWidgets_EXPORT vtkKWStateMachineCluster : public vtkKWObject { public: static vtkKWStateMachineCluster* New(); vtkTypeRevisionMacro(vtkKWStateMachineCluster, vtkKWObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get id. vtkGetMacro(Id, vtkIdType); // Description: // Set/Get simple name. vtkGetStringMacro(Name); vtkSetStringMacro(Name); // Description: // Add a state. // Return 1 on success, 0 otherwise. virtual int AddState(vtkKWStateMachineState *state); virtual int HasState(vtkKWStateMachineState *state); virtual int GetNumberOfStates(); virtual vtkKWStateMachineState* GetNthState(int rank); protected: vtkKWStateMachineCluster(); ~vtkKWStateMachineCluster(); vtkIdType Id; char *Name; // Description: // Remove state(s). virtual void RemoveState(vtkKWStateMachineState *state); virtual void RemoveAllStates(); // PIMPL Encapsulation for STL containers //BTX vtkKWStateMachineClusterInternals *Internals; //ETX private: static vtkIdType IdCounter; vtkKWStateMachineCluster(const vtkKWStateMachineCluster&); // Not implemented void operator=(const vtkKWStateMachineCluster&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWMaterialPropertyWidget.cxx0000644000175000017500000007552110752133413023254 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWMaterialPropertyWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWMaterialPropertyWidget.h" #include "vtkKWCheckButton.h" #include "vtkKWEvent.h" #include "vtkKWFrame.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWFrameWithLabel.h" #include "vtkKWLabelWithLabel.h" #include "vtkKWPopupButtonWithLabel.h" #include "vtkKWPushButtonSetWithLabel.h" #include "vtkKWPopupButton.h" #include "vtkKWPushButton.h" #include "vtkKWPushButtonSet.h" #include "vtkKWScaleWithEntry.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include #include #include //---------------------------------------------------------------------------- vtkCxxRevisionMacro(vtkKWMaterialPropertyWidget, "$Revision: 1.29 $"); //---------------------------------------------------------------------------- class vtkKWMaterialPropertyWidgetInternals { public: typedef vtksys_stl::list PresetsContainer; typedef vtksys_stl::list::iterator PresetsContainerIterator; PresetsContainer Presets; }; //---------------------------------------------------------------------------- vtkKWMaterialPropertyWidget::vtkKWMaterialPropertyWidget() { this->PreviewSize = 40; this->PresetSize = 40; this->PopupPreviewSize = 24; this->GridOpacity = 0.3; this->LightingParametersVisibility = 1; this->MaterialColor[0] = 1.0; this->MaterialColor[1] = 1.0; this->MaterialColor[2] = 1.0; this->PropertyChangedEvent = vtkKWEvent::MaterialPropertyChangedEvent; this->PropertyChangingEvent = vtkKWEvent::MaterialPropertyChangingEvent; this->PropertyChangedCommand = NULL; this->PropertyChangingCommand = NULL; // Presets this->Internals = new vtkKWMaterialPropertyWidgetInternals; this->AddDefaultPresets(); // UI this->PopupMode = 0; this->PopupButton = NULL; this->MaterialPropertiesFrame = vtkKWFrameWithLabel::New(); this->ControlFrame = vtkKWFrame::New(); this->LightingFrame = vtkKWFrame::New(); this->AmbientScale = vtkKWScaleWithEntry::New(); this->DiffuseScale = vtkKWScaleWithEntry::New(); this->SpecularScale = vtkKWScaleWithEntry::New(); this->SpecularPowerScale = vtkKWScaleWithEntry::New(); this->PresetsFrame = vtkKWFrame::New(); this->PreviewLabel = vtkKWLabelWithLabel::New(); this->PresetPushButtonSet = vtkKWPushButtonSetWithLabel::New(); } //---------------------------------------------------------------------------- vtkKWMaterialPropertyWidget::~vtkKWMaterialPropertyWidget() { // Commands if (this->PropertyChangedCommand) { delete [] this->PropertyChangedCommand; this->PropertyChangedCommand = NULL; } if (this->PropertyChangingCommand) { delete [] this->PropertyChangingCommand; this->PropertyChangingCommand = NULL; } // Delete all presets if (this->Internals) { vtkKWMaterialPropertyWidgetInternals::PresetsContainerIterator it = this->Internals->Presets.begin(); vtkKWMaterialPropertyWidgetInternals::PresetsContainerIterator end = this->Internals->Presets.end(); for (; it != end; ++it) { if (*it) { if ((*it)->HelpString) { delete [] (*it)->HelpString; } delete (*it); } } delete this->Internals; } // Delete UI if (this->PopupButton) { this->PopupButton->Delete(); this->PopupButton = NULL; } if (this->MaterialPropertiesFrame) { this->MaterialPropertiesFrame->Delete(); this->MaterialPropertiesFrame = NULL; } if (this->ControlFrame) { this->ControlFrame->Delete(); this->ControlFrame = NULL; } if (this->LightingFrame) { this->LightingFrame->Delete(); this->LightingFrame = NULL; } if (this->AmbientScale) { this->AmbientScale->Delete(); this->AmbientScale = NULL; } if (this->DiffuseScale) { this->DiffuseScale->Delete(); this->DiffuseScale = NULL; } if (this->SpecularScale) { this->SpecularScale->Delete(); this->SpecularScale = NULL; } if (this->SpecularPowerScale) { this->SpecularPowerScale->Delete(); this->SpecularPowerScale = NULL; } if (this->PresetsFrame) { this->PresetsFrame->Delete(); this->PresetsFrame = NULL; } if (this->PreviewLabel) { this->PreviewLabel->Delete(); this->PreviewLabel = NULL; } if (this->PresetPushButtonSet) { this->PresetPushButtonSet->Delete(); this->PresetPushButtonSet = NULL; } } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::AddDefaultPresets() { if (!this->Internals) { return; } vtkKWMaterialPropertyWidget::Preset *preset; // Presets : Unshaded preset = new vtkKWMaterialPropertyWidget::Preset; preset->Ambient = 1.0; preset->Diffuse = 0.0; preset->Specular = 0.0; preset->SpecularPower = 1.0; preset->HelpString = vtksys::SystemTools::DuplicateString( ks_("Material Preset|Full ambient eliminating all directional shading.")); this->Internals->Presets.push_back(preset); // Presets : Dull preset = new vtkKWMaterialPropertyWidget::Preset; preset->Ambient = 0.2; preset->Diffuse = 1.0; preset->Specular = 0.0; preset->SpecularPower = 1.0; preset->HelpString = vtksys::SystemTools::DuplicateString( ks_("Material Preset|Dull material properties (no specular lighting)")); this->Internals->Presets.push_back(preset); // Presets : Smooth preset = new vtkKWMaterialPropertyWidget::Preset; preset->Ambient = 0.1; preset->Diffuse = 0.9; preset->Specular = 0.2; preset->SpecularPower = 10.0; preset->HelpString = vtksys::SystemTools::DuplicateString( ks_("Material Preset|Smooth material properties (moderate specular lighting")); this->Internals->Presets.push_back(preset); // Presets : Shiny preset = new vtkKWMaterialPropertyWidget::Preset; preset->Ambient = 0.1; preset->Diffuse = 0.6; preset->Specular = 0.5; preset->SpecularPower = 40.0; preset->HelpString = vtksys::SystemTools::DuplicateString( ks_("Material Preset|Shiny material properties (high specular lighting)")); this->Internals->Presets.push_back(preset); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); vtkKWFrame *frame; // -------------------------------------------------------------- // If in popup mode, create the popup button if (this->PopupMode) { if (!this->PopupButton) { this->PopupButton = vtkKWPopupButtonWithLabel::New(); } this->PopupButton->SetParent(this); this->PopupButton->Create(); this->PopupButton->GetLabel()->SetText( ks_("Material Property Editor|Material:")); this->PopupButton->GetWidget()->SetText(""); this->PopupButton->GetWidget()->SetPopupTitle( ks_("Material Property Editor|Material Properties")); this->PopupButton->SetBalloonHelpString( ks_("Edit Material Properties.")); this->Script("pack %s -side left -anchor w -fill x", this->PopupButton->GetWidgetName()); } // -------------------------------------------------------------- // Material frame if (this->PopupMode) { this->MaterialPropertiesFrame->AllowFrameToCollapseOff(); this->MaterialPropertiesFrame->SetParent( this->PopupButton->GetWidget()->GetPopupFrame()); } else { this->MaterialPropertiesFrame->AllowFrameToCollapseOn(); this->MaterialPropertiesFrame->SetParent(this); } this->MaterialPropertiesFrame->Create(); this->MaterialPropertiesFrame->SetLabelText( ks_("Material Property Editor|Material Properties")); this->Script("pack %s -padx 0 -pady 0 -fill x -expand yes -anchor w", this->MaterialPropertiesFrame->GetWidgetName()); frame = this->MaterialPropertiesFrame->GetFrame(); // -------------------------------------------------------------- // Control frame this->ControlFrame->SetParent(frame); this->ControlFrame->Create(); // -------------------------------------------------------------- // Lighting frame this->LightingFrame->SetParent(frame); this->LightingFrame->Create(); // -------------------------------------------------------------- // Ambient int entry_width = 5; int label_width = 12; int row = 0; this->AmbientScale->SetParent(this->LightingFrame); this->AmbientScale->Create(); this->AmbientScale->SetCommand(this, "PropertyChangingCallback"); this->AmbientScale->SetEndCommand(this, "PropertyChangedCallback"); this->AmbientScale->SetEntryCommand(this, "PropertyChangedCallback"); this->AmbientScale->SetEntryWidth(entry_width); this->AmbientScale->SetLabelText(ks_("Material Property Editor|Ambient:")); this->AmbientScale->SetLabelWidth(label_width); this->AmbientScale->SetRange(0, 100); this->AmbientScale->SetBalloonHelpString( k_("Set the ambient coefficient within the range [0,100] for lighting")); this->Script("grid %s -padx 2 -pady 2 -sticky news -row %d", this->AmbientScale->GetWidgetName(), row++); this->Script("grid columnconfigure %s 0 -weight 1", this->AmbientScale->GetParent()->GetWidgetName(), row++); // -------------------------------------------------------------- // Diffuse this->DiffuseScale->SetParent(this->LightingFrame); this->DiffuseScale->Create(); this->DiffuseScale->SetCommand(this, "PropertyChangingCallback"); this->DiffuseScale->SetEndCommand(this, "PropertyChangedCallback"); this->DiffuseScale->SetEntryCommand(this, "PropertyChangedCallback"); this->DiffuseScale->SetEntryWidth(entry_width); this->DiffuseScale->SetLabelText(ks_("Material Property Editor|Diffuse:")); this->DiffuseScale->SetLabelWidth(label_width); this->DiffuseScale->SetRange(0, 100); this->DiffuseScale->SetBalloonHelpString( k_("Set the diffuse coefficient within the range [0,100] for lighting")); this->Script("grid %s -padx 2 -pady 2 -sticky news -row %d", this->DiffuseScale->GetWidgetName(), row++); // -------------------------------------------------------------- // Specular this->SpecularScale->SetParent(this->LightingFrame); this->SpecularScale->Create(); this->SpecularScale->SetCommand(this, "PropertyChangingCallback"); this->SpecularScale->SetEndCommand(this, "PropertyChangedCallback"); this->SpecularScale->SetEntryCommand(this, "PropertyChangedCallback"); this->SpecularScale->SetEntryWidth(entry_width); this->SpecularScale->SetLabelText( ks_("Material Property Editor|Specular:")); this->SpecularScale->SetLabelWidth(label_width); this->SpecularScale->SetRange(0, 100); this->SpecularScale->SetBalloonHelpString( k_("Set the specular coefficient within the range [0,100] for lighting")); this->Script("grid %s -padx 2 -pady 2 -sticky news -row %d", this->SpecularScale->GetWidgetName(), row++); // -------------------------------------------------------------- // Specular power this->SpecularPowerScale->SetParent(this->LightingFrame); this->SpecularPowerScale->Create(); this->SpecularPowerScale->SetCommand(this, "PropertyChangingCallback"); this->SpecularPowerScale->SetEndCommand(this, "PropertyChangedCallback"); this->SpecularPowerScale->SetEntryCommand(this, "PropertyChangedCallback"); this->SpecularPowerScale->SetEntryWidth(entry_width); this->SpecularPowerScale->SetLabelText( ks_("Material Property Editor|Power:")); this->SpecularPowerScale->SetLabelWidth(label_width); this->SpecularPowerScale->SetRange(1, 50); this->SpecularPowerScale->SetBalloonHelpString( k_("Set the specular power within the range [0,50] for lighting")); this->Script("grid %s -padx 2 -pady 2 -sticky news -row %d", this->SpecularPowerScale->GetWidgetName(), row++); // -------------------------------------------------------------- // Presets + Preview frame this->PresetsFrame->SetParent(frame); this->PresetsFrame->Create(); // -------------------------------------------------------------- // Preview this->PreviewLabel->SetParent(this->PresetsFrame); this->PreviewLabel->SetLabelPositionToTop(); this->PreviewLabel->ExpandWidgetOff(); this->PreviewLabel->Create(); this->PreviewLabel->GetLabel()->SetText( ks_("Material Property Editor|Preview:")); this->Script("pack %s -side left -padx 2 -pady 2 -anchor nw", this->PreviewLabel->GetWidgetName()); // -------------------------------------------------------------- // Presets this->PresetPushButtonSet->SetParent(this->PresetsFrame); this->PresetPushButtonSet->SetLabelPositionToTop(); this->PresetPushButtonSet->GetLabel()->SetText( ks_("Material Property Editor|Presets:")); this->PresetPushButtonSet->Create(); this->PresetPushButtonSet->ExpandWidgetOff(); this->Script( "pack %s -side right -padx 2 -pady 2 -anchor nw", this->PresetPushButtonSet->GetWidgetName()); vtkKWPushButtonSet *pbs = this->PresetPushButtonSet->GetWidget(); pbs->PackHorizontallyOn(); this->CreatePresets(); // Set some default values that are more pleasing the black body this->UpdateScales(0.1 * 100, 0.9 * 100, 0.2 * 100, 10.0 * 100); // Pack this->Pack(); // Update according to the current view/widget this->Update(); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::Pack() { if (!this->IsCreated()) { return; } if (this->MaterialPropertiesFrame) { this->MaterialPropertiesFrame->GetFrame()->UnpackChildren(); } if (this->ControlFrame) { this->Script("pack %s -padx 0 -pady 0 -fill x -expand yes -anchor w", this->ControlFrame->GetWidgetName()); } if (this->LightingFrame && this->LightingParametersVisibility) { this->Script("pack %s -padx 0 -pady 0 -fill x -expand yes -anchor w", this->LightingFrame->GetWidgetName()); } if (this->PresetsFrame) { this->Script("pack %s -anchor w -fill x -expand y", this->PresetsFrame->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::Update() { // Update enable state this->UpdateEnableState(); if (!this->IsCreated()) { return; } } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::SetLightingParametersVisibility(int arg) { if (this->LightingParametersVisibility == arg) { return; } this->LightingParametersVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::SetPreviewSize(int v) { if (this->PreviewSize == v || v < 8) { return; } this->PreviewSize = v; this->Modified(); this->UpdatePreview(); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::SetGridOpacity(double v) { if (this->GridOpacity == v || v < 0.0 || v > 1.0) { return; } this->GridOpacity = v; this->Modified(); this->UpdatePreview(); this->CreatePresets(); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::SetMaterialColor(double r, double g, double b) { if (this->MaterialColor[0] == r && this->MaterialColor[1] == g && this->MaterialColor[2] == b) { return; } this->MaterialColor[0] = r; this->MaterialColor[1] = g; this->MaterialColor[2] = b; this->UpdatePreview(); this->CreatePresets(); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::UpdateScales(double ambient, double diffuse, double specular, double specular_power) { // Ambient if (this->AmbientScale && this->AmbientScale->GetValue() != ambient) { int old_disable = this->AmbientScale->GetDisableCommands(); this->AmbientScale->SetDisableCommands(1); this->AmbientScale->SetValue(ambient); this->AmbientScale->SetDisableCommands(old_disable); } // Diffuse if (this->DiffuseScale && this->DiffuseScale->GetValue() != diffuse) { int old_disable = this->DiffuseScale->GetDisableCommands(); this->DiffuseScale->SetDisableCommands(1); this->DiffuseScale->SetValue(diffuse); this->DiffuseScale->SetDisableCommands(old_disable); } // Specular if (this->SpecularScale && this->SpecularScale->GetValue() != specular) { int old_disable = this->SpecularScale->GetDisableCommands(); this->SpecularScale->SetDisableCommands(1); this->SpecularScale->SetValue(specular); this->SpecularScale->SetDisableCommands(old_disable); } // Specular power if (this->SpecularPowerScale && this->SpecularPowerScale->GetValue() != specular_power) { int old_disable = this->SpecularPowerScale->GetDisableCommands(); this->SpecularPowerScale->SetDisableCommands(1); this->SpecularPowerScale->SetValue(specular_power); this->SpecularPowerScale->SetDisableCommands(old_disable); } } //---------------------------------------------------------------------------- int vtkKWMaterialPropertyWidget::UpdateScalesFromPreset(const Preset *preset) { if (!preset) { return 0; } this->UpdateScales(preset->Ambient * 100.0, preset->Diffuse * 100.0, preset->Specular * 100.0, preset->SpecularPower * 100.0); return 1; } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::UpdatePreview() { if (!this->IsCreated()) { return; } // Update the preview int pixel_size = 3 + (this->GridOpacity == 1.0 ? 0 : 1); unsigned char *buffer = new unsigned char [this->PreviewSize * this->PreviewSize * pixel_size]; this->CreateImage(buffer, this->AmbientScale->GetValue(), this->DiffuseScale->GetValue(), this->SpecularScale->GetValue(), this->SpecularPowerScale->GetValue(), this->PreviewSize); this->PreviewLabel->GetWidget()->SetImageToPixels( buffer, this->PreviewSize, this->PreviewSize, pixel_size); delete [] buffer; // Update the popup preview too automatically this->UpdatePopupPreview(); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::SetPopupPreviewSize(int v) { if (this->PopupPreviewSize == v || v < 8) { return; } this->PopupPreviewSize = v; this->Modified(); this->UpdatePopupPreview(); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::UpdatePopupPreview() { if (!this->IsCreated() || !this->PopupMode) { return; } // Update the popup preview int pixel_size = 3 + (this->GridOpacity == 1.0 ? 0 : 1); unsigned char *buffer = new unsigned char [ this->PopupPreviewSize * this->PopupPreviewSize * pixel_size]; this->CreateImage(buffer, this->AmbientScale->GetValue(), this->DiffuseScale->GetValue(), this->SpecularScale->GetValue(), this->SpecularPowerScale->GetValue(), this->PopupPreviewSize); this->PopupButton->GetWidget()->SetImageToPixels( buffer, this->PopupPreviewSize, this->PopupPreviewSize, pixel_size); delete [] buffer; } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::SetPresetSize(int v) { if (this->PresetSize == v || v < 8) { return; } this->PresetSize = v; this->Modified(); this->CreatePresets(); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::CreatePresets() { if (!this->IsCreated()) { return; } // Delete all presets vtkKWPushButtonSet *pbs = this->PresetPushButtonSet->GetWidget(); pbs->DeleteAllWidgets(); int pixel_size = 3 + (this->GridOpacity == 1.0 ? 0 : 1); unsigned char *buffer = new unsigned char [this->PresetSize * this->PresetSize * pixel_size]; // Create all presets int rank = 0; vtkKWMaterialPropertyWidgetInternals::PresetsContainerIterator it = this->Internals->Presets.begin(); vtkKWMaterialPropertyWidgetInternals::PresetsContainerIterator end = this->Internals->Presets.end(); for (; it != end; ++it, ++rank) { if (*it) { vtkKWPushButton *pb = pbs->AddWidget(rank); if ((*it)->HelpString) { pb->SetBalloonHelpString((*it)->HelpString); } this->CreateImage(buffer, (*it)->Ambient * 100.0, (*it)->Diffuse * 100.0, (*it)->Specular * 100.0, (*it)->SpecularPower, this->PresetSize); pb->SetImageToPixels( buffer, this->PresetSize, this->PresetSize, pixel_size); vtksys_ios::ostringstream preset_callback; preset_callback << "PresetMaterialCallback " << rank; pb->SetCommand(this, preset_callback.str().c_str()); } } delete [] buffer; } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->PopupButton); this->PropagateEnableState(this->MaterialPropertiesFrame); this->PropagateEnableState(this->ControlFrame); this->PropagateEnableState(this->LightingFrame); int enabled = this->AreControlsEnabled() ? this->GetEnabled() : 0; if (this->AmbientScale) { this->AmbientScale->SetEnabled(enabled); } if (this->DiffuseScale) { this->DiffuseScale->SetEnabled(enabled); } if (this->SpecularScale) { this->SpecularScale->SetEnabled(enabled); } if (this->SpecularPowerScale) { this->SpecularPowerScale->SetEnabled(enabled); } if (this->PreviewLabel) { this->PreviewLabel->SetEnabled(enabled); } if (this->PresetPushButtonSet) { this->PresetPushButtonSet->SetEnabled(enabled); } } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::PropertyChangingCallback(double) { // We put UpdatePreview out of the test to make sure the UI can still // be modified/tested without any real VTK object connected to it // (say, a vtkVolumeProperty) int prop_has_changed = this->UpdatePropertyFromInterface(); this->UpdatePreview(); if (prop_has_changed) { this->InvokePropertyChangingCommand(); this->SendStateEvent(this->PropertyChangingEvent); } } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::PropertyChangedCallback(double) { // We put UpdatePreview out of the test to make sure the UI can still // be modified/tested without any real VTK object connected to it // (say, a vtkVolumeProperty) this->UpdatePropertyFromInterface(); this->UpdatePreview(); // The ones above are out of the test too, since this callback is most of the // times called at the end of an interaction which had triggered // PropertyChangingCallback already. Since PropertyChangingCallback will // modify the property, at the time PropertyChangedCallback is invoked // the property values are the same, thus UpdatePropertyFromInterface will // most likely return 0. We Sacrifice a bit of effiency here to make sure // the right command and events are send. this->InvokePropertyChangedCommand(); this->SendStateEvent(this->PropertyChangedEvent); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::PresetMaterialCallback(int rank) { vtkKWMaterialPropertyWidgetInternals::PresetsContainerIterator it = this->Internals->Presets.begin(); vtkKWMaterialPropertyWidgetInternals::PresetsContainerIterator end = this->Internals->Presets.end(); for (; it != end && rank; ++it, --rank); if (it != end) { int prop_has_changed = this->UpdatePropertyFromPreset(*it); this->UpdateScalesFromPreset(*it); this->Update(); if (prop_has_changed) { this->InvokePropertyChangedCommand(); this->SendStateEvent(this->PropertyChangedEvent); } } } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::SendStateEvent(int event) { this->InvokeEvent(event, NULL); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::CreateImage(unsigned char *data, double ambient, double diffuse, double specular, double specular_power, int size) { int i, j; double dist, intensity[3]; double pt[3], normal[3], light[3], view[3], ref[3]; double diffuseComp, specularComp, specularDot; int iGrid, jGrid; int pixel_size = 3 + (this->GridOpacity == 1.0 ? 0 : 1); int r, g, b, a; double size2 = (double)size * 0.5; for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { dist = sqrt((double)((i-size2)*(i-size2) + (j-size2)*(j-size2))); if (dist <= size2 - 1) { normal[0] = pt[0] = (i-size2) / (size2-1); normal[1] = pt[1] = (j-size2) / (size2-1); normal[2] = pt[2] = sqrt(1 - pt[0]*pt[0] - pt[1]*pt[1]); vtkMath::Normalize(normal); light[0] = -5 - pt[0]; light[1] = -5 - pt[1]; light[2] = 5 - pt[2]; vtkMath::Normalize(light); view[0] = -pt[0]; view[1] = -pt[1]; view[2] = 5 - pt[2]; vtkMath::Normalize(view); ref[0] = 2*normal[0]*vtkMath::Dot(normal, light) - light[0]; ref[1] = 2*normal[1]*vtkMath::Dot(normal, light) - light[1]; ref[2] = 2*normal[2]*vtkMath::Dot(normal, light) - light[2]; vtkMath::Normalize(ref); diffuseComp = diffuse*.01*vtkMath::Dot(normal, light); if (diffuseComp < 0) { diffuseComp = 0; } specularDot = vtkMath::Dot(ref, view); if (specularDot < 0) { specularDot = 0; } specularComp = specular*.01*pow(specularDot, specular_power); intensity[0] = (ambient*.01 + diffuseComp)*this->MaterialColor[0] + specularComp; intensity[1] = (ambient*.01 + diffuseComp)*this->MaterialColor[1] + specularComp; intensity[2] = (ambient*.01 + diffuseComp)*this->MaterialColor[2] + specularComp; if (intensity[0] > 1) { intensity[0] = 1; } if (intensity[1] > 1) { intensity[1] = 1; } if (intensity[2] > 1) { intensity[2] = 1; } r = static_cast(255 * intensity[0]); g = static_cast(255 * intensity[1]); b = static_cast(255 * intensity[2]); a = 255; } else { a = (int)(this->GridOpacity * 255); iGrid = i / (size/8); jGrid = j / (size/8); if (((iGrid / 2) * 2 == iGrid && (jGrid / 2) * 2 == jGrid) || ((iGrid / 2) * 2 != iGrid && (jGrid / 2) * 2 != jGrid)) { r = g = b = 0; } else { r = g = b = 255; } } data[(i*size+j) * pixel_size] = r; data[(i*size+j) * pixel_size + 1] = g; data[(i*size+j) * pixel_size + 2] = b; if (pixel_size > 3) { data[(i*size+j) * pixel_size + 3] = a; } } } } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::SetPropertyChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->PropertyChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::InvokePropertyChangedCommand() { this->InvokeObjectMethodCommand(this->PropertyChangedCommand); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::SetPropertyChangingCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->PropertyChangingCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::InvokePropertyChangingCommand() { this->InvokeObjectMethodCommand(this->PropertyChangingCommand); } //---------------------------------------------------------------------------- void vtkKWMaterialPropertyWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "PopupMode: " << (this->PopupMode ? "On" : "Off") << endl; os << indent << "PreviewSize: " << this->PreviewSize << endl; os << indent << "PresetSize: " << this->PresetSize << endl; os << indent << "PopupPreviewSize: " << this->PopupPreviewSize << endl; os << indent << "GridOpacity: " << this->GridOpacity << endl; os << indent << "PropertyChangedEvent: " << this->PropertyChangedEvent << endl; os << indent << "PropertyChangingEvent: " << this->PropertyChangingEvent << endl; os << indent << "MaterialColor: " << this->MaterialColor[0] << " " << this->MaterialColor[1] << " " << this->MaterialColor[2] << endl; os << indent << "LightingParametersVisibility: " << (this->LightingParametersVisibility ? "On" : "Off") << endl; os << indent << "PopupButton: "; if (this->PopupButton) { os << endl; this->PopupButton->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWScaleWithEntry.h0000644000175000017500000003527510551257663021154 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWScaleWithEntry.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWScaleWithEntry - a scale widget with a label and entry // .SECTION Description // A widget that represents a more complex scale (or slider) with options for // positioning a label, displaying an entry, working in popup mode, etc. // For a more lightweight widget, check vtkKWScale. // The label position and visibility can be changed through the // vtkKWWidgetWithLabel superclass methods (see SetLabelPosition). // The default position for the label is on the left of the scale for // horizontal scales, on the right (top corner) for vertical ones. // The default position for the entry is on the right of the scale for // horizontal scales, on the right (bottom corner) for vertical ones. // Both label and entry are visible by default. // For convenience purposes, an empty label is not displayed though (make // sure you use the SetLabelText method to set the label). // In popup mode, a small button replaces the scale. Pressing that button // will popup a scale the user can interact with, until it leaves the scale // focus, which will withdraw the popup automatically. In that mode, the // label and entry position are always displayed side by side, horizontally. // Many of the vtkKWScale methods have been added to this API for // convenience purposes, but GetScale() can be used to retrieve the // internal vtkKWScale and access the rest of the API. // .SECTION See Also // vtkKWScale vtkKWScaleWithLabel vtkKWWidgetWithLabel #ifndef __vtkKWScaleWithEntry_h #define __vtkKWScaleWithEntry_h #include "vtkKWScaleWithLabel.h" class vtkKWEntry; class vtkKWLabel; class vtkKWPushButton; class vtkKWTopLevel; class KWWidgets_EXPORT vtkKWScaleWithEntry : public vtkKWScaleWithLabel { public: static vtkKWScaleWithEntry* New(); vtkTypeRevisionMacro(vtkKWScaleWithEntry,vtkKWScaleWithLabel); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set the range for this scale. virtual void SetRange(double min, double max); virtual void SetRange(const double *range) { this->SetRange(range[0], range[1]); }; virtual double *GetRange(); virtual void GetRange(double &min, double &max); virtual void GetRange(double range[2]) { this->GetRange(range[0], range[1]); }; virtual double GetRangeMin() { return this->GetRange()[0]; }; virtual double GetRangeMax() { return this->GetRange()[1]; }; // Description: // Set/Get the value of the scale. virtual void SetValue(double v); virtual double GetValue(); // Description: // Set/Get the resolution of the slider. virtual void SetResolution(double r); virtual double GetResolution(); // Description: // Turn on/off the automatic clamping of the end values when the // user types a value beyond the range. Default is on. virtual void SetClampValue(int); virtual int GetClampValue(); vtkBooleanMacro(ClampValue, int); // Description: // Get the internal vtkKWScale. // Retrive that object to set the resolution, range, value, etc. virtual vtkKWScale* GetScale() { return this->GetWidget(); }; // Description: // Set/Get whether to display the range of the scale. // If the scale orientation is horizontal, the min is displayed on the // left of the scale, the max range on the right. For vertical orientation, // min is on top, max at the bottom. In popup mode, the range is // displayed directly in the popup window using the same layout as above. void SetRangeVisibility(int flag); vtkGetMacro(RangeVisibility, int); vtkBooleanMacro(RangeVisibility, int); // Description: // Set/Get the internal entry visibility (On by default). // IMPORTANT: if you know you may not show the entry, try to // set that flag as early as possible (ideally, before calling Create()) // in order to lower the footprint of the widget: the entry will not be // allocated and created if there is no need to show it. // Later on, you can still use that option to show the entry: it will be // allocated and created on the fly. virtual void SetEntryVisibility(int); vtkBooleanMacro(EntryVisibility, int); vtkGetMacro(EntryVisibility, int); // Description: // Set the contents label. // IMPORTANT: this method will create the label on the fly, use it only if // you are confident that you will indeed display the label. // Override the superclass so that the label is packed/unpacked if the // text value is an empty string. virtual void SetLabelText(const char *); // Description: // Get the internal entry. // IMPORTANT: the internal entry is "lazy created", i.e. it is neither // allocated nor created until GetEntry() is called. This allows // for a lower footprint and faster UI startup. Therefore, do *not* use // GetEntry() to check if the entry exists, as it will automatically // allocate the entry. Use HasEntry() instead. virtual vtkKWEntry* GetEntry(); virtual int HasEntry(); // Description: // Set/Get the entry width. // IMPORTANT: this method will create the entry on the fly, use it only if // you are confident that you will indeed display the entry. virtual void SetEntryWidth(int width); virtual int GetEntryWidth(); // Description: // If supported, set the entry position in regards to the rest of // the composite widget. Check the subclass for more information about // what the Default position is, and if specific positions are supported. // The default position for the entry is on the right of the scale for // horizontal scales, on the right (bottom corner) for vertical ones. // Remember that the label position and visibility can also be changed // through the vtkKWWidgetWithLabel superclass methods (SetLabelPosition). //BTX enum { EntryPositionDefault = 0, EntryPositionTop, EntryPositionBottom, EntryPositionLeft, EntryPositionRight }; //ETX virtual void SetEntryPosition(int); vtkGetMacro(EntryPosition, int); virtual void SetEntryPositionToDefault() { this->SetEntryPosition(vtkKWScaleWithEntry::EntryPositionDefault); }; virtual void SetEntryPositionToTop() { this->SetEntryPosition(vtkKWScaleWithEntry::EntryPositionTop); }; virtual void SetEntryPositionToBottom() { this->SetEntryPosition(vtkKWScaleWithEntry::EntryPositionBottom); }; virtual void SetEntryPositionToLeft() { this->SetEntryPosition(vtkKWScaleWithEntry::EntryPositionLeft); }; virtual void SetEntryPositionToRight() { this->SetEntryPosition(vtkKWScaleWithEntry::EntryPositionRight); }; // Description: // Set both the label and entry position to the top of the scale // (label in the left corner, entry in the right corner) virtual void SetLabelAndEntryPositionToTop(); // Description: // Set/Get a popup scale. // WARNING: must be set *before* Create() is called. vtkSetMacro(PopupMode, int); vtkGetMacro(PopupMode, int); vtkBooleanMacro(PopupMode, int); vtkGetObjectMacro(PopupPushButton, vtkKWPushButton); // Description: // Set/Get the entry expansion flag. This flag is only used if PopupMode // mode is On. In that case, the default behaviour is to provide a widget // as compact as possible, i.e. the Entry won't be expanded if the widget // grows. Set ExpandEntry to On to override this behaviour. virtual void SetExpandEntry(int flag); vtkGetMacro(ExpandEntry, int); vtkBooleanMacro(ExpandEntry, int); // Description: // Set/Get the orientation type. // For widgets that can lay themselves out with either a horizontal or // vertical orientation, such as scales, this option specifies which // orientation should be used. // Valid constants can be found in vtkKWOptions::OrientationType. virtual void SetOrientation(int); virtual int GetOrientation(); virtual void SetOrientationToHorizontal(); virtual void SetOrientationToVertical(); // Description // Set/Get the desired long dimension of the scale. // For vertical scales this is the scale's height, for horizontal scales // it is the scale's width. In pixel. virtual void SetLength(int length); virtual int GetLength(); // Description: // Specifies commands to associate with the widget. // 'Command' is invoked when the widget value is changing (i.e. during // user interaction). // 'StartCommand' is invoked at the beginning of a user interaction with // the widget (when a mouse button is pressed over the widget for example). // 'EndCommand' is invoked at the end of the user interaction with the // widget (when the mouse button is released for example). // 'EntryCommand' is invoked when the widget value is changed using // the text entry. // The need for a 'Command', 'StartCommand' and 'EndCommand' can be // explained as follows: 'EndCommand' can be used to be notified about any // changes made to this widget *after* the corresponding user interaction has // been performed (say, after releasing the mouse button that was dragging // a slider, or after clicking on a checkbutton). 'Command' can be set // *additionally* to be notified about the intermediate changes that // occur *during* the corresponding user interaction (say, *while* dragging // a slider). While setting 'EndCommand' is enough to be notified about // any changes, setting 'Command' is an application-specific choice that // is likely to depend on how fast you want (or can) answer to rapid changes // occuring during a user interaction, if any. 'StartCommand' is rarely // used but provides an opportunity for the application to modify its // state and prepare itself for user-interaction; in that case, the // 'EndCommand' is usually set in a symmetric fashion to set the application // back to its previous state. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // Note that the same events as vtkKWScale are generated, as a convenience. // The following parameters are also passed to the command: // - the current value: double virtual void SetCommand(vtkObject *object, const char *method); virtual void SetStartCommand(vtkObject *object, const char *method); virtual void SetEndCommand(vtkObject *object, const char *method); virtual void SetEntryCommand(vtkObject *object, const char *method); // Description: // Events. IMPORTANT: this widget is a composite widget that assembles // both a vtkKWScale (which can be retrieved using GetScale()) and a // (which can be retrieved using GetEntry()). Events are generated by // both classes separately (see the corresponding class documentation). // HOWEVER, for convenience purposes, an instance of vtkKWScaleWithEntry // will emit (i.e. forward) the events that were sent by its internal // vtkKWScale automatically, just as if they were sent by the instance // itself. Therefore, you do not need to listen to the internal GetScale() // or GetEntry() objects, but to the instance directly. // Check the vtkKWScale documentation for the list of events. // (for example, vtkKWScale::ScaleValueChangingEvent, // vtkKWScale::ScaleValueChangedEvent, // vtkKWScale::ScaleValueStartChangingEvent, etc). // Description: // Set/Get whether the above commands should be called or not. // This make it easier to disable the commands while setting the scale // value for example. virtual void SetDisableCommands(int); virtual int GetDisableCommands(); vtkBooleanMacro(DisableCommands, int); // Description: // Setting this string enables balloon help for this widget. // Override to pass down to children for cleaner behavior virtual void SetBalloonHelpString(const char *str); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void DisplayPopupModeCallback(); virtual void WithdrawPopupModeCallback(); virtual void EntryValueCallback(const char *value); virtual void ScaleValueCallback(double num); // Description: // Add all the default observers needed by that object, or remove // all the observers that were added through AddCallbackCommandObserver. // Subclasses can override these methods to add/remove their own default // observers, but should call the superclass too. virtual void AddCallbackCommandObservers(); virtual void RemoveCallbackCommandObservers(); protected: vtkKWScaleWithEntry(); ~vtkKWScaleWithEntry(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Bind/Unbind all components so that values can be changed, but // no command will be called. void Bind(); void UnBind(); int PopupMode; int RangeVisibility; virtual void InvokeEntryCommand(double value); char *EntryCommand; int EntryVisibility; int EntryPosition; int ExpandEntry; vtkKWTopLevel *TopLevel; vtkKWPushButton *PopupPushButton; vtkKWLabel *RangeMinLabel; vtkKWLabel *RangeMaxLabel; // Description: // Pack or repack the widget. To be implemented by subclasses. virtual void Pack(); // Description: // Create the entry virtual void CreateEntry(); // Description: // Update internal widgets value virtual void UpdateValue(); virtual void SetEntryValue(double num); virtual void UpdateRange(); // Description: // Processes the events that are passed through CallbackCommand (or others). // Subclasses can oberride this method to process their own events, but // should call the superclass too. virtual void ProcessCallbackCommandEvents( vtkObject *caller, unsigned long event, void *calldata); private: // Description: // Internal entry // In 'private:' to allow lazy evaluation. GetEntry() will create the // entry if it does not exist. This allow the object to remain lightweight. vtkKWEntry *Entry; vtkKWScaleWithEntry(const vtkKWScaleWithEntry&); // Not implemented void operator=(const vtkKWScaleWithEntry&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWRenderWidget.h0000644000175000017500000004212311072710121020576 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWRenderWidget.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWRenderWidget - a render widget // .SECTION Description // This class encapsulates a render window, a renderer and several other // objects inside a single widget. Actors and props can be added, // annotations can be set. // .WARNING // This widget set the camera to be in parallel projection mode. // You can change this default (after Create()) by calling: // renderwidget->GetRenderer()->GetActiveCamera()->ParallelProjectionOff(); #ifndef __vtkKWRenderWidget_h #define __vtkKWRenderWidget_h #include "vtkKWCompositeWidget.h" #include "vtkWindows.h" // needed for RECT HDC class vtkCamera; class vtkCornerAnnotation; class vtkProp; class vtkRenderWindow; class vtkRenderer; class vtkTextActor; class vtkKWMenu; class vtkKWRenderWidgetInternals; class vtkRenderWindowInteractor; class KWWidgets_EXPORT vtkKWRenderWidget : public vtkKWCompositeWidget { public: static vtkKWRenderWidget* New(); vtkTypeRevisionMacro(vtkKWRenderWidget, vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Close the widget. // This method brings the widget back to an empty/clean state. // It removes all the actors/props, removes the bindings, resets the // annotations, etc. virtual void Close(); // Description: // Render the scene. virtual void Render(); // Description: // Enable/disable rendering. vtkGetMacro(RenderState, int); vtkSetClampMacro(RenderState, int, 0, 1); vtkBooleanMacro(RenderState, int); // Description: // Set/Get the rendering mode. //BTX enum { InteractiveRender = 0, StillRender = 1, DisabledRender = 2, SingleRender = 3 }; //ETX vtkSetClampMacro(RenderMode, int, vtkKWRenderWidget::InteractiveRender, vtkKWRenderWidget::SingleRender); vtkGetMacro(RenderMode, int); virtual void SetRenderModeToInteractive() { this->SetRenderMode(vtkKWRenderWidget::InteractiveRender); }; virtual void SetRenderModeToStill() { this->SetRenderMode(vtkKWRenderWidget::StillRender); }; virtual void SetRenderModeToSingle() { this->SetRenderMode(vtkKWRenderWidget::SingleRender); }; virtual void SetRenderModeToDisabled() { this->SetRenderMode(vtkKWRenderWidget::DisabledRender); }; // Description: // Set/Get the collapsing of renders. If this is set to true, then // all call to Render() will be collapsed. Once this is set to false, if // there are any pending render requests, the widget will render. virtual void SetCollapsingRenders(int); vtkBooleanMacro(CollapsingRenders, int); vtkGetMacro(CollapsingRenders, int); // Description: // Reset the widget. // This implementation calls ResetCamera() and Render(). virtual void Reset(); // Description: // Reset the camera to display all the actors in the scene, or just // the camera clipping range. // This is done for each renderer (if multiple renderers are supported). // Note that no default renderers exist before Create() is called. virtual void ResetCamera(); virtual void ResetCameraClippingRange(); // Description: // Add/remove the widget bindings. // The AddBindings() method sets up general bindings like the Expose or // Configure events so that the scene is rendered properly when the widget // is mapped to the screen. It also calls the AddInteractionBindings() // which sets up interaction bindings like mouse events, keyboard events, // etc. The AddBindings() method is called automatically when the widget // is created by the Create() method. Yet, the methods are public so // that one can temporarily enable or disable the bindings to limit // the interaction with this widget. virtual void AddBindings(); virtual void RemoveBindings(); virtual void AddInteractionBindings(); virtual void RemoveInteractionBindings(); // Description: // Convenience method to set the visibility of all annotations. // Subclasses should override this method to propagate this visibility // flag to their own annotations. virtual void SetAnnotationsVisibility(int v); vtkBooleanMacro(AnnotationsVisibility, int); // Description: // Get and control the corner annotation. Turn SupportCornerAnnotation // to off (on by default) if this widget should not support any corner // annotation (i.e. never display it, and do not populate the annotation // context menu with the corresponding entry). virtual void SetCornerAnnotationVisibility(int v); virtual int GetCornerAnnotationVisibility(); virtual void ToggleCornerAnnotationVisibility(); vtkBooleanMacro(CornerAnnotationVisibility, int); virtual void SetCornerAnnotationColor(double r, double g, double b); virtual void SetCornerAnnotationColor(double *rgb) { this->SetCornerAnnotationColor(rgb[0], rgb[1], rgb[2]); }; virtual double* GetCornerAnnotationColor(); vtkGetObjectMacro(CornerAnnotation, vtkCornerAnnotation); vtkGetMacro(SupportCornerAnnotation, int); virtual void SetSupportCornerAnnotation(int); vtkBooleanMacro(SupportCornerAnnotation, int); // Description: // Get and control the header annotation. virtual void SetHeaderAnnotationVisibility(int v); virtual int GetHeaderAnnotationVisibility(); virtual void ToggleHeaderAnnotationVisibility(); vtkBooleanMacro(HeaderAnnotationVisibility, int); virtual void SetHeaderAnnotationColor(double r, double g, double b); virtual void SetHeaderAnnotationColor(double *rgb) { this->SetHeaderAnnotationColor(rgb[0], rgb[1], rgb[2]); }; virtual double* GetHeaderAnnotationColor(); virtual void SetHeaderAnnotationText(const char*); virtual char* GetHeaderAnnotationText(); vtkGetObjectMacro(HeaderAnnotation, vtkTextActor); // Description: // Set/Get the distance units that pixel sizes are measured in virtual void SetDistanceUnits(const char*); vtkGetStringMacro(DistanceUnits); // Description: // Get the render window, get the renderwindow interactor vtkGetObjectMacro(RenderWindow, vtkRenderWindow); virtual vtkRenderWindowInteractor* GetRenderWindowInteractor(); // Description: // Get the VTK widget vtkGetObjectMacro(VTKWidget, vtkKWCoreWidget); // Description: // If the widget supports multiple renderers: // GetNthRenderer() gets the Nth renderer (or NULL if it does not exist), // GetRendererIndex() gets the id of a given renderer (or -1 if this renderer // does not belong to this widget), i.e. its index/position in the list // of renderers. AddRenderer() will add a renderer, RemoveAllRenderers will // remove all renderers. // Note that no default renderers exist before Create() is called. virtual vtkRenderer* GetRenderer() { return this->GetNthRenderer(0); } virtual vtkRenderer* GetNthRenderer(int index); virtual int GetNumberOfRenderers(); virtual int GetRendererIndex(vtkRenderer*); virtual void AddRenderer(vtkRenderer*); virtual void RemoveRenderer(vtkRenderer*); virtual void RemoveNthRenderer(int index); virtual void RemoveAllRenderers(); // Description: // Get the overlay renderer. // Note that no default overlay renderer exist before Create() is called. virtual vtkRenderer* GetOverlayRenderer() { return this->GetNthOverlayRenderer(0); } virtual vtkRenderer* GetNthOverlayRenderer(int index); virtual int GetNumberOfOverlayRenderers(); virtual int GetOverlayRendererIndex(vtkRenderer*); virtual void AddOverlayRenderer(vtkRenderer*); virtual void RemoveOverlayRenderer(vtkRenderer*); virtual void RemoveNthOverlayRenderer(int index); virtual void RemoveAllOverlayRenderers(); // Description: // Set the backgrounds color of the renderer(s) (not the overlay ones). // Note that no default renderers exist before Create() is called. virtual void GetRendererBackgroundColor(double *r, double *g, double *b); virtual void SetRendererBackgroundColor(double r, double g, double b); virtual void SetRendererBackgroundColor(double rgb[3]) { this->SetRendererBackgroundColor(rgb[0], rgb[1], rgb[2]); }; virtual void GetRendererBackgroundColor2(double *r, double *g, double *b); virtual void SetRendererBackgroundColor2(double r, double g, double b); virtual void SetRendererBackgroundColor2(double rgb[3]) { this->SetRendererBackgroundColor2(rgb[0], rgb[1], rgb[2]); }; virtual void SetRendererGradientBackground(int); virtual int GetRendererGradientBackground(); virtual void ToggleRendererGradientBackground(); // Description: // Add props (actors) to *all* widget renderer(s) or *all* overlay // renderer(s), or to specific ones. // Note that no default renderers exist before Create() is called. virtual void AddViewProp(vtkProp *prop); virtual void AddViewPropToNthRenderer(vtkProp *p, int index); virtual void AddOverlayViewProp(vtkProp *prop); virtual void AddViewPropToNthOverlayRenderer(vtkProp *p, int index); // Description: // Query/remove props (actors) from both renderer(s) and overlay renderer(s). virtual int HasViewProp(vtkProp *prop); virtual void RemoveViewProp(vtkProp *prop); virtual void RemoveAllViewProps(); // Description: // The ComputeVisiblePropBounds() method returns the bounds of the // visible props for a renderer (given its index). By default, it is just // a call to vtkRenderer::ComputeVisiblePropBounds(). virtual void ComputeVisiblePropBounds(int index, double bounds[6]); // Description: // Set/Get the printing flag (i.e., are we printing?) virtual void SetPrinting(int arg); vtkBooleanMacro(Printing, int); vtkGetMacro(Printing, int); // Description: // Set/Get offscreen rendering flag (e.g., for screenshots) vtkBooleanMacro(OffScreenRendering, int); virtual void SetOffScreenRendering(int); virtual int GetOffScreenRendering(); // Description: // Use a context menu. It is posted by a right click, and allows // properties and mode to be controlled. vtkSetMacro(UseContextMenu, int); vtkGetMacro(UseContextMenu, int); vtkBooleanMacro(UseContextMenu, int); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Overridden for debugging purposes. This class is usually the center of the // whole "a vtkTkRenderWidget is being destroyed before its render window" // problem. virtual void Register(vtkObjectBase* o); virtual void UnRegister(vtkObjectBase* o); // Description: // Setup print parameters #if defined(_WIN32) && !defined(__CYGWIN__) virtual void SetupPrint(RECT &rcDest, HDC ghdc, int printerPageSizeX, int printerPageSizeY, int printerDPIX, int printerDPIY, float scaleX, float scaleY, int screenSizeX, int screenSizeY); #endif // Description: // Get memory device context (when rendering to memory) virtual void* GetMemoryDC(); // Description: // Add all the default observers needed by that object, or remove // all the observers that were added through AddCallbackCommandObserver. // Subclasses can override these methods to add/remove their own default // observers, but should call the superclass too. virtual void AddCallbackCommandObservers(); virtual void RemoveCallbackCommandObservers(); // Description: // Callbacks. Internal, do not use. virtual void MouseMoveCallback( int num, int x, int y, int ctrl, int shift, int alt); virtual void MouseWheelCallback( int delta, int ctrl, int shift, int alt); virtual void MouseButtonPressCallback( int num, int x, int y, int ctrl, int shift, int alt, int repeat); virtual void MouseButtonReleaseCallback( int num, int x, int y, int ctrl, int shift, int alt); virtual void KeyPressCallback( char key, int x, int y, int ctrl, int shift, int alt, char *keysym); virtual void KeyReleaseCallback( char key, int x, int y, int ctrl, int shift, int alt, char *keysym); virtual void ConfigureCallback(int width, int height); virtual void ExposeCallback(); virtual void EnterCallback(int x, int y); virtual void LeaveCallback(int x, int y); virtual void FocusInCallback(); virtual void FocusOutCallback(); virtual int RendererBackgroundColorCallback(); virtual int RendererBackgroundColor2Callback(); virtual void RendererGradientBackgroundCallback(); // Description: // Event list //BTX enum { CornerAnnotationVisibilityChangedEvent = 24000, RendererGradientBackgroundChangedEvent, RendererBackgroundColorChangedEvent, RendererBackgroundColor2ChangedEvent }; //ETX // Description: // Some constants vtkGetStringMacro(RendererBackgroundColorRegKey); vtkSetStringMacro(RendererBackgroundColorRegKey); vtkGetStringMacro(RendererBackgroundColor2RegKey); vtkSetStringMacro(RendererBackgroundColor2RegKey); vtkGetStringMacro(RendererGradientBackgroundRegKey); vtkSetStringMacro(RendererGradientBackgroundRegKey); protected: vtkKWRenderWidget(); ~vtkKWRenderWidget(); // Description: // Create the widget. virtual void CreateWidget(); vtkKWCoreWidget *VTKWidget; vtkRenderWindow *RenderWindow; vtkCornerAnnotation *CornerAnnotation; vtkTextActor *HeaderAnnotation; int RenderMode; int PreviousRenderMode; int InExpose; int RenderState; int Printing; char *DistanceUnits; int CollapsingRenders; int CollapsingRendersCount; // Description: // Create the default renderers inside the render window. // Superclass can override to create different renderers. // It is called by Create(). virtual void CreateDefaultRenderers(); // Description: // Install the renderers inside the render window. // Superclass can override to install them in a different layout. // It is called by Create(). virtual void InstallRenderers(); // Description: // Set the renderers default values (say, default background colors). virtual void SetRenderersDefaultValues(); // Description: // Update the widget according to the units. // Should be called when any units-related ivar has changed. virtual void UpdateAccordingToUnits() {}; // Description: // Setup memory rendering virtual void SetupMemoryRendering(int width, int height, void *cd); virtual void ResumeScreenRendering(); // Description: // Processes the events that are passed through CallbackCommand (or others). // Subclasses can oberride this method to process their own events, but // should call the superclass too. virtual void ProcessCallbackCommandEvents( vtkObject *caller, unsigned long event, void *calldata); // Context menu int UseContextMenu; vtkKWMenu *ContextMenu; // Description: // Populate the context menu that pops up when the user right-clicks on // the render area. // Superclass should override this method to populate this // menu with the commands they feel comfortable exposing to the user. // This implementation is actually split into several methods to help // organizing the menu into several categories. It calls, in that order: // - PopulateContextMenuWithInteractionEntries(): interaction mode // - PopulateContextMenuWithAnnotationEntries(): annotations, 2d text // - PopulateContextMenuWithOptionEntries(): misc. options // - PopulateContextMenuWithCameraEntries(): camera, change viewpoints // - PopulateContextMenuWithColorEntries(): background color, etc. // Each method is passed a pointer to the context menu. // A menu separator is added automatically between each non-empty section. virtual void PopulateContextMenu(vtkKWMenu*); virtual void PopulateContextMenuWithInteractionEntries(vtkKWMenu*) {}; virtual void PopulateContextMenuWithAnnotationEntries(vtkKWMenu*); virtual void PopulateContextMenuWithOptionEntries(vtkKWMenu*) {}; virtual void PopulateContextMenuWithCameraEntries(vtkKWMenu*); virtual void PopulateContextMenuWithColorEntries(vtkKWMenu*); // Description: // Update the render window interactor size virtual void UpdateRenderWindowInteractorSize(int width, int height); // PIMPL Encapsulation for STL containers vtkKWRenderWidgetInternals *Internals; int SupportCornerAnnotation; // Description: // Some constants char *RendererBackgroundColorRegKey; char *RendererBackgroundColor2RegKey; char *RendererGradientBackgroundRegKey; private: vtkKWRenderWidget(const vtkKWRenderWidget&); // Not implemented void operator=(const vtkKWRenderWidget&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWParameterValueFunctionInterface.cxx0000644000175000017500000000333510424463537025054 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWParameterValueFunctionInterface.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWParameterValueFunctionInterface.h" #include "vtkCallbackCommand.h" #include "vtkObjectFactory.h" vtkCxxRevisionMacro(vtkKWParameterValueFunctionInterface, "$Revision: 1.7 $"); //---------------------------------------------------------------------------- void vtkKWParameterValueFunctionInterface::CreateWidget() { this->Superclass::CreateWidget(); } //---------------------------------------------------------------------------- int vtkKWParameterValueFunctionInterface::FunctionLineIsSampledBetweenPoints( int vtkNotUsed(id1), int vtkNotUsed(id2)) { return 0; } //---------------------------------------------------------------------------- int vtkKWParameterValueFunctionInterface::GetFunctionPointId( double parameter, int *id) { int size = this->GetFunctionSize(); double p; for (int i = 0; i < size; i++) { if (this->GetFunctionPointParameter(i, &p) && p == parameter) { *id = i; return 1; } } return 0; } //---------------------------------------------------------------------------- void vtkKWParameterValueFunctionInterface::PrintSelf( ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWToolbarSet.h0000644000175000017500000002244710450314651020307 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWToolbarSet.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWToolbarSet - a "set of toolbars" widget // .SECTION Description // A simple widget representing a set of toolbars.. #ifndef __vtkKWToolbarSet_h #define __vtkKWToolbarSet_h #include "vtkKWCompositeWidget.h" class vtkKWFrame; class vtkKWMenu; class vtkKWSeparator; class vtkKWToolbar; class vtkKWToolbarSetInternals; class KWWidgets_EXPORT vtkKWToolbarSet : public vtkKWCompositeWidget { public: static vtkKWToolbarSet* New(); vtkTypeRevisionMacro(vtkKWToolbarSet,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the frame that can be used as a parent to a toolbar vtkGetObjectMacro(ToolbarsFrame, vtkKWFrame); // Description: // Add a toolbar to the set. // The default_visibility parameter sets the visibility of the toolbar // in the set once it is added (so that it can be added hidden for example, // before its visibility setting is retrieved from the registry). // Return 1 on success, 0 otherwise. virtual int AddToolbar(vtkKWToolbar *toolbar) { return this->AddToolbar(toolbar, 1); }; virtual int AddToolbar(vtkKWToolbar *toolbar, int default_visibility); virtual int HasToolbar(vtkKWToolbar *toolbar); // Description: // Get the n-th toolbar, and the number of toolbars. virtual vtkKWToolbar* GetNthToolbar(int rank); virtual int GetNumberOfToolbars(); // Description: // Remove a toolbar (or all) from the set. // Return 1 on success, 0 otherwise. virtual int RemoveToolbar(vtkKWToolbar *toolbar); virtual void RemoveAllToolbars(); // Description: // Set/Get the aspect of the toolbar (flat or 3D GUI style, or unchanged) // Important: this will *not* override the toolbar aspect of a toolbar // which aspect was already set to 'UnChanged'. virtual void SetToolbarsAspect(int); // Description: // Set/Get the aspect of the widgets (flat, 3D GUI style, or unchanged) // Important: this will *not* override the widgets aspect of a toolbar // which widgets aspect was already set to 'UnChanged'. virtual void SetToolbarsWidgetsAspect(int); // Description: // Set the visibility of a toolbar. virtual void HideToolbar(vtkKWToolbar *toolbar); virtual void ShowToolbar(vtkKWToolbar *toolbar); virtual void SetToolbarVisibility(vtkKWToolbar *toolbar, int flag); virtual int GetToolbarVisibility(vtkKWToolbar *toolbar); virtual void ToggleToolbarVisibility(vtkKWToolbar *toolbar); // Description: // Return the number of visible toolbars virtual int GetNumberOfVisibleToolbars(); // Description: // Set a toolbar's anchor. By default, toolbars are packed from left // to right in the order they were added to the toolbar set, i.e. each // toolbar is "anchored" to the west side of the set. One can change // this anchor on a per-toolbar basis. This means that all toolbars anchored // to the west side will be grouped together on that side, and all toolbars // anchored to the east side will be grouped on the opposite side. Note // though that anchoring acts like a "mirror": packing starts from the // anchor side, progressing towards the middle of the toolbar set (i.e., // toolbars anchored west are packed left to right, toolbars anchored east // are packed right to left, following the order they were inserted in // the set). //BTX enum { ToolbarAnchorWest = 0, ToolbarAnchorEast }; //ETX virtual void SetToolbarAnchor(vtkKWToolbar *toolbar, int anchor); virtual int GetToolbarAnchor(vtkKWToolbar *toolbar); virtual void SetToolbarAnchorToWest(vtkKWToolbar *toolbar) { this->SetToolbarAnchor(toolbar, vtkKWToolbarSet::ToolbarAnchorWest); }; virtual void SetToolbarAnchorToEast(vtkKWToolbar *toolbar) { this->SetToolbarAnchor(toolbar, vtkKWToolbarSet::ToolbarAnchorEast); }; // Description: // Save/Restore the visibility flag of one/all toolbars to/from the registry // Note that the name of each toolbar to save/restore should have been set // for this method to work (see vtkKWToolbar). virtual void SaveToolbarVisibilityToRegistry(vtkKWToolbar *toolbar); virtual void RestoreToolbarVisibilityFromRegistry(vtkKWToolbar *toolbar); virtual void SaveToolbarsVisibilityToRegistry(); virtual void RestoreToolbarsVisibilityFromRegistry(); // Description: // Set/Get if the visibility flag of the toolbars should be saved // or restored to the registry automatically. // It is restored when the toolbar is added, and saved when the visibility // flag is changed. vtkBooleanMacro(SynchronizeToolbarsVisibilityWithRegistry, int); vtkGetMacro(SynchronizeToolbarsVisibilityWithRegistry, int); vtkSetMacro(SynchronizeToolbarsVisibilityWithRegistry, int); // Description: // Create and update a menu that can be used to control the visibility of // all toolbars. // The Populate...() method will repopulate the menu (note that it does // *not* remove all entries, so that this menu can be used for several // toolbar sets). // The Update...() method will update the state of the entries according // to the toolbarsvisibility (the first one will call the second one // automatically). virtual void PopulateToolbarsVisibilityMenu(vtkKWMenu *menu); virtual void UpdateToolbarsVisibilityMenu(vtkKWMenu *menu); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the visibility of a toolbar is changed. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - pointer to the toolbar which visibility changed: vtkKWToolbar* virtual void SetToolbarVisibilityChangedCommand( vtkObject *object, const char *method); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the number of toolbars has changed // (i.e. a toolbar is added or removed). // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetNumberOfToolbarsChangedCommand( vtkObject *object, const char *method); // Description: // Set/Get the visibility of the separator at the bottom of the set virtual void SetBottomSeparatorVisibility(int); vtkBooleanMacro(BottomSeparatorVisibility, int); vtkGetMacro(BottomSeparatorVisibility, int); // Description: // Set/Get the visibility of the separator at the top of the set virtual void SetTopSeparatorVisibility(int); vtkBooleanMacro(TopSeparatorVisibility, int); vtkGetMacro(TopSeparatorVisibility, int); // Description: // Update the toolbar set // (update the enabled state of all toolbars, call PackToolbars(), etc.). virtual void Update(); // Description: // (Re)Pack the toolbars, if needed (if the widget is created, and the // toolbar is created, AddToolbar will pack the toolbar automatically). virtual void Pack(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); protected: vtkKWToolbarSet(); ~vtkKWToolbarSet(); // Description: // Create the widget. virtual void CreateWidget(); vtkKWSeparator *TopSeparator; vtkKWFrame *ToolbarsFrame; vtkKWSeparator *BottomSeparator; int BottomSeparatorVisibility; int TopSeparatorVisibility; int SynchronizeToolbarsVisibilityWithRegistry; char *ToolbarVisibilityChangedCommand; char *NumberOfToolbarsChangedCommand; virtual void InvokeToolbarVisibilityChangedCommand( vtkKWToolbar *toolbar); virtual void InvokeNumberOfToolbarsChangedCommand(); //BTX // A toolbar slot stores a toolbar + some infos class ToolbarSlot { public: int Visibility; int Anchor; vtkKWSeparator *Separator; vtkKWToolbar *Toolbar; }; // PIMPL Encapsulation for STL containers vtkKWToolbarSetInternals *Internals; friend class vtkKWToolbarSetInternals; // Helper methods ToolbarSlot* GetToolbarSlot(vtkKWToolbar *toolbar); //ETX virtual void PackToolbars(); virtual void PackBottomSeparator(); virtual void PackTopSeparator(); private: vtkKWToolbarSet(const vtkKWToolbarSet&); // Not implemented void operator=(const vtkKWToolbarSet&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWWidgetWithSpinButtons.cxx0000644000175000017500000000537710424463541023103 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgetWithSpinButtons.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWWidgetWithSpinButtons.h" #include "vtkKWSpinButtons.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWWidgetWithSpinButtons); vtkCxxRevisionMacro(vtkKWWidgetWithSpinButtons, "$Revision: 1.4 $"); //---------------------------------------------------------------------------- vtkKWWidgetWithSpinButtons::vtkKWWidgetWithSpinButtons() { this->SpinButtons = vtkKWSpinButtons::New(); } //---------------------------------------------------------------------------- vtkKWWidgetWithSpinButtons::~vtkKWWidgetWithSpinButtons() { if (this->SpinButtons) { this->SpinButtons->Delete(); this->SpinButtons = NULL; } } //---------------------------------------------------------------------------- void vtkKWWidgetWithSpinButtons::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Create the spin buttons subwidget this->SpinButtons->SetParent(this); this->SpinButtons->Create(); this->SpinButtons->SetNextCommand(this, "NextValueCallback"); this->SpinButtons->SetPreviousCommand(this, "PreviousValueCallback"); // Subclasses will call this->Pack() here. Not now. // this->Pack(); } //---------------------------------------------------------------------------- void vtkKWWidgetWithSpinButtons::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->SpinButtons); } // --------------------------------------------------------------------------- void vtkKWWidgetWithSpinButtons::SetBalloonHelpString(const char *string) { this->Superclass::SetBalloonHelpString(string); if (this->SpinButtons) { this->SpinButtons->SetBalloonHelpString(string); } } //---------------------------------------------------------------------------- void vtkKWWidgetWithSpinButtons::PrintSelf(ostream& os, vtkIndent indent) { if (this->SpinButtons) { os << endl; this->SpinButtons->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWLoadSaveDialog.cxx0000644000175000017500000000173410602302270021407 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWLoadSaveDialog.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWLoadSaveDialog.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWLoadSaveDialog ); vtkCxxRevisionMacro(vtkKWLoadSaveDialog, "$Revision: 1.58 $"); //---------------------------------------------------------------------------- void vtkKWLoadSaveDialog::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWListBox.h0000644000175000017500000002233510502267136017614 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWListBox.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWListBox - List Box // .SECTION Description // A widget that can have a list of items. // Use vtkKWListBoxWithScrollbars if you need scrollbars. // .SECTION See Also // vtkKWListBoxWithScrollbars #ifndef __vtkKWListBox_h #define __vtkKWListBox_h #include "vtkKWCoreWidget.h" class KWWidgets_EXPORT vtkKWListBox : public vtkKWCoreWidget { public: static vtkKWListBox* New(); vtkTypeRevisionMacro(vtkKWListBox,vtkKWCoreWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the background color of the widget. virtual void GetBackgroundColor(double *r, double *g, double *b); virtual double* GetBackgroundColor(); virtual void SetBackgroundColor(double r, double g, double b); virtual void SetBackgroundColor(double rgb[3]) { this->SetBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget. virtual void GetForegroundColor(double *r, double *g, double *b); virtual double* GetForegroundColor(); virtual void SetForegroundColor(double r, double g, double b); virtual void SetForegroundColor(double rgb[3]) { this->SetForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget when it is disabled. virtual void GetDisabledForegroundColor(double *r, double *g, double *b); virtual double* GetDisabledForegroundColor(); virtual void SetDisabledForegroundColor(double r, double g, double b); virtual void SetDisabledForegroundColor(double rgb[3]) { this->SetDisabledForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the highlight thickness, a non-negative value indicating the // width of the highlight rectangle to draw around the outside of the // widget when it has the input focus. virtual void SetHighlightThickness(int); virtual int GetHighlightThickness(); // Description: // Set/Get the border width, a non-negative value indicating the width of // the 3-D border to draw around the outside of the widget (if such a border // is being drawn; the Relief option typically determines this). virtual void SetBorderWidth(int); virtual int GetBorderWidth(); // Description: // Set/Get the 3-D effect desired for the widget. // The value indicates how the interior of the widget should appear // relative to its exterior. // Valid constants can be found in vtkKWOptions::ReliefType. virtual void SetRelief(int); virtual int GetRelief(); virtual void SetReliefToRaised(); virtual void SetReliefToSunken(); virtual void SetReliefToFlat(); virtual void SetReliefToRidge(); virtual void SetReliefToSolid(); virtual void SetReliefToGroove(); // Description: // Specifies the font to use when drawing text inside the widget. // You can use predefined font names (e.g. 'system'), or you can specify // a set of font attributes with a platform-independent name, for example, // 'times 12 bold'. In this example, the font is specified with a three // element list: the first element is the font family, the second is the // size, the third is a list of style parameters (normal, bold, roman, // italic, underline, overstrike). Example: 'times 12 {bold italic}'. // The Times, Courier and Helvetica font families are guaranteed to exist // and will be matched to the corresponding (closest) font on your system. // If you are familiar with the X font names specification, you can also // describe the font that way (say, '*times-medium-r-*-*-12*'). virtual void SetFont(const char *font); virtual const char* GetFont(); // Description: // Set/Get the one of several styles for manipulating the selection. // Valid constants can be found in vtkKWOptions::SelectionModeType. virtual void SetSelectionMode(int); virtual int GetSelectionMode(); virtual void SetSelectionModeToSingle(); virtual void SetSelectionModeToBrowse(); virtual void SetSelectionModeToMultiple(); virtual void SetSelectionModeToExtended(); // Description: // Specifies whether or not a selection in the widget should also be the X // selection. If the selection is exported, then selecting in the widget // deselects the current X selection, selecting outside the widget deselects // any widget selection, and the widget will respond to selection retrieval // requests when it has a selection. virtual void SetExportSelection(int); virtual int GetExportSelection(); vtkBooleanMacro(ExportSelection, int); // Description: // Get the current selected string in the list. This is used when // Select mode is single or browse. virtual const char *GetSelection(); virtual int GetSelectionIndex(); virtual void SetSelectionIndex(int); // Description: // When selectmode is multiple or extended, then these methods can // be used to set and query the selection. virtual void SetSelectState(int idx, int state); virtual int GetSelectState(int idx); // Description: // Add an entry. virtual void InsertEntry(int index, const char *name); // Description: // Append a unique string to the list. If the string exists, // it will not be appended virtual int AppendUnique(const char* name); // Description: // Append a string to the list. This call does not check if the string // is unique. virtual int Append(const char* name); // Description: // Specifies a command to be invoked when an element is selected/deselected // in the widget. Re-selecting an element will trigger this command too. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetSelectionCommand(vtkObject *object, const char *method); // Description: // Specifies a command to be invoked when the user single-click or // double-click in the listbox. This does *not* imply the selection changed // though (use SetSelectionCommand instead). // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // Set callback for single and double click on a list item. virtual void SetDoubleClickCommand(vtkObject *obj, const char *method); virtual void SetSingleClickCommand(vtkObject *obj, const char *method); // Description: // Events. The ListBoxSelectionChangedEvent is triggered when an element // is selected/deselected in the widget. Re-selecting an element will // trigger this event too. It is similar in concept as the 'SelectionCommand' /// callback but can be used by multiple listeners/observers at a time. //BTX enum { ListBoxSelectionChangedEvent = 10000 }; //ETX // Description: // Get number of items in the list. virtual int GetNumberOfItems(); // Description: // Get the item at the given index. virtual const char* GetItem(int index); // Description: // Returns the index of the first given item. virtual int GetItemIndex(const char* item); // Description: // Delete a range of items in the list. virtual void DeleteRange(int start, int end); // Description: // Delete all items from the list. virtual void DeleteAll(); // Description: // Set the width of the list box. If the width is less than or equal to 0, // then the width is set to the size of the largest string. virtual void SetWidth(int); virtual int GetWidth(); // Description: // Set the height of the list box. If the height is less than or equal to 0, // then the height is set to the size of the number of items in the listbox. virtual void SetHeight(int); virtual int GetHeight(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void SelectionCallback(); protected: vtkKWListBox(); ~vtkKWListBox(); // Description: // Create the widget. virtual void CreateWidget(); char* CurrentSelection; // store last call of CurrentSelection char* Item; // store last call of GetItem char *SelectionCommand; virtual void InvokeSelectionCommand(); private: vtkKWListBox(const vtkKWListBox&); // Not implemented void operator=(const vtkKWListBox&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWStateMachineDOTWriter.cxx0000644000175000017500000002667510661115510022721 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWStateMachineDOTWriter.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWStateMachineDOTWriter.h" #include "vtkObjectFactory.h" #include "vtkKWStateMachine.h" #include "vtkKWStateMachineState.h" #include "vtkKWStateMachineInput.h" #include "vtkKWStateMachineTransition.h" #include "vtkKWStateMachineCluster.h" #include #include #include //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWStateMachineDOTWriter); vtkCxxRevisionMacro(vtkKWStateMachineDOTWriter, "$Revision: 1.4 $"); //---------------------------------------------------------------------------- vtkKWStateMachineDOTWriter::vtkKWStateMachineDOTWriter() { this->GraphLabel = NULL; this->GraphFontName = NULL; this->SetGraphFontName("Helvetica"); this->GraphFontSize = 12; this->GraphFontColor[0] = 0.0; this->GraphFontColor[1] = 0.0; this->GraphFontColor[2] = 0.0; this->GraphDirection = vtkKWStateMachineDOTWriter::GraphDirectionLeftToRight; this->StateFontName = NULL; this->SetStateFontName("Helvetica"); this->StateFontSize = 9; this->StateFontColor[0] = 0.0; this->StateFontColor[1] = 0.0; this->StateFontColor[2] = 0.0; this->InputFontName = NULL; this->SetInputFontName("Helvetica"); this->InputFontSize = 8; this->InputFontColor[0] = 0.0; this->InputFontColor[1] = 0.0; this->InputFontColor[2] = 1.0; this->ClusterFontName = NULL; this->SetClusterFontName("Helvetica"); this->ClusterFontSize = 10; this->ClusterFontColor[0] = 0.0; this->ClusterFontColor[1] = 0.0; this->ClusterFontColor[2] = 0.0; this->PutStatesAtSameRank = 0; this->CommandVisibility = 1; } //---------------------------------------------------------------------------- vtkKWStateMachineDOTWriter::~vtkKWStateMachineDOTWriter() { this->SetGraphLabel(NULL); this->SetGraphFontName(NULL); this->SetStateFontName(NULL); this->SetInputFontName(NULL); this->SetClusterFontName(NULL); } //---------------------------------------------------------------------------- void vtkKWStateMachineDOTWriter::SetGraphDirectionToTopToBottom() { this->SetGraphDirection( vtkKWStateMachineDOTWriter::GraphDirectionTopToBottom); } //---------------------------------------------------------------------------- void vtkKWStateMachineDOTWriter::SetGraphDirectionToLeftToRight() { this->SetGraphDirection( vtkKWStateMachineDOTWriter::GraphDirectionLeftToRight); } //---------------------------------------------------------------------------- int vtkKWStateMachineDOTWriter::WriteToStream(ostream& os) { if (!this->Input) { vtkErrorMacro("Input is not set!"); return 0; } vtkIndent indent; indent = indent.GetNextIndent(); int i, j; // Open graph os << "digraph G {" << endl; if (this->GraphDirection == vtkKWStateMachineDOTWriter::GraphDirectionLeftToRight) { os << indent << "rankdir=LR;" << endl; } else if (this->GraphDirection == vtkKWStateMachineDOTWriter::GraphDirectionTopToBottom) { os << indent << "rankdir=TB;" << endl; } char state_color[10]; sprintf(state_color, "#%02x%02x%02x", (int)(this->StateFontColor[0] * 255.0), (int)(this->StateFontColor[1] * 255.0), (int)(this->StateFontColor[2] * 255.0)); os << indent << "node [fontcolor=\"" << state_color << "\", fontsize=" << this->StateFontSize; if (this->StateFontName) { os << ", fontname=\"" << this->StateFontName << "\""; } os << "];" << endl; char input_color[10]; sprintf(input_color, "#%02x%02x%02x", (int)(this->InputFontColor[0] * 255.0), (int)(this->InputFontColor[1] * 255.0), (int)(this->InputFontColor[2] * 255.0)); os << indent << "edge [fontcolor=\"" << input_color << "\", fontsize=" << this->InputFontSize; if (this->InputFontName) { os << ", fontname=\"" << this->InputFontName << "\""; } os << "];" << endl; // Write all states os << endl; vtksys_ios::ostringstream all_states; int nb_states = this->Input->GetNumberOfStates(); for (i = 0; i < nb_states; i++) { vtkKWStateMachineState *state = this->Input->GetNthState(i); os << indent << state->GetId(); os << " [label=\""; if (state->GetName()) { os << state->GetName(); } else { os << state->GetId(); } if (this->CommandVisibility) { int has_enter = state->HasEnterCommand() || state->HasObserver(vtkKWStateMachineState::EnterEvent); int has_leave = state->HasLeaveCommand() || state->HasObserver(vtkKWStateMachineState::LeaveEvent); if (has_enter || has_leave) { os << "\\n["; if (has_enter) { os << "e"; } if (has_leave) { if (has_enter) { os << "/"; } os << "l"; } os << "]"; } } os << "\""; if (state->GetAccepting()) { os << ", peripheries=2"; } os << "];" << endl; if (this->PutStatesAtSameRank) { all_states << state->GetId() << "; "; } } // Write all transitions os << endl; int nb_transitions = this->Input->GetNumberOfTransitions(); for (i = 0; i < nb_transitions; i++) { vtkKWStateMachineTransition *transition = this->Input->GetNthTransition(i); if (!this->WriteSelfLoop && transition->GetOriginState() == transition->GetDestinationState()) { continue; } os << indent << transition->GetOriginState()->GetId() << " -> " << transition->GetDestinationState()->GetId(); vtkKWStateMachineInput *input = transition->GetInput(); os << " [label=\""; if (input->GetName()) { os << input->GetName(); } else { os << input->GetId(); } if (this->CommandVisibility) { int has_end = transition->HasEndCommand() || transition->HasObserver(vtkKWStateMachineTransition::EndEvent); int has_start = transition->HasStartCommand() || transition->HasObserver(vtkKWStateMachineTransition::StartEvent); if (has_end || has_start) { os << " ["; if (has_start) { os << "s"; } if (has_end) { if (has_start) { os << "/"; } os << "e"; } os << "]"; } } os << "\"];" << endl; } // Write all clusters char cluster_color[10]; sprintf(cluster_color, "#%02x%02x%02x", (int)(this->ClusterFontColor[0] * 255.0), (int)(this->ClusterFontColor[1] * 255.0), (int)(this->ClusterFontColor[2] * 255.0)); int nb_clusters = this->Input->GetNumberOfClusters(); for (i = 0; i < nb_clusters; i++) { os << endl; vtkKWStateMachineCluster *cluster = this->Input->GetNthCluster(i); os << indent << "subgraph cluster" << cluster->GetId() << " {" << endl; vtkIndent next_indent = indent.GetNextIndent(); os << next_indent << "fontcolor=\"" << cluster_color << "\"; " << "fontsize=" << this->ClusterFontSize << "; "; if (this->ClusterFontName) { os << "fontname=\"" << this->ClusterFontName << "\"; "; } os << endl; os << next_indent << "style=dashed;" << endl; os << next_indent << "label=\""; if (cluster->GetName()) { os << cluster->GetName(); } else { os << cluster->GetId(); } os << "\"" << endl; nb_states = cluster->GetNumberOfStates(); os << next_indent; for (j = 0; j < nb_states; j++) { vtkKWStateMachineState *state = cluster->GetNthState(j); os << state->GetId() << "; "; } os << endl; os << indent << "}" << endl; } // Put all states at same rank? if (this->PutStatesAtSameRank) { os << endl; os << indent << "{" << endl; vtkIndent next_indent = indent.GetNextIndent(); os << next_indent << "rank=same;" << endl; os << next_indent << all_states.str().c_str() << endl; os << indent << "}" << endl; } // Label has to be at the end in order to be inherited by subgraphs if (this->GraphLabel) { os << endl; char graph_color[10]; sprintf(graph_color, "#%02x%02x%02x", (int)(this->GraphFontColor[0] * 255.0), (int)(this->GraphFontColor[1] * 255.0), (int)(this->GraphFontColor[2] * 255.0)); os << indent << "fontcolor=\"" << graph_color << "\";" << endl; os << indent << "fontsize=" << this->GraphFontSize << ";" << endl; if (this->GraphFontName) { os << indent << "fontname=\"" << this->GraphFontName << "\";" << endl; } os << indent << "label=\"" << this->GraphLabel << "\";" << endl; } // Close graph os << "}" << endl; return 1; } //---------------------------------------------------------------------------- int vtkKWStateMachineDOTWriter::WriteToFile(const char *filename) { ofstream os(filename, ios::out); int ret = this->WriteToStream(os); if (!ret) { os.close(); vtksys::SystemTools::RemoveFile(filename); } return ret; } //---------------------------------------------------------------------------- void vtkKWStateMachineDOTWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "GraphLabel: " << (this->GraphLabel ? this->GraphLabel : "None") << endl; os << indent << "GraphDirection: " << this->GraphDirection << endl; os << indent << "GraphFontName: " << (this->GraphFontName ? this->GraphFontName : "None") << endl; os << indent << "GraphFontSize: " << this->GraphFontSize << endl; os << indent << "GraphFontColor: (" << this->GraphFontColor[0] << ", " << this->GraphFontColor[1] << ", " << this->GraphFontColor[2] << ")\n"; os << indent << "StateFontName: " << (this->StateFontName ? this->StateFontName : "None") << endl; os << indent << "StateFontSize: " << this->StateFontSize << endl; os << indent << "StateFontColor: (" << this->StateFontColor[0] << ", " << this->StateFontColor[1] << ", " << this->StateFontColor[2] << ")\n"; os << indent << "InputFontName: " << (this->InputFontName ? this->InputFontName : "None") << endl; os << indent << "InputFontSize: " << this->InputFontSize << endl; os << indent << "InputFontColor: (" << this->InputFontColor[0] << ", " << this->InputFontColor[1] << ", " << this->InputFontColor[2] << ")\n"; os << indent << "GraphFontName: " << (this->GraphFontName ? this->GraphFontName : "None") << endl; os << indent << "GraphFontSize: " << this->GraphFontSize << endl; os << indent << "GraphFontColor: (" << this->GraphFontColor[0] << ", " << this->GraphFontColor[1] << ", " << this->GraphFontColor[2] << ")\n"; os << indent << "PutStatesAtSameRank: " << (this->PutStatesAtSameRank ? "On" : "Off") << endl; os << indent << "CommandVisibility: " << (this->CommandVisibility ? "On" : "Off") << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWApplication.cxx0000644000175000017500000026660211305012213021037 0ustar domibeldomibel/*========================================================================= Module: vtkKWApplication.cxx,v Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #ifdef __APPLE__ #include #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 #include #define Cursor X11Cursor #endif #endif // __APPLE__ #include "vtkKWApplication.h" #include "vtkObjectFactory.h" #include "vtkOutputWindow.h" #include "vtkTclUtil.h" #include "vtkKWBalloonHelpManager.h" #include "vtkKWColorPickerDialog.h" #include "vtkKWEntry.h" #include "vtkKWEntryWithLabel.h" #include "vtkKWEvent.h" #include "vtkKWFrame.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWLanguage.h" #include "vtkKWLoadSaveDialog.h" #include "vtkKWLogDialog.h" #include "vtkKWLogWidget.h" #include "vtkKWMessageDialog.h" #include "vtkKWObject.h" #include "vtkKWOptionDataBase.h" #include "vtkKWPushButton.h" #include "vtkKWRegistryHelper.h" #include "vtkKWSeparator.h" #include "vtkKWSplashScreen.h" #include "vtkKWTclInteractor.h" #include "vtkKWText.h" #include "vtkKWTextWithScrollbars.h" #include "vtkKWTheme.h" #include "vtkKWTkUtilities.h" #include "vtkKWTkcon.h" #include "vtkKWToolbar.h" #include "vtkKWWindowBase.h" #include #include #include #include #include #include "Resources/KWWidgets.rc.h" #include "vtkKWWidgetsConfigure.h" #include "vtkKWWidgetsBuildConfigure.h" #include "Resources/vtkKWMiscResources.h" #include "vtkToolkits.h" static Tcl_Interp *Et_Interp = 0; #ifdef KWWidgets_USE_TKDND #include "Utilities/tkdnd/vtkKWTkDnDInit.h" #endif #ifdef KWWidgets_USE_TKTREECTRL #include "Utilities/TkTreeCtrl/vtkKWTkTreeCtrlInit.h" #endif #ifdef _WIN32 #include "vtkWindows.h" #include #include #include #ifdef KWWidgets_USE_HTML_HELP #include #endif #include "Utilities/ApplicationIcon/vtkKWSetApplicationIconTclCommand.h" #endif #ifdef __APPLE__ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 #undef Cursor #endif #endif // __APPLE__ const char *vtkKWApplication::ExitDialogName = "ExitApplication"; const char *vtkKWApplication::SendErrorLogDialogName = "SendErrorLog"; const char *vtkKWApplication::BalloonHelpVisibilityRegKey = "ShowBalloonHelp"; const char *vtkKWApplication::SaveUserInterfaceGeometryRegKey = "SaveUserInterfaceGeometry"; const char *vtkKWApplication::SplashScreenVisibilityRegKey = "ShowSplashScreen"; const char *vtkKWApplication::PrintTargetDPIRegKey = "PrintTargetDPI"; const char *vtkKWApplication::MostRecentVersionLaunchedRegKey = "MostRecentVersionLaunched"; //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWApplication ); vtkCxxRevisionMacro(vtkKWApplication, "$Revision: 1.356 $"); extern "C" int Kwwidgets_Init(Tcl_Interp *interp); // Initialize VTK Tcl. If we have not wrapped VTK for Tcl, then // we can only rely on Common and the two renderwidgets extern "C" int Vtkcommontcl_Init(Tcl_Interp *interp); #ifdef KWWidgets_BUILD_VTK_WIDGETS extern "C" int Vtktkrenderwidget_Init(Tcl_Interp *interp); extern "C" int Vtktkimageviewerwidget_Init(Tcl_Interp *interp); #ifdef VTK_WRAP_TCL extern "C" int Vtkfilteringtcl_Init(Tcl_Interp *interp); extern "C" int Vtkimagingtcl_Init(Tcl_Interp *interp); extern "C" int Vtkgraphicstcl_Init(Tcl_Interp *interp); extern "C" int Vtkiotcl_Init(Tcl_Interp *interp); #ifdef VTK_USE_RENDERING extern "C" int Vtkrenderingtcl_Init(Tcl_Interp *interp); extern "C" int Vtkvolumerenderingtcl_Init(Tcl_Interp *interp); extern "C" int Vtkhybridtcl_Init(Tcl_Interp *interp); extern "C" int Vtkwidgetstcl_Init(Tcl_Interp *interp); #endif // VTK_USE_RENDERING #ifdef VTK_USE_PARALLEL extern "C" int Vtkparalleltcl_Init(Tcl_Interp *interp); #endif // VTK_USE_PARALLEL #endif // VTK_WRAP_TCL #endif // KWWidgets_BUILD_VTK_WIDGETS #ifdef KWWidgets_USE_INCR_TCL extern "C" int Itcl_Init(Tcl_Interp *interp); extern "C" int Itk_Init(Tcl_Interp *interp); #endif //---------------------------------------------------------------------------- class KWWidgets_EXPORT vtkKWOutputWindow : public vtkOutputWindow { public: vtkTypeMacro(vtkKWOutputWindow,vtkOutputWindow); static vtkKWOutputWindow* New(); void DisplayDebugText(const char* t) { this->Application->DebugMessage(t); if (this->PromptUser) { this->Application->DisplayLogDialog(NULL); } } void DisplayWarningText(const char* t) { this->Application->WarningMessage(t); if (this->PromptUser) { this->Application->DisplayLogDialog(NULL); } } void DisplayErrorText(const char* t) { this->Application->ErrorMessage(t); if (this->PromptUser) { this->Application->DisplayLogDialog(NULL); } } void DisplayText(const char* t) { this->Application->InformationMessage(t); if (this->PromptUser) { this->Application->DisplayLogDialog(NULL); } } void DisplayGenericWarningText(const char* t) { this->DisplayWarningText(t); } void SetApplication(vtkKWApplication *app) { this->Application = app; } protected: vtkKWOutputWindow() { this->Application = NULL; } vtkKWApplication *Application; private: vtkKWOutputWindow(const vtkKWOutputWindow&); void operator=(const vtkKWOutputWindow&); }; //---------------------------------------------------------------------------- class vtkKWApplicationInternals { public: typedef vtksys_stl::vector WindowsContainer; typedef vtksys_stl::vector::iterator WindowsContainerIterator; WindowsContainer Windows; // Some temporary storage var that do not need to be exposed in the .h vtksys_stl::string VersionNameTemp; vtksys_stl::string LimitedEditionModeNameTemp; vtksys_stl::string RegistryVersionNameTemp; // For ::PutEnv class DeletingCharVector : public vtksys_stl::vector { public: ~DeletingCharVector() { for(vtksys_stl::vector::iterator i = this->begin(); i != this->end(); ++i) { delete []*i; } } }; vtkOutputWindow *PreviousOutputWindow; vtkKWOutputWindow *LogOutputWindow; }; vtkStandardNewMacro(vtkKWOutputWindow); //---------------------------------------------------------------------------- vtkKWApplication::vtkKWApplication() { /* IMPORTANT: Do *ALL* simple inits *first* before a possible early return due to an error condition. Avoids crashing during destructor when some members have not been properly NULL initialized... */ this->Internals = NULL; this->MajorVersion = 1; this->MinorVersion = 0; this->Name = NULL; this->VersionName = NULL; this->ReleaseName = NULL; this->PrettyName = NULL; this->ReleaseMode = 0; this->RegistryVersionName = NULL; this->LimitedEditionMode = 0; this->LimitedEditionModeName = NULL; this->HelpDialogStartingPage = NULL; this->TutorialStartingPage = NULL; this->InstallationDirectory = NULL; this->UserDataDirectory = NULL; this->EmailFeedbackAddress = NULL; this->InExit = 0; this->ExitStatus = 0; this->ExitAfterLoadScript = 0; this->PromptBeforeExit = 1; this->SendErrorLogBeforeExit = 0; this->DialogUp = 0; this->SaveUserInterfaceGeometry = 1; this->RegistryHelper = NULL; this->OptionDataBase = NULL; this->RegistryLevel = 10; this->BalloonHelpManager = NULL; this->CharacterEncoding = VTK_ENCODING_UNKNOWN; this->AboutDialog = NULL; this->AboutDialogImage = NULL; this->AboutRuntimeInfo = NULL; this->SplashScreen = NULL; this->SupportSplashScreen = 0; this->SplashScreenVisibility = 1; this->PrintTargetDPI = 100.0; this->Theme = NULL; this->LogDialog = NULL; this->TclInteractor = NULL; this->ColorPickerDialog = NULL; /* IMPORTANT: Do *NOT* call anything that retrieves the application's TclName. Doing so will force a mapping between a Tcl object and this class with the wrong command function, i.e. a Tcl object will be created and mapped to a vtkKWApplication Tcl command. As a result, any subclass vtkFoo of vtkKWApplication will appear to be a vtkKWApplication instead of a vtkFoo, and will be missing all the corresponding wrapped methods. */ // Setup Tcl if (!this->GetMainInterp()) { vtkErrorMacro( "Interpreter not set. This probably means that Tcl was not " "initialized properly..."); return; } // Instantiate the PIMPL Encapsulation for STL containers this->Internals = new vtkKWApplicationInternals; // Output win this->InstallOutputWindow(); // Application name and version // Try to find if we are running from a script and set the application name // accordingly. Otherwise try to find the executable name. vtksys_stl::string script = vtksys::SystemTools::GetFilenameWithoutExtension( vtksys::SystemTools::GetFilenameName( vtkKWTkUtilities::GetCurrentScript(this->GetMainInterp()))); if (script.size()) { this->Name = vtksys::SystemTools::DuplicateString(script.c_str()); } else { const char *nameofexec = Tcl_GetNameOfExecutable(); if (nameofexec && vtksys::SystemTools::FileExists(nameofexec)) { vtksys_stl::string filename = vtksys::SystemTools::GetFilenameName(nameofexec); vtksys_stl::string filenamewe = vtksys::SystemTools::GetFilenameWithoutExtension(filename); if (!vtksys::SystemTools::StringStartsWith(filenamewe.c_str(), "wish") && !vtksys::SystemTools::StringStartsWith(filenamewe.c_str(), "tclsh")) { this->Name = vtksys::SystemTools::DuplicateString(filenamewe.c_str()); } } } // Still no name... use default... if (!this->Name) { this->Name = vtksys::SystemTools::DuplicateString("Sample Application"); } // Encoding... this->SetCharacterEncoding(VTK_ENCODING_ISO_8859_1); vtksys::SystemTools::EnableMSVCDebugHook(); if (this->ReleaseMode) { vtkObject::GlobalWarningDisplayOff(); } } //---------------------------------------------------------------------------- vtkKWApplication::~vtkKWApplication() { this->PrepareForDelete(); delete this->Internals; this->Internals = NULL; vtkObjectFactory::UnRegisterAllFactories(); this->SetLimitedEditionModeName(NULL); this->SetName(NULL); this->SetVersionName(NULL); this->SetReleaseName(NULL); this->SetPrettyName(NULL); this->SetRegistryVersionName(NULL); this->SetInstallationDirectory(NULL); this->SetUserDataDirectory(NULL); this->SetEmailFeedbackAddress(NULL); this->SetHelpDialogStartingPage(NULL); this->SetTutorialStartingPage(NULL); if (this->RegistryHelper ) { this->RegistryHelper->Delete(); this->RegistryHelper = NULL; } if (this->OptionDataBase ) { this->OptionDataBase->Delete(); this->OptionDataBase = NULL; } } //---------------------------------------------------------------------------- void vtkKWApplication::PrepareForDelete() { if (this->AboutDialogImage) { this->AboutDialogImage->Delete(); this->AboutDialogImage = NULL; } if (this->AboutRuntimeInfo) { this->AboutRuntimeInfo->Delete(); this->AboutRuntimeInfo = NULL; } if (this->AboutDialog) { this->AboutDialog->Delete(); this->AboutDialog = NULL; } if (this->SplashScreen) { this->SplashScreen->Delete(); this->SplashScreen = NULL; } if (this->TclInteractor) { this->TclInteractor->SetMasterWindow(NULL); this->TclInteractor->Delete(); this->TclInteractor = NULL; } if (this->ColorPickerDialog) { this->ColorPickerDialog->SetMasterWindow(NULL); this->ColorPickerDialog->Delete(); this->ColorPickerDialog = NULL; } // vtkKWOutputWindow is actually using the LogDialog, so before deleting // it, just switch back to the previous output window this->RestoreOutputWindow(); if (this->LogDialog) { this->LogDialog->Delete(); this->LogDialog = NULL; } if (this->BalloonHelpManager ) { this->BalloonHelpManager->Delete(); this->BalloonHelpManager = NULL; } if (this->GetMainInterp()) { vtkKWTkUtilities::CancelAllTimerHandlers(this->GetMainInterp()); } } //---------------------------------------------------------------------------- void vtkKWApplication::InstallOutputWindow() { this->Internals->PreviousOutputWindow = vtkOutputWindow::GetInstance(); this->Internals->PreviousOutputWindow->Register(this); this->Internals->LogOutputWindow = vtkKWOutputWindow::New(); this->Internals->LogOutputWindow->SetApplication(this); vtkOutputWindow::SetInstance(this->Internals->LogOutputWindow); } //---------------------------------------------------------------------------- void vtkKWApplication::RestoreOutputWindow() { if (this->Internals->LogOutputWindow) { if (vtkOutputWindow::GetInstance() == this->Internals->LogOutputWindow) { vtkOutputWindow::SetInstance(this->Internals->PreviousOutputWindow); } this->Internals->PreviousOutputWindow->Delete(); this->Internals->LogOutputWindow->Delete(); this->Internals->LogOutputWindow = NULL; } } //---------------------------------------------------------------------------- void vtkKWApplication::SetApplication(vtkKWApplication*) { vtkErrorMacro( << "Do not set the Application on an Application" << endl); } //---------------------------------------------------------------------------- int vtkKWApplication::AddWindow(vtkKWWindowBase *win) { if (this->Internals) { this->Internals->Windows.push_back(win); win->Register(this); if (!win->GetApplication()) { win->SetApplication(this); } return 1; } return 0; } //---------------------------------------------------------------------------- int vtkKWApplication::RemoveWindow(vtkKWWindowBase *win) { // If this is the last window, go straight to Exit. // This will give the app a chance to ask the user for confirmation. // It is likely that this method has been called by vtkKWWindowBase::Close(). // In that case, Exit() will call vtkKWWindowBase::Close() *again*, and we // will be back here, but this won't infinite loop since this->Exit() // will return false (as we are already "exiting", check this->InExit) if (this->GetNumberOfWindows() <= 1) { // We managed to exit right away if (this->Exit()) { return 1; } // we could not exit, but not because we were already exiting, but // because of other factors like errors or user not confirming if (!this->InExit) { return 0; } } if (this->Internals && win) { vtkKWApplicationInternals::WindowsContainerIterator it = vtksys_stl::find(this->Internals->Windows.begin(), this->Internals->Windows.end(), win); if (it != this->Internals->Windows.end()) { win->Withdraw(); win->PrepareForDelete(); win->UnRegister(this); this->Internals->Windows.erase(it); return 1; } } return 0; } //---------------------------------------------------------------------------- vtkKWWindowBase* vtkKWApplication::GetNthWindow(int rank) { if (this->Internals && rank >= 0 && rank < this->GetNumberOfWindows()) { return this->Internals->Windows[rank]; } return NULL; } //---------------------------------------------------------------------------- int vtkKWApplication::GetNumberOfWindows() { if (this->Internals) { return (int)this->Internals->Windows.size(); } return 0; } //---------------------------------------------------------------------------- int vtkKWApplication::GetNumberOfWindowsMapped() { int i, nb_windows = this->GetNumberOfWindows(), count = 0; for (i = 0; i < nb_windows; i++) { vtkKWWindowBase *win = this->GetNthWindow(i); if (win && win->IsMapped()) { ++count; } } return count; } //---------------------------------------------------------------------------- int vtkKWApplication::Exit() { // Avoid a recursive exit. if (this->InExit) { return 0; } // Send error log if (this->SendErrorLogBeforeExit) { this->SendErrorLog(); } // If a dialog is still up, complain and bail if (this->IsDialogUp()) { vtkKWTkUtilities::Bell(this->GetMainInterp()); return 0; } // Prompt confirmation if needed // Let's just use the first window here, if any, to center the dialog if (this->PromptBeforeExit && !this->DisplayExitDialog(this->GetNthWindow(0))) { return 0; } this->InExit = 1; // I guess it does not hurt to save the application settings now // In order to restore them, the RestoreApplicationSettingsFromRegistry() // method should be called before the Start() method is invoked. // It can not be called in the constructore since the application name // is required. It also should probably be called after any command // line argument parsing that would change the registry level. this->SaveApplicationSettingsToRegistry(); // Close all windows // This loop might be a little dangerous if a window never closes... // We could loop over the given number of window, and test if there // are still windows left at the end (= error) while (this->GetNumberOfWindows()) { vtkKWWindowBase *win = this->GetNthWindow(0); if (win) { win->SetPromptBeforeClose(0); win->Close(); } } // This call has to be here, not before the previous loop, so that // for example, the balloon help manager is not destroyed before // all windows are removed (in some rare occasions, a user can be fast // enough to quit the app while moving the mouse on a widget that // has a binding to the balloon help manager this->PrepareForDelete(); return 1; } //---------------------------------------------------------------------------- Tcl_Interp *vtkKWApplication::InitializeTcl(int argc, char *argv[], ostream *err) { // Command line args: language // This is also done in Start(), but this is should be as early // as we can change the language. int index = 0, pos = 0; if (vtkKWApplication::CheckForValuedArgument( argc, argv, "--lang", index, pos) == VTK_OK) { vtkKWLanguage::SetCurrentLanguage( vtkKWLanguage::GetLanguageFromXPG(argv[index] + pos)); } Tcl_Interp *interp; char *args; char buf[100]; (void)err; // The call to Tcl_FindExecutable has to be executed *now*, it does more // than just finding the executable (for ex:, it will set variables // depending on the value of TCL_LIBRARY, TK_LIBRARY) vtkTclApplicationInitExecutable(argc, argv); // Create the interpreter interp = Tcl_CreateInterp(); args = Tcl_Merge(argc - 1, argv + 1); Tcl_SetVar(interp, (char *)"argv", args, TCL_GLOBAL_ONLY); ckfree(args); sprintf(buf, "%d", argc-1); Tcl_SetVar(interp, (char *)"argc", buf, TCL_GLOBAL_ONLY); Tcl_SetVar(interp, (char *)"argv0", argv[0], TCL_GLOBAL_ONLY); Tcl_SetVar(interp, (char *)"tcl_interactive", (char *)"0", TCL_GLOBAL_ONLY); #ifdef __CYGWIN__ Tcl_SetVar(interp, "tclDefaultLibrary", "/usr/share/tcl" TCL_VERSION, TCL_GLOBAL_ONLY); #endif const char* relative_dirs[] = { "lib", "../lib", "../../lib", "lib/TclTk", "../lib/TclTk", "../../lib/TclTk", "lib/TclTk/lib", "../lib/TclTk/lib", "../../lib/TclTk/lib", ".." KWWidgets_TclTk_INSTALL_LIB_DIR, // for exe in PREFIX/bin "../.." KWWidgets_TclTk_INSTALL_LIB_DIR, // for exe in PREFIX/lib/foo-V.v 0 }; vtkTclApplicationInitTclTk(interp, relative_dirs); Tcl_Interp *res = vtkKWApplication::InitializeTcl(interp, err); // If we are on Windows, bring a win32 message box since cerr is not // redirected to the command prompt. #ifdef _WIN32 if (!res && err) { MessageBox(NULL, k_("The application failed to initialize Tcl/Tk!"), k_("Initialization Error!"), MB_ICONERROR | MB_OK); } #endif return res; } //---------------------------------------------------------------------------- Tcl_Interp *vtkKWApplication::InitializeVTK(Tcl_Interp *interp, ostream *err) { // Initialize VTK if (Vtkcommontcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkcommontcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } #ifdef KWWidgets_BUILD_VTK_WIDGETS if (Vtktkrenderwidget_Init(interp) != TCL_OK) { if (err) { *err << "Vtktkrenderwidget_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } if (Vtktkimageviewerwidget_Init(interp) != TCL_OK) { if (err) { *err << "Vtktkimageviewerwidget_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } #ifdef VTK_WRAP_TCL if (Vtkfilteringtcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkfilteringtcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } if (Vtkimagingtcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkimagingtcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } if (Vtkgraphicstcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkgraphicstcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } if (Vtkiotcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkiotcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } #ifdef VTK_USE_RENDERING if (Vtkrenderingtcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkrenderingtcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } if (Vtkvolumerenderingtcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkvolumerenderingtcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } if (Vtkhybridtcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkhybridtcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } if (Vtkwidgetstcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkwidgetstcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } #endif // VTK_USE_RENDERING #ifdef VTK_USE_PARALLEL if (Vtkparalleltcl_Init(interp) != TCL_OK) { if (err) { *err << "Vtkparalleltcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } #endif // VTK_USE_PARALLEL #endif // VTK_WRAP_TCL #endif // KWWidgets_BUILD_VTK_WIDGETS return interp; } //---------------------------------------------------------------------------- Tcl_Interp *vtkKWApplication::InitializeTcl(Tcl_Interp *interp, ostream *err) { // As a convenience, try to find the text domain binding for // KWWidgets right now vtkKWInternationalization::FindTextDomainBinding( "KWWidgets", KWWidgets_INSTALL_DATA_DIR); if (Et_Interp) { return NULL; } // Init Tcl Et_Interp = interp; int status; status = Tcl_Init(interp); if (status != TCL_OK) { if (err) { *err << "Tcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } // Init Tk if (!Tcl_PkgPresent(interp, "Tk", NULL, 0)) { status = Tk_Init(interp); if (status != TCL_OK) { if (err) { *err << "Tk_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } Tcl_StaticPackage(interp, (char *)"Tk", Tk_Init, 0); } // As a convenience, withdraw the main Tk toplevel Tcl_GlobalEval(interp, "wm withdraw ."); // Create the SetApplicationIcon command #ifdef _WIN32 vtkKWSetApplicationIconTclCommand_DoInit(interp); #endif #ifdef KWWidgets_USE_INCR_TCL // Initialize [incr Tcl] if (!Tcl_PkgPresent(interp, "Itcl", NULL, 0)) { status = Itcl_Init(interp); if (status != TCL_OK) { if (err) { *err << "Itcl_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } } // Initialize [incr Tk] if (!Tcl_PkgPresent(interp, "Itk", NULL, 0)) { status = Itk_Init(interp); if (status != TCL_OK) { if (err) { *err << "Itk_Init error: " << Tcl_GetStringResult(interp) << endl; } return NULL; } } #endif // Initialize TkTreeCtrl #ifdef KWWidgets_USE_TKTREECTRL vtkKWTkTreeCtrlInit::Initialize(interp); #endif // Initialize tkdnd #ifdef KWWidgets_USE_TKDND vtkKWTkDnDInit::Initialize(interp); #endif // Initialize VTK vtkKWApplication::InitializeVTK(interp, err); // Initialize Widgets Kwwidgets_Init(interp); return interp; } //---------------------------------------------------------------------------- Tcl_Interp *vtkKWApplication::GetMainInterp() { return Et_Interp; } //---------------------------------------------------------------------------- void vtkKWApplication::Start() { int i; // look at Tcl for any args int argc = atoi(this->Script("set argc")) + 1; char **argv = new char *[argc]; argv[0] = NULL; for (i = 1; i < argc; i++) { argv[i] = strdup(this->Script("lindex $argv %d",i-1)); } this->Start(argc,argv); for (i = 0; i < argc; i++) { if (argv[i]) { free(argv[i]); } } delete [] argv; } //---------------------------------------------------------------------------- void vtkKWApplication::ParseCommandLineArguments(int argc, char **argv) { // Command line args: language int index = 0, pos = 0; if (vtkKWApplication::CheckForValuedArgument( argc, argv, "--lang", index, pos) == VTK_OK) { vtkKWLanguage::SetCurrentLanguage( vtkKWLanguage::GetLanguageFromXPG(argv[index] + pos)); } } //---------------------------------------------------------------------------- void vtkKWApplication::Start(int argc, char **argv) { #ifdef _WIN32 #if (defined(_MSC_VER) && _MSC_VER < 1300) #else // I hate to do that, but the way Tcl/Tk handles icons in menus is just // plain broken, even after reporting a bug back in 2, this was // half fixed, but icons are still corrupted in cascade menus. // The only way to fix this is to temporarily disable menu animations // https://sourceforge.net/tracker/?func=detail&aid=1329198&group_id=12997&atid=112997 OSVERSIONINFO ovi; ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); BOOL bRet = GetVersionEx(&ovi); BOOL bMenuFading = FALSE; BOOL bMenuAnim = FALSE; if (ovi.dwMajorVersion >= 5) { SystemParametersInfo(SPI_GETMENUFADE, 0, &bMenuFading, 0); SystemParametersInfo(SPI_SETMENUFADE, 0, (LPVOID) FALSE, SPIF_SENDWININICHANGE); SystemParametersInfo(SPI_GETMENUANIMATION, 0, &bMenuAnim, 0); SystemParametersInfo(SPI_SETMENUANIMATION, 0, (LPVOID) FALSE, SPIF_SENDWININICHANGE); } #endif #endif // Command line args this->ParseCommandLineArguments(argc, argv); // As a convenience, hide any splash screen if (this->SupportSplashScreen && this->SplashScreen) { this->GetSplashScreen()->Withdraw(); } InstallTclBgErrorCallback(); // If no windows has been mapped so far, then as a convenience, // map the first one int i, nb_windows = this->GetNumberOfWindows(); for (i = 0; i < nb_windows && !this->GetNthWindow(i)->IsMapped(); i++) { } if (i >= nb_windows && nb_windows) { this->GetNthWindow(0)->Display(); vtkKWTkUtilities::WithdrawTopLevel(this->GetMainInterp(), "."); } // Set the KWWidgets icon by default // For this to work, the executable should be linked against the // KWWidgets resource file KWWidgets.rc: // INCLUDE("${KWWidgets_CMAKE_DIR}/KWWidgetsResourceMacros.cmake") // KWWidgets_CREATE_RC_FILE("foo.rc") // ADD_EXECUTABLE(... foo.rc) #ifdef _WIN32 if (this->GetNumberOfWindows()) { this->ProcessPendingEvents(); vtkKWSetApplicationIcon( this->GetMainInterp(), NULL, IDI_KWWidgetsICO); vtkKWSetApplicationSmallIcon( this->GetMainInterp(), NULL, IDI_KWWidgetsICOSMALL); } #endif // Start the event loop while (this->GetNumberOfWindows()) { this->DoOneTclEvent(); } #ifdef _WIN32 #if (defined(_MSC_VER) && _MSC_VER < 1300) #else // Restore menu animation if (ovi.dwMajorVersion >= 5) { SystemParametersInfo(SPI_SETMENUFADE, 0, (LPVOID) bMenuFading, SPIF_SENDWININICHANGE); SystemParametersInfo(SPI_SETMENUANIMATION, 0, (LPVOID) bMenuAnim, SPIF_SENDWININICHANGE); } #endif #endif // In case we never went through Exit() this->PrepareForDelete(); } //---------------------------------------------------------------------------- void vtkKWApplication::RestoreApplicationSettingsFromRegistry() { // Show balloon help ? vtkKWBalloonHelpManager *mgr = this->GetBalloonHelpManager(); if (mgr && this->HasRegistryValue( 2, "RunTime", vtkKWApplication::BalloonHelpVisibilityRegKey)) { mgr->SetVisibility( this->GetIntRegistryValue( 2, "RunTime", vtkKWApplication::BalloonHelpVisibilityRegKey)); } // Save user interface geometry ? if (this->HasRegistryValue( 2, "Geometry", vtkKWApplication::SaveUserInterfaceGeometryRegKey)) { this->SaveUserInterfaceGeometry = this->GetIntRegistryValue( 2, "Geometry", vtkKWApplication::SaveUserInterfaceGeometryRegKey); } // Show splash screen ? if (this->HasRegistryValue( 2, "RunTime", vtkKWApplication::SplashScreenVisibilityRegKey)) { this->SplashScreenVisibility = this->GetIntRegistryValue( 2, "RunTime", vtkKWApplication::SplashScreenVisibilityRegKey); } if (this->RegistryLevel <= 0) { this->SplashScreenVisibility = 0; this->SaveUserInterfaceGeometry = 0; } // Printer settings if (this->HasRegistryValue( 2, "RunTime", vtkKWApplication::PrintTargetDPIRegKey)) { this->SetPrintTargetDPI( this->GetFloatRegistryValue( 2, "RunTime", vtkKWApplication::PrintTargetDPIRegKey)); } // Toolbar settings if (this->HasRegistryValue( 2, "RunTime", vtkKWToolbar::ToolbarAspectRegKey) && vtkKWToolbar::GetGlobalToolbarAspect() != vtkKWToolbar::ToolbarAspectUnChanged) { vtkKWToolbar::SetGlobalToolbarAspect( this->GetApplication()->GetIntRegistryValue( 2, "RunTime", vtkKWToolbar::ToolbarAspectRegKey)); } if (this->GetApplication()->HasRegistryValue( 2, "RunTime", vtkKWToolbar::WidgetsAspectRegKey) && vtkKWToolbar::GetGlobalWidgetsAspect() != vtkKWToolbar::WidgetsAspectUnChanged) { vtkKWToolbar::SetGlobalWidgetsAspect( this->GetApplication()->GetIntRegistryValue( 2, "RunTime", vtkKWToolbar::WidgetsAspectRegKey)); } } //---------------------------------------------------------------------------- void vtkKWApplication::SaveApplicationSettingsToRegistry() { // Show balloon help ? vtkKWBalloonHelpManager *mgr = this->GetBalloonHelpManager(); if (mgr) { this->SetRegistryValue( 2, "RunTime", vtkKWApplication::BalloonHelpVisibilityRegKey, "%d", mgr->GetVisibility()); } // Save user interface geometry ? this->SetRegistryValue( 2, "Geometry", vtkKWApplication::SaveUserInterfaceGeometryRegKey, "%d", this->GetSaveUserInterfaceGeometry()); // Show splash screen ? this->SetRegistryValue( 2, "RunTime", vtkKWApplication::SplashScreenVisibilityRegKey, "%d", this->GetSplashScreenVisibility()); // Printer settings this->SetRegistryValue( 2, "RunTime", vtkKWApplication::PrintTargetDPIRegKey, "%lf", this->PrintTargetDPI); // Toolbar settings if (vtkKWToolbar::GetGlobalToolbarAspect() != vtkKWToolbar::ToolbarAspectUnChanged) { this->SetRegistryValue( 2, "RunTime", vtkKWToolbar::ToolbarAspectRegKey, "%d", vtkKWToolbar::GetGlobalToolbarAspect()); } if (vtkKWToolbar::GetGlobalWidgetsAspect() != vtkKWToolbar::WidgetsAspectUnChanged) { this->SetRegistryValue( 2, "RunTime", vtkKWToolbar::WidgetsAspectRegKey, "%d", vtkKWToolbar::GetGlobalWidgetsAspect()); } // Most recent version int recent_major = 0, recent_minor = 0; if (!this->GetMostRecentVersionLaunched(&recent_major, &recent_minor) || this->MajorVersion > recent_major || (this->MajorVersion == recent_major && this->MinorVersion > recent_minor)) { this->SetRegistryValue( 2, "RunTime", vtkKWApplication::MostRecentVersionLaunchedRegKey, "%d.%d", this->MajorVersion, this->MinorVersion); } } //---------------------------------------------------------------------------- void vtkKWApplication::DoOneTclEvent() { Tcl_DoOneEvent(0); } //---------------------------------------------------------------------------- void vtkKWApplication::InstallTclBgErrorCallback() { this->Script( "proc bgerror { m } " "{ global Application errorInfo; " "%s TclBgErrorCallback \"$m\n$errorInfo\"}", this->GetTclName()); } //---------------------------------------------------------------------------- void vtkKWApplication::TclBgErrorCallback(const char* message) { vtkErrorMacro("TclTk error: "<< message); } //---------------------------------------------------------------------------- int vtkKWApplication::OpenLink(const char *link) { #ifdef _WIN32 HINSTANCE result = ShellExecute( NULL, "open", link, NULL, NULL, SW_SHOWNORMAL); if ((int)result > 32) { return 1; } #endif #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 /* Refs: http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/Reference/reference.html http://developer.apple.com/qa/qa2001/qa1028.html http://www.omnigroup.com/mailman/archive/macosx-dev/2001-May/026547.html http://anonsvn.wireshark.org/wireshark/trunk/gtk/webbrowser.c */ CFStringRef link_CFString = CFStringCreateWithCString(NULL, link, kCFStringEncodingASCII); if (link_CFString) { // Get URL from string and open it CFURLRef link_CFURL = CFURLCreateWithString(NULL, link_CFString, NULL); CFRelease(link_CFString); if (link_CFURL) { OSStatus status = LSOpenCFURLRef(link_CFURL, NULL); CFRelease(link_CFURL); if (!status) { return 1; } } } // Failed? Tried to interpret it as a filesystem path vtksys_stl::string path = vtksys::SystemTools::CollapseFullPath(link); CFStringRef path_CFString = CFStringCreateWithCString(NULL, link, kCFStringEncodingASCII); if (path_CFString) { Boolean is_dir = vtksys::SystemTools::FileIsDirectory(path.c_str()); CFURLRef path_CFURL = CFURLCreateWithFileSystemPath( NULL, path_CFString, kCFURLPOSIXPathStyle, is_dir); CFRelease(path_CFString); if (path_CFURL) { OSStatus status = LSOpenCFURLRef(path_CFURL, NULL); CFRelease(path_CFURL); if (!status) { return 1; } } } #endif vtksys_stl::string msg(k_("Please open:\n")); if (link) { msg += link; } vtkKWMessageDialog::PopupMessage( this, this->GetNthWindow(0), ks_("Display Help Dialog|Title|Open Link"), msg.c_str(), vtkKWMessageDialog::WarningIcon); return 1; } //---------------------------------------------------------------------------- int vtkKWApplication::ExploreLink(const char *link) { vtksys_stl::string path = vtksys::SystemTools::CollapseFullPath(link); #ifdef _WIN32 vtksys::SystemTools::ReplaceString(path, "/", "\\"); vtksys_stl::string command("explorer.exe /n,/e,"); if (!vtksys::SystemTools::FileIsDirectory(path.c_str())) { command += "/select,"; } command += path; if (WinExec(command.c_str(), SW_SHOWNORMAL) > 32) { return 1; } #endif #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 /* Refs: AppleEvents http://developer.apple.com/documentation/AppleScript/Conceptual/AppleEvents/create_send_aepg/chapter_7_section_4.html */ AppleEvent reveal_Event; CFStringRef path_CFString = CFStringCreateWithCString(NULL, path.c_str(), kCFStringEncodingUTF8); if (path_CFString) { Boolean is_dir = vtksys::SystemTools::FileIsDirectory(path.c_str()); CFURLRef path_CFURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, path_CFString, kCFURLPOSIXPathStyle, is_dir); if (path_CFURL) { FSRef path_FSRef; if (CFURLGetFSRef(path_CFURL, &path_FSRef)) { AliasHandle path_Alias; if (FSNewAlias(NULL, &path_FSRef, &path_Alias) == noErr) { const OSType finderSignature = 'MACS'; if (AEBuildAppleEvent( kAEMiscStandards, kAEMakeObjectsVisible, typeApplSignature, &finderSignature, sizeof(finderSignature), kAutoGenerateReturnID, kAnyTransactionID, &reveal_Event, NULL, "'----':[alis(@@)]", path_Alias) == noErr) { OSErr err = AESendMessage( &reveal_Event, NULL, kAENoReply | kAEAlwaysInteract | kAECanSwitchLayer, kAEDefaultTimeout ); AEDisposeDesc(&reveal_Event); if (err == noErr) { return 1; } } } } } } /* Refs (Navigation Services) http://developer.apple.com/documentation/Carbon/Conceptual/NavServicesIntro/ns_intro_carb/chapter_1_section_1.html http://developer.apple.com/documentation/Carbon/Conceptual/ProvidingNavigationDialogs/nsx_intro/chapter_1_section_1.html http://developer.apple.com/documentation/Carbon/Reference/Navigation_Services_Ref/Reference/reference.html http://developer.apple.com/documentation/Carbon/Conceptual/ProvidingNavigationDialogs/nsx_tasks/chapter_3_section_3.html http://developer.apple.com/qa/qa2001/qa1151.html http://developer.apple.com/documentation/Carbon/Reference/File_Manager/Reference/reference.html#//apple_ref/c/func/FSPathMakeRef */ #endif vtkKWLoadSaveDialog *dlg = vtkKWLoadSaveDialog::New(); dlg->SetApplication(this); dlg->SetInitialFileName(path.c_str()); dlg->SaveDialogOff(); if (vtksys::SystemTools::FileIsDirectory(path.c_str())) { dlg->ChooseDirectoryOn(); } else { vtksys_stl::string ext = vtksys::SystemTools::GetFilenameExtension(path); dlg->SetDefaultExtension(ext.c_str()); vtksys_stl::string file_types("{{"); file_types += ext; file_types += " files} {"; file_types += ext; file_types += "}}"; dlg->SetFileTypes(file_types.c_str()); } dlg->MultipleSelectionOff(); dlg->GenerateLastPath(path.c_str()); dlg->Create(); dlg->Invoke(); dlg->Delete(); return 1; } //---------------------------------------------------------------------------- void vtkKWApplication::ProcessPendingEvents() { vtkKWTkUtilities::ProcessPendingEvents(this); } //---------------------------------------------------------------------------- void vtkKWApplication::ProcessIdleTasks() { vtkKWTkUtilities::ProcessIdleTasks(this); } //---------------------------------------------------------------------------- int vtkKWApplication::DisplayExitDialog(vtkKWTopLevel *master) { vtkKWMessageDialog *dialog = vtkKWMessageDialog::New(); dialog->SetApplication(this); dialog->SetStyleToYesNo(); dialog->SetMasterWindow(master); dialog->SetOptions( vtkKWMessageDialog::QuestionIcon | vtkKWMessageDialog::RememberYes | vtkKWMessageDialog::Beep | vtkKWMessageDialog::YesDefault); dialog->SetDialogName(vtkKWApplication::ExitDialogName); char buffer[500]; sprintf(buffer, k_("Are you sure you want to exit %s?"), this->GetPrettyName()); dialog->SetText(buffer); sprintf(buffer, ks_("Exit Dialog|Title|Exit %s"), this->GetPrettyName()); dialog->SetTitle(buffer); int ret = dialog->Invoke(); dialog->Delete(); // This UI interface usually displays a checkbox offering the choice // to prompt for exit or not. Update that UI. for (int i = 0; i < this->GetNumberOfWindows(); i++) { this->GetNthWindow(i)->Update(); } return ret; } //---------------------------------------------------------------------------- void vtkKWApplication::DisplayHelpPage(const char *page, vtkKWTopLevel* master) { if (!page || !*page) { return; } vtksys_stl::string helplink; // If it's not a remote link (crude test) and we can't find it yet, try in // the install/bin directory int is_local = strstr(page, "://") ? 0 : 1; if (is_local && !vtksys::SystemTools::FileExists(page)) { if (this->GetInstallationDirectory()) { vtksys_stl::string try_file; helplink = this->GetInstallationDirectory(); helplink += "/"; try_file = helplink + page; if (!vtksys::SystemTools::FileExists(try_file.c_str())) { helplink += "../"; try_file = helplink + page; if (!vtksys::SystemTools::FileExists(try_file.c_str())) { helplink += "doc/"; try_file = helplink + page; if (!vtksys::SystemTools::FileExists(try_file.c_str())) { helplink += "../Documentation/"; } } } } } helplink += page; int status = 1; char buffer[500]; const char *res = vtksys::SystemTools::FileExists(helplink.c_str()) ? helplink.c_str() : page; #if defined(_WIN32) && defined(KWWidgets_USE_HTML_HELP) // .chm ? if (strstr(helplink.c_str(), ".chm") || strstr(helplink.c_str(), ".CHM")) { status = HtmlHelp(NULL, helplink.c_str(), HH_DISPLAY_TOPIC, 0) ? 1 : 0; } // otherwise just try to open else #endif { status = this->OpenLink(helplink.c_str()); } if (!status) { sprintf( buffer, k_("The help resource %s cannot be displayed. This can be the result of " "the program being wrongly installed or the help file being " "corrupted."), res); vtkKWMessageDialog::PopupMessage( this, master, ks_("Display Help Dialog|Title|Help Error!"), buffer, vtkKWMessageDialog::ErrorIcon); } } //---------------------------------------------------------------------------- void vtkKWApplication::DisplayHelpDialog(vtkKWTopLevel* master) { this->DisplayHelpPage(this->HelpDialogStartingPage, master); } //---------------------------------------------------------------------------- void vtkKWApplication::DisplayTutorial(vtkKWTopLevel* master) { this->DisplayHelpPage(this->TutorialStartingPage, master); } //---------------------------------------------------------------------------- void vtkKWApplication::DisplayAboutDialog(vtkKWTopLevel* master) { if (this->InExit) { return; } if (!this->AboutDialog) { this->AboutDialog = vtkKWMessageDialog::New(); } if (!this->AboutDialog->IsCreated()) { this->AboutDialog->SetApplication(this); this->AboutDialog->SetMasterWindow(master); this->AboutDialog->ModalOn(); this->AboutDialog->Create(); this->AboutDialog->SetBorderWidth(1); this->AboutDialog->SetReliefToSolid(); } this->ConfigureAboutDialog(); this->AboutDialog->Invoke(); } //---------------------------------------------------------------------------- void vtkKWApplication::ConfigureAboutDialog() { if (this->SupportSplashScreen) { this->CreateSplashScreen(); const char *img_name = this->SplashScreen ? this->SplashScreen->GetImageName() : NULL; if (img_name) { if (!this->AboutDialogImage) { this->AboutDialogImage = vtkKWLabel::New(); } if (!this->AboutDialogImage->IsCreated()) { this->AboutDialogImage->SetParent(this->AboutDialog->GetTopFrame()); this->AboutDialogImage->Create(); } this->AboutDialogImage->SetConfigurationOption("-image", img_name); this->Script("pack %s -side top", this->AboutDialogImage->GetWidgetName()); int w = vtkKWTkUtilities::GetPhotoWidth(this->GetMainInterp(), img_name); int h = vtkKWTkUtilities::GetPhotoHeight(this->GetMainInterp(), img_name); this->AboutDialog->GetTopFrame()->SetWidth(w); this->AboutDialog->GetTopFrame()->SetHeight(h); if (w > this->AboutDialog->GetTextWidth()) { this->AboutDialog->SetTextWidth(w); } this->Script( "pack %s -side bottom", // -expand 1 -fill both this->AboutDialog->GetMessageDialogFrame()->GetWidgetName()); } } if (!this->AboutRuntimeInfo) { this->AboutRuntimeInfo = vtkKWTextWithScrollbars::New(); } if (!this->AboutRuntimeInfo->IsCreated()) { this->AboutRuntimeInfo->SetParent(this->AboutDialog->GetBottomFrame()); this->AboutRuntimeInfo->Create(); this->AboutRuntimeInfo->VerticalScrollbarVisibilityOn(); this->AboutRuntimeInfo->HorizontalScrollbarVisibilityOff(); vtkKWText *text = this->AboutRuntimeInfo->GetWidget(); text->SetWidth(60); text->SetHeight(8); text->SetWrapToWord(); text->ReadOnlyOn(); double r, g, b; vtkKWFrame *parent = vtkKWFrame::SafeDownCast(text->GetParent()); parent->GetBackgroundColor(&r, &g, &b); text->SetBackgroundColor(r, g, b); this->Script("pack %s -side top -padx 2 -expand 1 -fill both", this->AboutRuntimeInfo->GetWidgetName()); } char buffer[500]; sprintf(buffer, ks_("About Dialog|Title|About %s"), this->GetPrettyName()); this->AboutDialog->SetTitle(buffer); vtksys_ios::ostringstream str; this->AddAboutText(str); str << endl; this->AddSystemInformation(str); str << endl; this->AddAboutCopyrights(str); this->AboutRuntimeInfo->GetWidget()->SetText( str.str().c_str() ); } //---------------------------------------------------------------------------- void vtkKWApplication::AddSystemInformation(ostream &os) { } //---------------------------------------------------------------------------- void vtkKWApplication::AddAboutText(ostream &os) { os << this->GetPrettyName(); const char *app_ver_name = this->GetVersionName(); const char *app_rel_name = this->GetReleaseName(); if ((app_ver_name && *app_ver_name) || (app_rel_name && *app_rel_name)) { os << " ("; if (app_ver_name && *app_ver_name) { os << app_ver_name; if (app_rel_name && *app_rel_name) { os << " "; } } if (app_rel_name && *app_rel_name) { os << app_rel_name; } os << ")"; } os << endl; if (this->GetInstallationDirectory()) { os << "Installation directory: " << this->GetInstallationDirectory() << endl; } os << "User data directory: " << this->GetUserDataDirectory() << endl; #ifdef KWWidgets_USE_INTERNATIONALIZATION int lang = vtkKWLanguage::GetCurrentLanguage(); const char *lang_name = vtkKWLanguage::GetLanguageName(lang); const char *lang_xpg = vtkKWLanguage::GetXPGFromLanguage(lang); if (lang_name) { os << lang_name; } if (lang_xpg) { if (lang_name) { os << " ("; } os << lang_xpg; if (lang_name) { os << ")"; } } if (lang_name || lang_xpg) { os << endl; } #endif } //---------------------------------------------------------------------------- void vtkKWApplication::AddAboutCopyrights(ostream &os) { int tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); os << "Tcl/Tk " << tcl_major << "." << tcl_minor << "." << tcl_patch_level << endl << " - Copyright (c) 1989-1994 The Regents of the University of " << "California." << endl << " - Copyright (c) 1994 The Australian National University." << endl << " - Copyright (c) 1994-1998 Sun Microsystems, Inc." << endl << " - Copyright (c) 1998-2000 Ajuba Solutions." << endl; #ifdef KWWidgets_USE_INTERNATIONALIZATION os << "GNU gettext runtime library (LGPL)" << endl; #endif os << "Nuvola Icon Theme - Copyright (c) 2003-2004 David Vignoni." << endl; os << "Crystal Project Icons - Copyright (c) 2006-2007 Everaldo Coelho." << endl; os << "Silk Icons - http://www.famfamfam.com/lab/icons/silk/" << endl; } //---------------------------------------------------------------------------- int vtkKWApplication::SendErrorLog() { int prompt = (vtkKWMessageDialog::RestoreMessageDialogResponseFromRegistry( this, vtkKWApplication::SendErrorLogDialogName) == 0); if (!prompt || !this->CanEmailFeedback() || !this->LogDialog || !this->LogDialog->GetLogWidget()->GetNumberOfRecords()) { return 0; } this->DisplayLogDialog(NULL); vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImage(image_ErrorLogMenuEntry, image_ErrorLogMenuEntry_width, image_ErrorLogMenuEntry_height, image_ErrorLogMenuEntry_pixel_size, image_ErrorLogMenuEntry_length, image_ErrorLogMenuEntry_decoded_length); vtkKWMessageDialog *dialog = vtkKWMessageDialog::New(); dialog->SetApplication(this); dialog->SetStyleToOkCancel(); dialog->SetMasterWindow(this->GetNthWindow(0)); dialog->SetOptions( vtkKWMessageDialog::RememberNo | vtkKWMessageDialog::Beep | vtkKWMessageDialog::CustomIcon | vtkKWMessageDialog::NoDefault); dialog->SetDialogName(vtkKWApplication::SendErrorLogDialogName); dialog->SetTitle(k_("Send Error Log?")); dialog->SetText(k_("Some errors were raised during your session. These errors did not cause any data loss, but by keeping us informed you can help us to improve our product.\n\nYou can send us this error log now. You can also review and send the error log in the future by accessing the \"Window\" menu or by clicking on the error icon located at the bottom right corner of the window.")); dialog->SetOKButtonText(k_("Send Log")); dialog->SetCancelButtonText(k_("Do Not Send Log")); dialog->GetIcon()->SetImageToIcon(icon); int ret = dialog->Invoke(); dialog->Delete(); icon->Delete(); this->GetLogDialog()->Withdraw(); if (ret) { this->GetLogDialog()->GetLogWidget()->EmailRecords( this->EmailFeedbackAddress); } return ret; } //---------------------------------------------------------------------------- vtkKWSplashScreen *vtkKWApplication::GetSplashScreen() { if (!this->SplashScreen) { this->SplashScreen = vtkKWSplashScreen::New(); this->SplashScreen->SetApplication(this); this->SplashScreen->Create(); } return this->SplashScreen; } //---------------------------------------------------------------------------- vtkKWOptionDataBase *vtkKWApplication::GetOptionDataBase() { if (!this->OptionDataBase) { this->OptionDataBase = vtkKWOptionDataBase::New(); } return this->OptionDataBase; } //---------------------------------------------------------------------------- vtkKWBalloonHelpManager *vtkKWApplication::GetBalloonHelpManager() { if (!this->BalloonHelpManager && !this->InExit) { this->BalloonHelpManager = vtkKWBalloonHelpManager::New(); this->BalloonHelpManager->SetApplication(this); } return this->BalloonHelpManager; } //---------------------------------------------------------------------------- vtkKWRegistryHelper *vtkKWApplication::GetRegistryHelper() { if (!this->RegistryHelper) { this->RegistryHelper = vtkKWRegistryHelper::New(); } return this->RegistryHelper; } //---------------------------------------------------------------------------- const char* vtkKWApplication::GetRegistryVersionName() { if (this->RegistryVersionName) { return this->RegistryVersionName; } if (this->Name) { char versionname_buffer[1024]; sprintf(versionname_buffer, "%s%d", this->Name, this->MajorVersion); this->Internals->RegistryVersionNameTemp = versionname_buffer; return this->Internals->RegistryVersionNameTemp.c_str(); } return NULL; } //---------------------------------------------------------------------------- int vtkKWApplication::SetRegistryValue(int level, const char* subkey, const char* key, const char* format, ...) { if (this->GetRegistryLevel() < 0 || this->GetRegistryLevel() < level) { return 0; } int res = 0; char buffer[vtkKWRegistryHelper::RegistryKeyNameSizeMax]; char value[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; sprintf(buffer, "%s\\%s", this->GetRegistryVersionName(), subkey); va_list var_args; va_start(var_args, format); vsprintf(value, format, var_args); va_end(var_args); vtkKWRegistryHelper *reg = this->GetRegistryHelper(); reg->SetTopLevel(this->GetName()); res = reg->SetValue(buffer, key, value); return res; } //---------------------------------------------------------------------------- int vtkKWApplication::GetRegistryValue(int level, const char* subkey, const char* key, char* value) { if (this->GetRegistryLevel() < 0 || this->GetRegistryLevel() < level || !value) { return 0; } int res = 0; char buff[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; char buffer[vtkKWRegistryHelper::RegistryKeyNameSizeMax]; sprintf(buffer, "%s\\%s", this->GetRegistryVersionName(), subkey); vtkKWRegistryHelper *reg = this->GetRegistryHelper(); reg->SetTopLevel(this->GetName()); buff[0] = 0; res = reg->ReadValue(buffer, key, buff); if (res) { *value = 0; strcpy(value, buff); } return res; } //---------------------------------------------------------------------------- int vtkKWApplication::DeleteRegistryValue(int level, const char* subkey, const char* key) { if (this->GetRegistryLevel() < 0 || this->GetRegistryLevel() < level) { return 0; } int res = 0; char buffer[vtkKWRegistryHelper::RegistryKeyNameSizeMax]; sprintf(buffer, "%s\\%s", this->GetRegistryVersionName(), subkey); vtkKWRegistryHelper *reg = this->GetRegistryHelper(); reg->SetTopLevel(this->GetName()); res = reg->DeleteValue(buffer, key); return res; } //---------------------------------------------------------------------------- int vtkKWApplication::HasRegistryValue(int level, const char* subkey, const char* key) { char buffer[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; return this->GetRegistryValue(level, subkey, key, buffer); } //---------------------------------------------------------------------------- float vtkKWApplication::GetFloatRegistryValue(int level, const char* subkey, const char* key) { if (this->GetRegistryLevel() < 0 || this->GetRegistryLevel() < level) { return 0; } float res = 0; char buffer[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; if (this->GetRegistryValue(level, subkey, key, buffer)) { res = atof(buffer); } return res; } //---------------------------------------------------------------------------- int vtkKWApplication::GetIntRegistryValue(int level, const char* subkey, const char* key) { if (this->GetRegistryLevel() < 0 || this->GetRegistryLevel() < level) { return 0; } int res = 0; char buffer[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; if (this->GetRegistryValue(level, subkey, key, buffer)) { res = atoi(buffer); } return res; } //---------------------------------------------------------------------------- int vtkKWApplication::GetBooleanRegistryValue(int level, const char* subkey, const char* key, const char* trueval) { if (this->GetRegistryLevel() < 0 || this->GetRegistryLevel() < level) { return 0; } char buffer[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; int allset = 0; if (this->GetRegistryValue(level, subkey, key, buffer)) { if (trueval && !strncmp(buffer+1, trueval+1, strlen(trueval)-1)) { allset = 1; } } return allset; } //---------------------------------------------------------------------------- void vtkKWApplication::SaveColorRegistryValue(int level, const char* key, double rgb[3]) { this->SetRegistryValue( level, "Colors", key, "Color: %lf %lf %lf", rgb[0], rgb[1], rgb[2]); } //---------------------------------------------------------------------------- int vtkKWApplication::RetrieveColorRegistryValue(int level, const char* key, double rgb[3]) { char buffer[1024]; rgb[0] = -1; rgb[1] = -1; rgb[2] = -1; int ok = 0; if (this->GetRegistryValue( level, "Colors", key, buffer) ) { if (*buffer) { sscanf(buffer, "Color: %lf %lf %lf", rgb, rgb+1, rgb+2); ok = 1; } } return ok; } //---------------------------------------------------------------------------- int vtkKWApplication::LoadScript(const char* filename) { int res = 1; vtksys_stl::string filename_copy(filename); if (Tcl_EvalFile(this->GetMainInterp(), filename_copy.c_str()) != TCL_OK) { vtkErrorMacro("\n Script: \n" << filename_copy.c_str() << "\n Returned Error on line " << this->GetMainInterp()->errorLine << ": \n " << Tcl_GetStringResult(this->GetMainInterp()) << endl); res = 0; if (this->ExitAfterLoadScript) { this->SetExitStatus(1); } } if (this->ExitAfterLoadScript) { this->SetPromptBeforeExit(0); this->Exit(); } return res; } //---------------------------------------------------------------------------- void vtkKWApplication::SetLimitedEditionMode(int v) { if (this->LimitedEditionMode == v) { return; } this->LimitedEditionMode = v; for (int i = 0; i < this->GetNumberOfWindows(); i++) { this->GetNthWindow(i)->Update(); } this->Modified(); } //---------------------------------------------------------------------------- int vtkKWApplication::GetLimitedEditionModeAndWarn(const char *feature) { if (this->LimitedEditionMode) { const char *lem_name = this->GetLimitedEditionModeName() ? this->GetLimitedEditionModeName() : "Limited Edition"; char buffer[500]; if (feature) { sprintf( buffer, k_("You are running in \'%s' mode. The feature you are trying to use " "(%s) is not available in this mode."), lem_name, feature); } else { sprintf( buffer, k_("You are running in \'%s' mode. The feature you are trying to use " "is not available in this mode."), lem_name); } vtkKWMessageDialog::PopupMessage( this, 0, this->GetPrettyName(), buffer, vtkKWMessageDialog::WarningIcon); } return this->LimitedEditionMode; } //---------------------------------------------------------------------------- void vtkKWApplication::SetReleaseMode(int arg) { if (this->ReleaseMode == arg) { return; } this->ReleaseMode = arg; this->Modified(); vtkObject::SetGlobalWarningDisplay(this->ReleaseMode ? 0 : 1); } //---------------------------------------------------------------------------- const char* vtkKWApplication::GetVersionName() { if (this->VersionName) { return this->VersionName; } if (this->Name) { char versionname_buffer[1024]; sprintf(versionname_buffer, "%s%d.%d", this->Name, this->MajorVersion, this->MinorVersion); this->Internals->VersionNameTemp = versionname_buffer; return this->Internals->VersionNameTemp.c_str(); } return NULL; } //---------------------------------------------------------------------------- int vtkKWApplication::GetMostRecentVersionLaunched(int *major, int *minor) { if (!this->HasRegistryValue( 2, "RunTime", vtkKWApplication::MostRecentVersionLaunchedRegKey)) { return 0; } char buffer[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; this->GetRegistryValue( 2, "RunTime", vtkKWApplication::MostRecentVersionLaunchedRegKey, buffer); if (sscanf(buffer, "%d.%d", major, minor) != 2) { return 0; } return 1; } //---------------------------------------------------------------------------- const char* vtkKWApplication::GetLimitedEditionModeName() { if (this->LimitedEditionModeName) { return this->LimitedEditionModeName; } if (this->Name) { char lemname_buffer[1024]; sprintf(lemname_buffer, "%s Limited Edition", this->Name); this->Internals->LimitedEditionModeNameTemp = lemname_buffer; return this->Internals->LimitedEditionModeNameTemp.c_str(); } return NULL; } //---------------------------------------------------------------------------- const char* vtkKWApplication::GetPrettyName() { vtksys_ios::ostringstream pretty_str; if (this->LimitedEditionMode) { const char *lem_name = this->GetLimitedEditionModeName(); if (lem_name) { pretty_str << lem_name << " "; } else { if (this->Name) { pretty_str << this->Name << " "; } pretty_str << "Limited Edition "; } } else if (this->Name) { pretty_str << this->Name << " "; } pretty_str << this->MajorVersion << "." << this->MinorVersion; if (this->ReleaseName) { pretty_str << " " << this->ReleaseName; } this->SetPrettyName(pretty_str.str().c_str()); return this->PrettyName; } //---------------------------------------------------------------------------- void vtkKWApplication::SetCharacterEncoding(int val) { if (val == this->CharacterEncoding) { return; } if (val < VTK_ENCODING_NONE) { val = VTK_ENCODING_NONE; } else if (val > VTK_ENCODING_UNKNOWN) { val = VTK_ENCODING_UNKNOWN; } this->CharacterEncoding = val; this->Modified(); } //---------------------------------------------------------------------------- void vtkKWApplication::SetTheme(vtkKWTheme *val) { if (val == this->Theme) { return; } if (this->Theme) { this->Theme->Uninstall(); } this->Theme = val; if (this->Theme) { if (!this->Theme->GetApplication()) { this->Theme->SetApplication(this); } this->Theme->Install(); } this->Modified(); } //---------------------------------------------------------------------------- int vtkKWApplication::CheckForArgument( int argc, char* argv[], const char *arg, int &index) { if (!argc || !argv || !arg) { return VTK_ERROR; } // Check each arg // Be careful with valued argument (should not be, but who knows) int i; for (i = 0; i < argc; i++) { if (argv[i]) { const char *equal = strchr(argv[i], '='); if (equal) { size_t part = equal - argv[i]; if (strlen(arg) == part && !strncmp(arg, argv[i], part)) { index = i; return VTK_OK; } } else { if (!strcmp(arg, argv[i])) { index = i; return VTK_OK; } } } } return VTK_ERROR; } //---------------------------------------------------------------------------- int vtkKWApplication::CheckForValuedArgument( int argc, char* argv[], const char *arg, int &index, int &value_pos) { int found = vtkKWApplication::CheckForArgument(argc, argv, arg, index); if (found == VTK_OK) { const char *equal = strchr(argv[index], '='); if (equal) { value_pos = (equal - argv[index]) + 1; return VTK_OK; } } return VTK_ERROR; } //---------------------------------------------------------------------------- int vtkKWApplication::GetCheckForUpdatesPath(ostream & #ifdef _WIN32 path #endif ) { #ifdef _WIN32 if (this->GetInstallationDirectory()) { vtksys_ios::ostringstream upd; upd << this->GetInstallationDirectory() << "/WiseUpdt.exe"; int res = vtksys::SystemTools::FileExists(upd.str().c_str()); if (res) { path << upd.str().c_str(); } return res; } #endif return 0; } //---------------------------------------------------------------------------- int vtkKWApplication::HasCheckForUpdates() { #if defined(_WIN32) && !defined(__CYGWIN__) vtksys_ios::ostringstream upd; int res = this->GetCheckForUpdatesPath(upd); return res; #else return 0; #endif } //---------------------------------------------------------------------------- void vtkKWApplication::CheckForUpdates() { if (!this->HasCheckForUpdates()) { return; } #if defined(_WIN32) && !defined(__CYGWIN__) vtksys_ios::ostringstream upd; if (this->GetCheckForUpdatesPath(upd)) { #if defined (__BORLANDC__) spawnl(P_NOWAIT, upd.str().c_str(), upd.str().c_str(), NULL); #else _spawnl(_P_NOWAIT, upd.str().c_str(), upd.str().c_str(), NULL); #endif } #endif } //---------------------------------------------------------------------------- int vtkKWApplication::CanEmailFeedback() { #if defined(_WIN32) && !defined(__CYGWIN__) HMODULE g_hMAPI = ::LoadLibrary("MAPI32.DLL"); int has_mapi = g_hMAPI ? 1 : 0; ::FreeLibrary(g_hMAPI); return (has_mapi && this->EmailFeedbackAddress) ? 1 : 0; #endif #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 return 1; #endif return 0; } //---------------------------------------------------------------------------- void vtkKWApplication::AddEmailFeedbackBody(ostream &os) { os << this->GetPrettyName() << " (" << this->GetVersionName(); if (this->GetReleaseName()) { os << " " << this->GetReleaseName(); } os << ")" << endl; this->AddSystemInformation(os); } //---------------------------------------------------------------------------- void vtkKWApplication::AddEmailFeedbackSubject(ostream &os) { os << this->GetPrettyName() << " " << ks_("Email Feedback|Subject|User Feedback"); } //---------------------------------------------------------------------------- int vtkKWApplication::SendEmail( const char *to, const char *subject, const char *message, const char *attachment_filename, const char *extra_error_msg) { #if defined(_WIN32) && !defined(__CYGWIN__) int retry = 1; ULONG err; while (retry) { // Load MAPI HMODULE g_hMAPI = ::LoadLibrary("MAPI32.DLL"); if (!g_hMAPI) { return 0; } // Recipient To: (no SMTP: for Mozilla) MapiRecipDesc recip_to = { 0L, MAPI_TO, NULL, (LPSTR)to, 0L, NULL }; // Attachement MapiFileDesc attachment = { 0L, 0L, -1L, (LPSTR)attachment_filename, NULL, NULL }; // The email itself MapiMessage email = { 0, (LPSTR)subject, (LPSTR)message, NULL, NULL, NULL, 0, NULL, 1, &recip_to, attachment_filename ? 1 : 0, attachment_filename ? &attachment : NULL }; // Send it err = ((LPMAPISENDMAIL)GetProcAddress(g_hMAPI, "MAPISendMail"))( 0L, 0L, &email, MAPI_DIALOG | MAPI_LOGON_UI, 0L); retry = 0; if (err != SUCCESS_SUCCESS) { vtksys_stl::string msg = k_("Sorry, an error occurred while trying to send an email.\n\n" "Please make sure that your default email client has been " "configured properly. The Microsoft Simple MAPI (Messaging " "Application Program Interface) is used to perform this " "operation and it might not be accessible if your " "default email client is not running."); if (extra_error_msg) { msg += "\n\n"; msg += extra_error_msg; } vtkKWMessageDialog *dlg = vtkKWMessageDialog::New(); this->CreateEmailMessageDialog( dlg, to, subject, message, attachment_filename); dlg->SetText(msg.c_str()); dlg->SetStyleToOkCancel(); dlg->SetOKButtonText(ks_("Email Feedback Dialog|Button|Retry")); dlg->Invoke(); int status = dlg->GetStatus(); if (status == vtkKWMessageDialog::StatusOK) { retry = 1; } dlg->Delete(); } ::FreeLibrary(g_hMAPI); } return (err != SUCCESS_SUCCESS ? 0 : 1); #endif #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 /* Refs http://lists.apple.com/archives/applescript-studio/2006/Nov/msg00012.html http://www.mackb.com/Uwe/Forum.aspx/entourage/21582/Applescript-to-create-new-message http://www.microsoft.com/mac/developers/default.mspx?CTT=PageView&clr=99-21-0&target=9efe4640-7277-4372-a304-4181b2c098f21033&srcid=40d869d3-e1a6-4bce-9e5b-fb5b87bec3f41033&ep=7 http://forums.macosxhints.com/archive/index.php/t-73192.html http://forums.macosxhints.com/archive/index.php/t-31163.html http://groups.google.com/group/EasyTask-Users/browse_thread/thread/fb2632fe253dd8e3 http://fundisom.com/apple/search/applescript-send-mail/ http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg08778.html http://www.aaronsw.com/weblog/001054 http://akosut.com/software/mailscripts.html */ // Sending an email using AppleEvents directly is just plain // hard. Let's write and run an AppleScript instead. vtksys_stl::string script; script = "tell application \"Mail\"\n" " activate\n" " set newMessage to make new outgoing message\n" " tell newMessage\n" " set visible to true\n"; if (to) { script = script + " make new recipient at end of to recipients with properties {address:\"" + to + "\"}\n"; } if (subject) { script = script + " set subject to \"" + vtksys::SystemTools::EscapeChars(subject, "\"") + "\"\n"; } if (message) { script = script + " set content to \"" + vtksys::SystemTools::EscapeChars(message, "\"") + "\n\n\n\"\n"; } if (attachment_filename) { script = script + " set filepath to POSIX path of \"" + attachment_filename + "\"\n" + " make new attachment with properties {file name:filepath}\n"; } script = script + " end tell\n" "end tell\n"; if (vtkKWApplication::RunAppleScript(script.c_str())) { return 1; } #endif vtksys_stl::string msg = k_("Sorry, sending an email from this operating system is not " "supported at the moment.\n\n" "In the meantime, we suggest you open your favorite email client " "and copy/paste the fields below to a new email message."); if (extra_error_msg) { msg += "\n\n"; msg += extra_error_msg; } vtkKWMessageDialog *dlg = vtkKWMessageDialog::New(); this->CreateEmailMessageDialog( dlg, to, subject, message, attachment_filename); dlg->SetText(msg.c_str()); dlg->Invoke(); return 0; } //---------------------------------------------------------------------------- void vtkKWApplication::CreateEmailMessageDialog( vtkKWMessageDialog *dlg, const char *to, const char *subject, const char *message, const char *attachment_filename) { if (!dlg) { return; } if (!dlg->GetApplication()) { dlg->SetApplication(this); } dlg->SetStyleToCancel(); dlg->SetOptions(vtkKWMessageDialog::ErrorIcon); dlg->SetTitle(ks_("Email Feedback Dialog|Title|Send Email Error!")); dlg->Create(); vtkKWSeparator *sep = vtkKWSeparator::New(); sep->SetParent(dlg->GetBottomFrame()); sep->Create(); sep->Delete(); this->Script("pack %s -side top -padx 2 -pady 2 -expand 1 -fill x", sep->GetWidgetName()); int label_width = 14; if (to) { vtkKWEntryWithLabel *to_entry = vtkKWEntryWithLabel::New(); to_entry->SetParent(dlg->GetBottomFrame()); to_entry->Create(); to_entry->SetLabelText(ks_("Email Feedback Dialog|Field|To:")); to_entry->SetLabelWidth(label_width); to_entry->GetWidget()->SetValue(to ? to : ""); to_entry->GetWidget()->ReadOnlyOn(); to_entry->Delete(); this->Script("pack %s -side top -padx 2 -pady 2 -expand 1 -fill x", to_entry->GetWidgetName()); } if (subject) { vtkKWEntryWithLabel *subject_entry = vtkKWEntryWithLabel::New(); subject_entry->SetParent(dlg->GetBottomFrame()); subject_entry->Create(); subject_entry->SetLabelText(ks_("Email Feedback Dialog|Field|Subject:")); subject_entry->SetLabelWidth(label_width); subject_entry->GetWidget()->SetValue(subject ? subject : ""); subject_entry->GetWidget()->ReadOnlyOn(); subject_entry->Delete(); this->Script("pack %s -side top -padx 2 -pady 2 -expand 1 -fill x", subject_entry->GetWidgetName()); } if (attachment_filename) { vtkKWFrame *attachment_frame = vtkKWFrame::New(); attachment_frame->SetParent(dlg->GetBottomFrame()); attachment_frame->Create(); attachment_frame->Delete(); this->Script("pack %s -side top -padx 0 -pady 0 -expand 1 -fill x", attachment_frame->GetWidgetName()); vtkKWEntryWithLabel *attachment_entry = vtkKWEntryWithLabel::New(); attachment_entry->SetParent(attachment_frame); attachment_entry->Create(); attachment_entry->SetLabelText( ks_("Email Feedback Dialog|Field|Attachment:")); attachment_entry->SetLabelWidth(label_width); attachment_entry->GetWidget()->SetValue( attachment_filename ? attachment_filename : ""); attachment_entry->GetWidget()->ReadOnlyOn(); attachment_entry->Delete(); this->Script("pack %s -side left -padx 2 -pady 2 -expand 1 -fill x", attachment_entry->GetWidgetName()); vtkKWPushButton *attachment_locate_button = vtkKWPushButton::New(); attachment_locate_button->SetParent(attachment_frame); attachment_locate_button->Create(); attachment_locate_button->SetImageToPredefinedIcon(vtkKWIcon::IconFolder); attachment_locate_button->SetBalloonHelpString( ks_("Email Feedback Dialog|Field|Attachment|Locate attachment on disk")); vtksys_stl::string command("ExploreLink {"); command += attachment_filename; command += "}"; attachment_locate_button->SetCommand(this, command.c_str()); attachment_locate_button->Delete(); this->Script("pack %s -side left -padx 2 -pady 2 -expand 0 -fill none", attachment_locate_button->GetWidgetName()); } if (message) { vtkKWTextWithScrollbars *message_text = vtkKWTextWithScrollbars::New(); message_text->SetParent(dlg->GetBottomFrame()); message_text->Create(); message_text->VerticalScrollbarVisibilityOn(); message_text->HorizontalScrollbarVisibilityOff(); vtkKWText *text_widget = message_text->GetWidget(); text_widget->SetWidth(60); text_widget->SetHeight(8); text_widget->SetWrapToWord(); text_widget->ReadOnlyOn(); text_widget->SetText(message ? message : ""); message_text->Delete(); this->Script("pack %s -side top -padx 2 -pady 2 -expand 1 -fill both", message_text->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWApplication::EmailFeedback() { if (!this->CanEmailFeedback()) { return; } vtksys_ios::ostringstream email_subject; this->AddEmailFeedbackSubject(email_subject); vtksys_ios::ostringstream message; this->AddEmailFeedbackBody(message); message << endl; char buffer[500]; sprintf( buffer, k_("If you continue to experience problems please use your email " "client to send us feedback at %s."), this->EmailFeedbackAddress); this->SendEmail( this->EmailFeedbackAddress, email_subject.str().c_str(), message.str().c_str(), NULL, buffer); } //---------------------------------------------------------------------------- #ifdef __APPLE__ int vtkKWApplication::RunAppleScript( const char *text) { #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 // Source: http://developer.apple.com/qa/qa2001/qa1026.html // Gotta link against -framework Carbon now :( long textLength = strlen(text); AEDesc scriptTextDesc; AECreateDesc(typeNull, NULL, 0, &scriptTextDesc); AEDesc resultData; OSStatus err; // Open the scripting component ComponentInstance theComponent = OpenDefaultComponent(kOSAComponentType, typeAppleScript); if (theComponent == NULL) { err = paramErr; } else { // Put the script text into an aedesc err = AECreateDesc(typeChar, text, textLength, &scriptTextDesc); if (err == noErr) { // Compile the script OSAID scriptID = kOSANullScript;; err = OSACompile(theComponent, &scriptTextDesc, kOSAModeNull, &scriptID); if (err == noErr) { // Run the script OSAID resultID = kOSANullScript;; err = OSAExecute( theComponent, scriptID, kOSANullScript, kOSAModeNull, &resultID); // Collect the results - if any AECreateDesc(typeNull, NULL, 0, &resultData); if (err == errOSAScriptError) { OSAScriptError(theComponent, kOSAErrorMessage, typeChar, &resultData); } else if (err == noErr && resultID != kOSANullScript) { OSADisplay( theComponent, resultID, typeChar, kOSAModeNull, &resultData); OSADispose(theComponent, resultID); } OSADispose(theComponent, scriptID); } } CloseComponent(theComponent); } AEDisposeDesc(&scriptTextDesc); return err == noErr ? 1 : 0; #endif (void)text; return 0; } #endif //---------------------------------------------------------------------------- void vtkKWApplication::RegisterDialogUp(vtkKWWidget *) { this->DialogUp++; } //---------------------------------------------------------------------------- void vtkKWApplication::UnRegisterDialogUp(vtkKWWidget *) { this->DialogUp--; if (this->DialogUp < 0) { vtkErrorMacro( "It seems that UnRegisterDialogUp() was called without a matching call to RegisterDialogUp(), since the number of dialogs supposed to be up is now negative... This is most likely not good."); } } //---------------------------------------------------------------------------- int vtkKWApplication::IsDialogUp() { return (this->DialogUp > 0 ? 1 : 0); } //---------------------------------------------------------------------------- const char* vtkKWApplication::GetInstallationDirectory() { if (!this->InstallationDirectory) { this->FindInstallationDirectory(); } return this->InstallationDirectory; } //---------------------------------------------------------------------------- void vtkKWApplication::FindInstallationDirectory() { const char *nameofexec = Tcl_GetNameOfExecutable(); if (nameofexec && vtksys::SystemTools::FileExists(nameofexec)) { vtksys_stl::string directory = vtksys::SystemTools::GetFilenamePath(nameofexec); // remove the /bin from the end // directory[strlen(directory) - 4] = '\0'; // => do not *do* that: first it breaks all the apps // relying on this method to find where the binary is installed // (hello plugins ?), second this is a hard-coded assumption, what // about msdev path, bin/release, bin/debug, etc. // If you need to remove whatever dir, just copy the result of this // method and strip it where needed. vtksys::SystemTools::ConvertToUnixSlashes(directory); this->SetInstallationDirectory(directory.c_str()); } else { char setup_key[vtkKWRegistryHelper::RegistryKeyNameSizeMax]; sprintf(setup_key, "%s\\Setup", this->GetRegistryVersionName()); vtkKWRegistryHelper *reg = this->GetRegistryHelper(); reg->SetTopLevel(this->GetName()); char installed_path[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; if (reg && reg->ReadValue(setup_key, "InstalledPath", installed_path)) { vtksys_stl::string directory(installed_path); vtksys::SystemTools::ConvertToUnixSlashes(directory); this->SetInstallationDirectory(directory.c_str()); } else { reg->SetGlobalScope(1); if (reg && reg->ReadValue(setup_key, "InstalledPath", installed_path)) { vtksys_stl::string directory(installed_path); vtksys::SystemTools::ConvertToUnixSlashes(directory); this->SetInstallationDirectory(directory.c_str()); } else { this->SetInstallationDirectory(0); } reg->SetGlobalScope(0); } } } //---------------------------------------------------------------------------- const char* vtkKWApplication::GetUserDataDirectory() { if (!this->UserDataDirectory) { vtksys_stl::string dir; #ifdef _WIN32 vtksys_stl::string personal; if (vtksys::SystemTools::ReadRegistryValue( "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders;Personal", // or ;AppData personal)) { dir = personal; dir += "/"; } #else dir = vtksys::SystemTools::GetEnv("HOME"); dir += "/."; #endif dir += this->GetName(); vtksys::SystemTools::ConvertToUnixSlashes(dir); // We assume that if the user data dir is being requested, we should // create it now in case it does not exist, so that it can be used right // away. if (!vtksys::SystemTools::FileExists(dir.c_str())) { vtksys::SystemTools::MakeDirectory(dir.c_str()); } this->UserDataDirectory = new char [dir.size() + 1]; strcpy(this->UserDataDirectory, dir.c_str()); } return this->UserDataDirectory; } //---------------------------------------------------------------------------- const char* vtkKWApplication::Script(const char* format, ...) { va_list var_args1, var_args2; va_start(var_args1, format); va_start(var_args2, format); const char* result = vtkKWTkUtilities::EvaluateStringFromArgs( this, format, var_args1, var_args2); va_end(var_args1); va_end(var_args2); return result; } //---------------------------------------------------------------------------- int vtkKWApplication::EvaluateBooleanExpression(const char* format, ...) { va_list var_args1, var_args2; va_start(var_args1, format); va_start(var_args2, format); const char* result = vtkKWTkUtilities::EvaluateStringFromArgs( this, format, var_args1, var_args2); va_end(var_args1); va_end(var_args2); return (result && !strcmp(result, "1")) ? 1 : 0; } //---------------------------------------------------------------------------- int vtkKWApplication::PutEnv(const char* value) { static vtkKWApplicationInternals::DeletingCharVector local_environment; char *env_var = new char[strlen(value) + 1]; strcpy(env_var, value); int ret = putenv(env_var); // save the pointer in the static vector so that it can // be deleted on exit // http://groups.google.com/group/comp.unix.wizards/msg/f0915a043bf259fa?dmode=source local_environment.push_back(env_var); return ret == 0; } //---------------------------------------------------------------------------- void vtkKWApplication::WarningMessage(const char* message) { this->InvokeEvent(vtkKWEvent::WarningMessageEvent, (void*)message); if (this->CreateLogDialog()) { this->GetLogDialog()->GetLogWidget()->AddWarningRecord(message); } #ifdef _WIN32 ::OutputDebugString(message); #endif cerr << message << endl; } //---------------------------------------------------------------------------- void vtkKWApplication::ErrorMessage(const char* message) { this->InvokeEvent(vtkKWEvent::ErrorMessageEvent, (void*)message); if (this->CreateLogDialog()) { this->GetLogDialog()->GetLogWidget()->AddErrorRecord(message); } #ifdef _WIN32 ::OutputDebugString(message); #endif cerr << message << endl; } //---------------------------------------------------------------------------- void vtkKWApplication::InformationMessage(const char* message) { this->InvokeEvent(vtkKWEvent::InformationMessageEvent, (void*)message); if (this->CreateLogDialog()) { this->GetLogDialog()->GetLogWidget()->AddInformationRecord(message); } #ifdef _WIN32 ::OutputDebugString(message); #endif cerr << message << endl; } //---------------------------------------------------------------------------- void vtkKWApplication::DebugMessage(const char* message) { this->InvokeEvent(vtkKWEvent::DebugMessageEvent, (void*)message); if (this->CreateLogDialog()) { this->GetLogDialog()->GetLogWidget()->AddDebugRecord(message); } #ifdef _WIN32 ::OutputDebugString(message); #endif cerr << message << endl; } //---------------------------------------------------------------------------- vtkKWLogDialog* vtkKWApplication::GetLogDialog() { if (!this->InExit && !this->LogDialog) { this->LogDialog = vtkKWLogDialog::New(); this->GetLogDialog()->SetApplication(this); } return this->LogDialog; } //---------------------------------------------------------------------------- int vtkKWApplication::CreateLogDialog() { if (this->GetLogDialog()) { if (!this->GetLogDialog()->IsCreated()) { this->GetLogDialog()->Create(); } return this->GetLogDialog()->IsCreated(); } return 0; } //---------------------------------------------------------------------------- void vtkKWApplication::DisplayLogDialog(vtkKWTopLevel* master) { if (this->CreateLogDialog()) { this->GetLogDialog()->SetMasterWindow( master ? master : this->GetNthWindow(0)); this->GetLogDialog()->Display(); } } //---------------------------------------------------------------------------- vtkKWTclInteractor* vtkKWApplication::GetTclInteractor() { if (!this->TclInteractor) { this->TclInteractor = vtkKWTkcon::New(); } if (!this->TclInteractor->IsCreated()) { this->TclInteractor->SetApplication(this); this->TclInteractor->Create(); } return this->TclInteractor; } //---------------------------------------------------------------------------- void vtkKWApplication::DisplayTclInteractor(vtkKWTopLevel *master) { vtkKWTclInteractor *tcl_interactor = this->GetTclInteractor(); if (tcl_interactor) { if (!master) { master = this->GetNthWindow(0); } if (master) { vtksys_stl::string title; if (master->GetTitle()) { title += master->GetTitle(); title += " : "; } title += ks_("Tcl Interactor Dialog|Title|Tcl Interactor"); tcl_interactor->SetTitle(title.c_str()); tcl_interactor->SetMasterWindow(master); } tcl_interactor->Display(); } } //---------------------------------------------------------------------------- vtkKWColorPickerDialog* vtkKWApplication::GetColorPickerDialog() { if (!this->ColorPickerDialog) { this->ColorPickerDialog = vtkKWColorPickerDialog::New(); } if (!this->ColorPickerDialog->IsCreated()) { this->ColorPickerDialog->SetApplication(this); // do not set the master window otherwise TAB doesn't switch focus this->ColorPickerDialog->Create(); this->ColorPickerDialog->SetDisplayPositionToPointer(); } return this->ColorPickerDialog; } //---------------------------------------------------------------------------- void vtkKWApplication::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Name: " << this->GetName() << endl; os << indent << "MajorVersion: " << this->MajorVersion << endl; os << indent << "MinorVersion: " << this->MinorVersion << endl; os << indent << "ReleaseName: " << (this->ReleaseName ? this->ReleaseName : "(None)") << endl; os << indent << "VersionName: " << (this->VersionName ? this->VersionName : "(None)") << endl; os << indent << "RegistryVersionName: " << (this->RegistryVersionName ? this->RegistryVersionName : "(None)") << endl; os << indent << "PrettyName: " << this->GetPrettyName() << endl; os << indent << "EmailFeedbackAddress: " << (this->GetEmailFeedbackAddress() ? this->GetEmailFeedbackAddress() : "(none)") << endl; os << indent << "HelpDialogStartingPage: " << (this->HelpDialogStartingPage ? this->HelpDialogStartingPage : "(none)") << endl; os << indent << "TutorialStartingPage: " << (this->TutorialStartingPage ? this->TutorialStartingPage : "(none)") << endl; os << indent << "ExitStatus: " << this->GetExitStatus() << endl; os << indent << "RegistryLevel: " << this->GetRegistryLevel() << endl; os << indent << "ExitAfterLoadScript: " << (this->ExitAfterLoadScript ? "on":"off") << endl; os << indent << "InExit: " << (this->InExit ? "on":"off") << endl; if (this->SplashScreen) { os << indent << "SplashScreen: " << this->SplashScreen << endl; } else { os << indent << "SplashScreen: (none)" << endl; } if (this->BalloonHelpManager) { os << indent << "BalloonHelpManager: " << this->BalloonHelpManager << endl; } else { os << indent << "BalloonHelpManager: (none)" << endl; } os << indent << "SupportSplashScreen: " << (this->SupportSplashScreen ? "on":"off") << endl; os << indent << "SplashScreenVisibility: " << (this->SplashScreenVisibility ? "on":"off") << endl; os << indent << "PromptBeforeExit: " << (this->GetPromptBeforeExit() ? "on":"off") << endl; os << indent << "SendErrorLogBeforeExit: " << (this->GetSendErrorLogBeforeExit() ? "on":"off") << endl; os << indent << "InstallationDirectory: " << (this->GetInstallationDirectory() ? this->GetInstallationDirectory() : "None") << endl; os << indent << "UserDataDirectory: " << (this->UserDataDirectory ? UserDataDirectory : "None") << endl; os << indent << "SaveUserInterfaceGeometry: " << (this->SaveUserInterfaceGeometry ? "On" : "Off") << endl; os << indent << "LimitedEditionMode: " << (this->LimitedEditionMode ? "On" : "Off") << endl; os << indent << "CharacterEncoding: " << this->CharacterEncoding << "\n"; os << indent << "Theme: "; if (this->Theme) { os << this->Theme << endl; } else { os << "NULL" << endl; } os << indent << "LimitedEditionModeName: " << (this->LimitedEditionModeName ? this->LimitedEditionModeName : "None") << endl; os << indent << "ReleaseMode: " << (this->ReleaseMode ? "On" : "Off") << endl; os << indent << "PrintTargetDPI: " << this->GetPrintTargetDPI() << endl; os << indent << "TclInteractor: " << this->GetTclInteractor() << endl; os << indent << "ColorPickerDialog: " << this->GetColorPickerDialog() << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWRegistryHelper.cxx0000644000175000017500000001537611451150151021552 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWRegistryHelper.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWRegistryHelper.h" #include "vtkDebugLeaks.h" #include "vtkObjectFactory.h" #ifdef _WIN32 # include "vtkKWWin32RegistryHelper.h" #else // _WIN32 # include "vtkKWUNIXRegistryHelper.h" #endif // _WIN32 #include vtkCxxRevisionMacro(vtkKWRegistryHelper, "$Revision: 1.5 $"); //---------------------------------------------------------------------------- vtkKWRegistryHelper *vtkKWRegistryHelper::New() { vtkObject* ret = vtkObjectFactory::CreateInstance("vtkKWRegistryHelper"); if(ret) { return static_cast(ret); } vtkDebugLeaks::DestructClass("vtkKWRegistryHelper"); #ifdef _WIN32 return vtkKWWin32RegistryHelper::New(); #else // _WIN32 return vtkKWUNIXRegistryHelper::New(); #endif // _WIN32 } //---------------------------------------------------------------------------- vtkKWRegistryHelper::vtkKWRegistryHelper() { this->TopLevel = 0; this->Opened = 0; this->Locked = 0; this->Changed = 0; this->Empty = 1; this->GlobalScope = 0; this->ConfigurationDirectory = NULL; } //---------------------------------------------------------------------------- vtkKWRegistryHelper::~vtkKWRegistryHelper() { this->SetTopLevel(0); if ( this->Opened ) { vtkErrorMacro("vtkKWRegistryHelper::Close should be " "called here. The registry is not closed."); } } //---------------------------------------------------------------------------- int vtkKWRegistryHelper::Open(const char *toplevel, const char *subkey, int readonly) { int res = 0; if ( this->GetLocked() ) { return 0; } if ( this->Opened ) { if ( !this->Close() ) { return 0; } } if (!toplevel || !*toplevel) { vtkErrorMacro("vtkKWRegistryHelper::Opened() Toplevel not defined"); return 0; } if ( this->IsSpace(toplevel[0]) || this->IsSpace(toplevel[strlen(toplevel)-1]) ) { vtkErrorMacro("Toplevel has to start with letter or number and end" " with one"); return 0; } if ( readonly == vtkKWRegistryHelper::ReadOnly ) { res = this->OpenInternal(toplevel, subkey, readonly); } else { res = this->OpenInternal(toplevel, subkey, readonly); this->SetLocked(1); } if ( res ) { this->Opened = 1; this->SetTopLevel( toplevel ); } return res; } //---------------------------------------------------------------------------- int vtkKWRegistryHelper::Close() { int res = 0; if ( this->Opened ) { res = this->CloseInternal(); } if ( res ) { this->Opened = 0; this->SetLocked(0); this->Changed = 0; } return res; } //---------------------------------------------------------------------------- int vtkKWRegistryHelper::ReadValue(const char *subkey, const char *key, char *value) { *value = 0; int res = 1; int open = 0; if ( ! value ) { return 0; } if ( !this->Opened ) { if ( !this->Open(this->GetTopLevel(), subkey, vtkKWRegistryHelper::ReadOnly) ) { return 0; } open = 1; } res = this->ReadValueInternal(key, value); if ( open ) { if ( !this->Close() ) { res = 0; } } return res; } //---------------------------------------------------------------------------- int vtkKWRegistryHelper::DeleteKey(const char *subkey, const char *key) { int res = 1; int open = 0; if ( !this->Opened ) { if ( !this->Open(this->GetTopLevel(), subkey, vtkKWRegistryHelper::ReadWrite) ) { return 0; } open = 1; } res = this->DeleteKeyInternal(key); this->Changed = 1; if ( open ) { if ( !this->Close() ) { res = 0; } } return res; } //---------------------------------------------------------------------------- int vtkKWRegistryHelper::DeleteValue(const char *subkey, const char *key) { int res = 1; int open = 0; if ( !this->Opened ) { if ( !this->Open(this->GetTopLevel(), subkey, vtkKWRegistryHelper::ReadWrite) ) { return 0; } open = 1; } res = this->DeleteValueInternal(key); this->Changed = 1; if ( open ) { if ( !this->Close() ) { res = 0; } } return res; } //---------------------------------------------------------------------------- int vtkKWRegistryHelper::SetValue(const char *subkey, const char *key, const char *value) { int res = 1; int open = 0; if ( !this->Opened ) { if ( !this->Open(this->GetTopLevel(), subkey, vtkKWRegistryHelper::ReadWrite) ) { return 0; } open = 1; } res = this->SetValueInternal( key, value ); this->Changed = 1; if ( open ) { if ( !this->Close() ) { res = 0; } } return res; } //---------------------------------------------------------------------------- int vtkKWRegistryHelper::IsSpace(char c) { return isspace(c); } //---------------------------------------------------------------------------- char *vtkKWRegistryHelper::Strip(char *str) { int cc; int len; char *nstr; if ( !str ) { return NULL; } len = (int)strlen(str); nstr = str; for( cc=0; ccIsSpace( *nstr ) ) { break; } nstr ++; } for( cc=((int)strlen(nstr)-1); cc>=0; cc-- ) { if ( !this->IsSpace( nstr[cc] ) ) { nstr[cc+1] = 0; break; } } return nstr; } //---------------------------------------------------------------------------- void vtkKWRegistryHelper::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); if( this->TopLevel ) { os << indent << "TopLevel: " << this->TopLevel << "\n"; } else { os << indent << "TopLevel: (none)\n"; } os << indent << "Locked: " << (this->Locked ? "On" : "Off") << "\n"; os << indent << "Opened: " << (this->Opened ? "On" : "Off") << "\n"; os << indent << "GlobalScope: " << (this->GlobalScope ? "On" : "Off") << "\n"; } kwwidgets-1.0.0~cvs20100930/vtkKWUserInterfacePanel.cxx0000644000175000017500000002405711131233223022312 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWUserInterfacePanel.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWUserInterfacePanel.h" #include "vtkKWUserInterfaceManager.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWUserInterfacePanel); vtkCxxRevisionMacro(vtkKWUserInterfacePanel, "$Revision: 1.20 $"); //---------------------------------------------------------------------------- vtkKWUserInterfacePanel::vtkKWUserInterfacePanel() { this->UserInterfaceManager = NULL; this->Enabled = 1; this->Name = NULL; this->PanelIsCreated = 0; } //---------------------------------------------------------------------------- vtkKWUserInterfacePanel::~vtkKWUserInterfacePanel() { this->SetUserInterfaceManager(NULL); this->SetName(NULL); } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::SetUserInterfaceManager(vtkKWUserInterfaceManager *_arg) { vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting UserInterfaceManager to " << _arg); if (this->UserInterfaceManager == _arg) { return; } #if 0 // Disable this code: we want to be able to add and remove panels by setting // the manager to NULL and back to what it was. if (this->IsCreated() && _arg) { vtkErrorMacro("The interface manager cannot be changed once this panel " "has been created. Use the manager's RemovePanel() method " "to remove the panel."); return; } #endif if (this->UserInterfaceManager != NULL) { this->UserInterfaceManager->RemovePanel(this); } this->UserInterfaceManager = _arg; if (this->UserInterfaceManager != NULL) { // Use the same application (for convenience) if (!this->GetApplication() && this->UserInterfaceManager->GetApplication()) { this->SetApplication(this->UserInterfaceManager->GetApplication()); } this->UserInterfaceManager->AddPanel(this); } this->Modified(); } // --------------------------------------------------------------------------- void vtkKWUserInterfacePanel::Create() { if (this->IsCreated()) { // Comment this one. Some user interface manager creates their panels // early on, or on the fly, so it is not too uncommon that this method // is called twice, without a need to be bothered about it. // vtkErrorMacro("The panel is already created"); return; } this->PanelIsCreated = 1; // As a convenience, if the manager associated to this panel has not been // created yet, it is created now. This might be useful since concrete // implementation of panels are likely to request pages in Create(), // which require the manager to be created. if (this->UserInterfaceManager && !this->UserInterfaceManager->IsCreated()) { this->UserInterfaceManager->Create(); } // Do *not* call Update() here. } // --------------------------------------------------------------------------- int vtkKWUserInterfacePanel::IsCreated() { return (this->GetApplication() != NULL && this->PanelIsCreated); } //---------------------------------------------------------------------------- int vtkKWUserInterfacePanel::AddPage(const char *title, const char *balloon, vtkKWIcon *icon) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before" "a page can be added."); return -1; } return this->UserInterfaceManager->AddPage(this, title, balloon, icon); } //---------------------------------------------------------------------------- int vtkKWUserInterfacePanel::RemovePage(const char *title) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before" "a page can be removed."); return -1; } return this->UserInterfaceManager->RemovePage(this, title); } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::SetPageTitle(int id, const char *title) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before " "a page can be set a new title."); return; } this->UserInterfaceManager->SetPageTitle(id, title); } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::SetPageBalloonHelpString(int id, const char *str) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before " "a page can be set a new balloon help string."); return; } this->UserInterfaceManager->SetPageBalloonHelpString(id, str); } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::SetPageIcon(int id, vtkKWIcon *icon) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before " "a page can be set a new icon."); return; } this->UserInterfaceManager->SetPageIcon(id, icon); } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::SetPageIconToPredefinedIcon( int id, int icon_index) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before " "a page can be set a new icon."); return; } this->UserInterfaceManager->SetPageIconToPredefinedIcon(id, icon_index); } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWUserInterfacePanel::GetPageWidget(int id) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before" "a page can be queried."); return NULL; } return this->UserInterfaceManager->GetPageWidget(id); } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWUserInterfacePanel::GetPageWidget(const char *title) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before " "a page can be queried."); return NULL; } return this->UserInterfaceManager->GetPageWidget(this, title); } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWUserInterfacePanel::GetPagesParentWidget() { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before " "a the pages parent can be queried."); return NULL; } return this->UserInterfaceManager->GetPagesParentWidget(this); } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::RaisePage(int id) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before" "a page can be raised."); return; } this->UserInterfaceManager->RaisePage(id); } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::RaisePage(const char *title) { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before " "a page can be raised."); return; } this->UserInterfaceManager->RaisePage(this, title); } //---------------------------------------------------------------------------- int vtkKWUserInterfacePanel::Show() { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before " "all pages can be shown."); return 0; } return this->UserInterfaceManager->ShowPanel(this); } //---------------------------------------------------------------------------- int vtkKWUserInterfacePanel::IsVisible() { if (this->UserInterfaceManager == NULL) { vtkErrorMacro("The UserInterfaceManager manager needs to be set before " "pages can be checked for visibility."); return 0; } return this->UserInterfaceManager->IsPanelVisible(this); } //---------------------------------------------------------------------------- int vtkKWUserInterfacePanel::Raise() { this->Show(); if (this->UserInterfaceManager) { return this->UserInterfaceManager->RaisePanel(this); } return 0; } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::Update() { // Update the enable state this->UpdateEnableState(); // Update the panel according to the manager (i.e. manager-specific changes) if (this->UserInterfaceManager) { this->UserInterfaceManager->UpdatePanel(this); } } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::SetEnabled(int e) { if ( this->Enabled == e ) { return; } this->Enabled = e; this->UpdateEnableState(); this->Modified(); } //---------------------------------------------------------------------------- void vtkKWUserInterfacePanel::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "UserInterfaceManager: " << this->UserInterfaceManager << endl; os << indent << "Enabled: " << (this->Enabled ? "On" : "Off") << endl; os << indent << "Name: " << (this->Name ? this->Name : "(none)") << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWSimpleEntryDialog.cxx0000644000175000017500000000627711103127470022177 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWSimpleEntryDialog.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWSimpleEntryDialog.h" #include "vtkKWEntry.h" #include "vtkKWFrame.h" #include "vtkKWMessage.h" #include "vtkKWEntryWithLabel.h" #include "vtkKWPushButton.h" #include "vtkKWCheckButton.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWSimpleEntryDialog ); vtkCxxRevisionMacro(vtkKWSimpleEntryDialog, "$Revision: 1.17 $"); //---------------------------------------------------------------------------- vtkKWSimpleEntryDialog::vtkKWSimpleEntryDialog() { this->Entry = vtkKWEntryWithLabel::New(); } //---------------------------------------------------------------------------- vtkKWSimpleEntryDialog::~vtkKWSimpleEntryDialog() { if (this->Entry) { this->Entry->Delete(); this->Entry = NULL; } } //---------------------------------------------------------------------------- void vtkKWSimpleEntryDialog::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro("SimpleEntryDialog already created"); return; } this->Superclass::CreateWidget(); this->Entry->SetParent(this->MessageDialogFrame); this->Entry->Create(); this->Entry->SetBinding("", this, "OK"); this->Entry->GetWidget()->SetBinding("", this, "OK"); this->Entry->SetBinding("", this, "Cancel"); this->Entry->GetWidget()->SetBinding("", this, "Cancel"); this->GetOKButton()->SetBinding("", this, "OK"); this->GetCancelButton()->SetBinding("", this, "Cancel"); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWSimpleEntryDialog::Pack() { this->Superclass::Pack(); if (this->Entry && this->Entry->IsCreated()) { vtkKWWidget *before = NULL; if (this->BottomFrame->IsPacked()) { before = this->BottomFrame; } else if (this->CheckButton->IsPacked()) { before = this->CheckButton; } this->Script("pack %s -side top %s %s -padx 4 -fill x -expand yes", this->Entry->GetWidgetName(), (before ? "-before" : ""), (before ? before->GetWidgetName() : "")); } } //---------------------------------------------------------------------------- int vtkKWSimpleEntryDialog::Invoke() { if (this->IsCreated()) { this->Entry->GetWidget()->Focus(); } return this->Superclass::Invoke(); } //---------------------------------------------------------------------------- void vtkKWSimpleEntryDialog::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Entry: " << this->Entry << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWStateMachineState.h0000644000175000017500000001211410526410341021562 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWStateMachineState.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWStateMachineState - a state machine state. // .SECTION Description // This class is the basis for a state machine state. // A state machine is defined by a set of states, a set of inputs and a // transition matrix that defines for each pair of (state,input) what is // the next state to assume. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWStateMachine vtkKWStateMachineInput vtkKWStateMachineTransition #ifndef __vtkKWStateMachineState_h #define __vtkKWStateMachineState_h #include "vtkKWObject.h" class KWWidgets_EXPORT vtkKWStateMachineState : public vtkKWObject { public: static vtkKWStateMachineState* New(); vtkTypeRevisionMacro(vtkKWStateMachineState, vtkKWObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get id. vtkGetMacro(Id, vtkIdType); // Description: // Set/Get simple name. vtkGetStringMacro(Name); vtkSetStringMacro(Name); // Description: // Set/Get longer description. vtkGetStringMacro(Description); vtkSetStringMacro(Description); // Description: // Enter the state. This method should be invoked by the state machine when // it enters this state. It will take care of calling the corresponding // callbacks (EnterCommand) and events (EnterEvent). Subclasses that // override this method should make sure they call their superclass's // Enter() method. virtual void Enter(); // Description: // Leave the state. This method should be invoked by the state machine when // it leaves this state. It will take care of calling the corresponding // callbacks (LeaveCommand) and events (LeaveEvent). Subclasses that // override this method should make sure they call their superclass's // Leave() method. virtual void Leave(); // Description: // Specifies a command to associate with this state. This command // should be invoked by the state machine when it enters this state. // State machine (sub)classes should call the Enter() method most of the // time, which will take care of triggering this callback and firing // the EnterEvent as well. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetEnterCommand(vtkObject *object, const char *method); virtual void InvokeEnterCommand(); virtual int HasEnterCommand(); // Description: // Specifies a command to associate with this state. This command // should be invoked by the state machine when it leaves this state. // State machine (sub)classes should call the Leave() method most of the // time, which will take care of triggering this callback and firing // the EnterEvent as well. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetLeaveCommand(vtkObject *object, const char *method); virtual void InvokeLeaveCommand(); virtual int HasLeaveCommand(); // Description: // Events. The EnterEvent should be fired when the state machine enters // this state. The LeaveEvent should be fired when the state machine // leaves this state. In both case, state machine (sub)classes should call // the corresponding Enter() end Leave() methods most of the time, which will // take care of triggering both the callbacks and firing the events. //BTX enum { EnterEvent = 10000, LeaveEvent }; //ETX // Description: // Set/Get if the set is an accepting state. This is mainly used for // display or IO purposes (see vtkKWStateMachineDOTWriter). vtkBooleanMacro(Accepting, int); vtkGetMacro(Accepting, int); vtkSetMacro(Accepting, int); protected: vtkKWStateMachineState(); ~vtkKWStateMachineState(); vtkIdType Id; char *Name; char *Description; int Accepting; char *EnterCommand; char *LeaveCommand; private: static vtkIdType IdCounter; vtkKWStateMachineState(const vtkKWStateMachineState&); // Not implemented void operator=(const vtkKWStateMachineState&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWThumbWheel.h0000644000175000017500000003525711012075636020302 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWThumbWheel.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWThumbWheel - a thumbwheel widget // .SECTION Description // A widget that repsentes a thumbwheel widget with options for // a label string and a text entry box. #ifndef __vtkKWThumbWheel_h #define __vtkKWThumbWheel_h #include "vtkKWCompositeWidget.h" class vtkKWLabel; class vtkKWEntry; class vtkKWPushButton; class vtkKWTopLevel; class KWWidgets_EXPORT vtkKWThumbWheel : public vtkKWCompositeWidget { public: static vtkKWThumbWheel* New(); vtkTypeRevisionMacro(vtkKWThumbWheel,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the value of the thumbwheel. virtual void SetValue(double v); vtkGetMacro(Value, double); // Description: // Set/Get the minimum value. The current value will be clamped only if // ClampMinimumValue is true. vtkSetMacro(MinimumValue, double); vtkGetMacro(MinimumValue, double); vtkSetMacro(ClampMinimumValue, int); vtkGetMacro(ClampMinimumValue, int); vtkBooleanMacro(ClampMinimumValue, int); // Description: // Set/Get the maximum value. The current value will be clamped only if // ClampMaximumValue is true. vtkSetMacro(MaximumValue, double); vtkGetMacro(MaximumValue, double); vtkSetMacro(ClampMaximumValue, int); vtkGetMacro(ClampMaximumValue, int); vtkBooleanMacro(ClampMaximumValue, int); // Description: // Set the range. virtual void SetRange(double min, double max) { this->SetMinimumValue(min); this->SetMaximumValue(max); }; virtual void SetRange(const double *range) { this->SetRange(range[0], range[1]); }; // Description: // Set/Get the resolution of the thumbwheel. Moving the thumbwheel will // increase/decrease the value by an amount proportional to this resolution. // If the Clamp option is set, then the value will always be an integer // number of increments of Resolution offset from the MinimumValue; for // example, if the MinimumValue is -0.5 and the MaximumValue is 1.0 and // the Resolution is set to .75, then Value can only be -0.5, 0.25, or 1.0. virtual void SetResolution(double r); vtkGetMacro(Resolution, double); vtkSetMacro(ClampResolution, int); vtkGetMacro(ClampResolution, int); vtkBooleanMacro(ClampResolution, int); // Description: // Set the interaction modes (mode 0 is left button, 1 is middle, // 2 is right). // Note: set it before setting the balloon help string. //BTX enum { InteractionModeNone = 0, InteractionModeLinearMotion, InteractionModeNonLinearMotion, InteractionModeToggleCenterIndicator }; //ETX virtual void SetInteractionMode(int mode, int v); virtual int GetInteractionMode(int mode); virtual void SetInteractionModeToNone(int mode) { this->SetInteractionMode( mode, vtkKWThumbWheel::InteractionModeNone); }; virtual void SetInteractionModeToLinear(int mode) { this->SetInteractionMode( mode, vtkKWThumbWheel::InteractionModeLinearMotion); }; virtual void SetInteractionModeToNonLinear(int mode) { this->SetInteractionMode( mode, vtkKWThumbWheel::InteractionModeNonLinearMotion); }; virtual void SetInteractionModeToToggleCenterIndicator(int mode) { this->SetInteractionMode( mode, vtkKWThumbWheel::InteractionModeToggleCenterIndicator); }; virtual char *GetInteractionModeAsString(int mode); // Description: // Set/Get the % of the thumbwheel's current width that must be "travelled" // by the mouse so that the value is increased/decreased by one resolution // unit (Resolution ivar). Linear mode only. // Example: if the threshold is 0.1, the current width is 100 pixels and // the resolution is 2, then the mouse must be moved 10 pixels to "the right" // to add 2 to the current value. // If set to 0, a reasonable value will be picked computed from the // whole range and the resolution. vtkSetClampMacro(LinearThreshold, double, 0.0, 1.0); vtkGetMacro(LinearThreshold, double); // Description: // Set/Get the maximum multiplier in non-linear mode. This bounds the // scaling factor applied to the resolution when the thumbwheel is reaching // its maximum left or right position. vtkSetMacro(NonLinearMaximumMultiplier, double); vtkGetMacro(NonLinearMaximumMultiplier, double); // Description: // Set/Get the width and height of the thumbwheel. Can't be smaller than 5x5. virtual void SetThumbWheelWidth(int v); vtkGetMacro(ThumbWheelWidth, int); virtual void SetThumbWheelHeight(int v); vtkGetMacro(ThumbWheelHeight, int); virtual void SetThumbWheelSize(int w, int h) { this->SetThumbWheelWidth(w); this->SetThumbWheelHeight(h); }; virtual void SetLength(int v) { this->SetThumbWheelWidth(v); }; // Description: // Enable/Disable automatic thumbwheel resizing. Turn it off if you want // a specific thumbwheel size, otherwise it will resize when its parent // widget expands. Note that the ThumbWheelWidth and ThumbWheelHeight ivars // are updated accordingly automatically. virtual void SetResizeThumbWheel(int flag); vtkGetMacro(ResizeThumbWheel, int); vtkBooleanMacro(ResizeThumbWheel, int); // Description: // Display/Hide a thumbwheel position indicator when the user performs a // motion. This is just a vertical colored bar following the mouse position. // Set/Get the indicator color. vtkSetMacro(DisplayThumbWheelPositionIndicator, int); vtkGetMacro(DisplayThumbWheelPositionIndicator, int); vtkBooleanMacro(DisplayThumbWheelPositionIndicator, int); vtkSetVector3Macro(ThumbWheelPositionIndicatorColor, double); vtkGetVectorMacro(ThumbWheelPositionIndicatorColor, double, 3); // Description: // Display/Hide a centrer indicator so that the user can easily find the // positive and negative part of the range. virtual void SetDisplayThumbWheelCenterIndicator(int flag); vtkGetMacro(DisplayThumbWheelCenterIndicator, int); vtkBooleanMacro(DisplayThumbWheelCenterIndicator, int); virtual void ToggleDisplayThumbWheelCenterIndicator(); // Description: // Set/Get the average size (in pixels) of the notches on the visible part // of the thumbwheel. Can be a decimal value, since it's only used to compute // the number of notches to display depending on the current thumbwheel size. virtual void SetSizeOfNotches(double v); vtkGetMacro(SizeOfNotches, double); // Description: // Display/Hide an entry field (optional). virtual void SetDisplayEntry(int flag); vtkGetMacro(DisplayEntry, int); vtkBooleanMacro(DisplayEntry, int); vtkGetObjectMacro(Entry, vtkKWEntry); // Description: // Display/Hide/Set a label (optional). virtual void SetDisplayLabel(int flag); vtkGetMacro(DisplayLabel, int); vtkBooleanMacro(DisplayLabel, int); virtual vtkKWLabel* GetLabel(); // Description: // Set/Get the position of the label and/or entry (on top, or on the side). virtual void SetDisplayEntryAndLabelOnTop(int flag); vtkGetMacro(DisplayEntryAndLabelOnTop, int); vtkBooleanMacro(DisplayEntryAndLabelOnTop, int); // Description: // Set/Get the popup mode. // WARNING: this mode must be set *before* Create() is called. vtkSetMacro(PopupMode, int); vtkGetMacro(PopupMode, int); vtkBooleanMacro(PopupMode, int); vtkGetObjectMacro(PopupPushButton, vtkKWPushButton); // Description: // Set/Get the entry expansion flag. This flag is only used if PopupMode // is On. In that case, the default behaviour is to provide a widget as // compact as possible, i.e. the Entry won't be expanded if the widget grows. // Set ExpandEntry to On to override this behaviour. virtual void SetExpandEntry(int flag); vtkGetMacro(ExpandEntry, int); vtkBooleanMacro(ExpandEntry, int); // Description: // Specifies commands to associate with the widget. // 'Command' is invoked when the widget value is changing (i.e. during // user interaction). // 'StartCommand' is invoked at the beginning of a user interaction with // the widget (when a mouse button is pressed over the widget for example). // 'EndCommand' is invoked at the end of the user interaction with the // widget (when the mouse button is released for example). // 'EntryCommand' is invoked when the widget value is changed using // the text entry. // The need for a 'Command', 'StartCommand' and 'EndCommand' can be // explained as follows: 'EndCommand' can be used to be notified about any // changes made to this widget *after* the corresponding user interaction has // been performed (say, after releasing the mouse button that was dragging // a slider, or after clicking on a checkbutton). 'Command' can be set // *additionally* to be notified about the intermediate changes that // occur *during* the corresponding user interaction (say, *while* dragging // a slider). While setting 'EndCommand' is enough to be notified about // any changes, setting 'Command' is an application-specific choice that // is likely to depend on how fast you want (or can) answer to rapid changes // occuring during a user interaction, if any. 'StartCommand' is rarely // used but provides an opportunity for the application to modify its // state and prepare itself for user-interaction; in that case, the // 'EndCommand' is usually set in a symmetric fashion to set the application // back to its previous state. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the current value: int (if Resolution is integer); double otherwise // Note: the 'int' signature is for convenience, so that the command can // be set to a callback accepting 'int'. In doubt, implement the callback // using a 'double' signature that will accept both 'int' and 'double'. virtual void SetCommand(vtkObject *object, const char *method); virtual void SetStartCommand(vtkObject *object, const char *method); virtual void SetEndCommand(vtkObject *object, const char *method); virtual void SetEntryCommand(vtkObject *object, const char *method); // Description: // Events. The ThumbWheelValueChangingEvent is triggered when the widget // value is changed (i.e., during user interaction on the widget's // thumbhweel), the ThumbWheelValueStartChangingEvent is invoked at the // beginning of an interaction with the widget, the // ThumbWheelValueChangedEvent is invoked at the end of an interaction with // the widget. They are similar in concept as the 'Command', 'StartCommand', // and 'EndCommand' callbacks but can be used by multiple listeners/observers // at a time. // The following parameters are also passed as client data: // - the current value: double //BTX enum { ThumbWheelValueChangingEvent = 10000, ThumbWheelValueChangedEvent, ThumbWheelValueStartChangingEvent }; //ETX // Description: // Setting this string enables balloon help for this widget. // Override to pass down to children for cleaner behavior. virtual void SetBalloonHelpString(const char *str); // Description: // Bind/Unbind all components so that values can be changed, but // no command will be called. void Bind(); void UnBind(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void ResizeThumbWheelCallback(); virtual void DisplayPopupCallback(); virtual void WithdrawPopupCallback(); virtual void EntryValueCallback(const char*); virtual void StartLinearMotionCallback(); virtual void PerformLinearMotionCallback(); virtual void StartNonLinearMotionCallback(); virtual void PerformNonLinearMotionCallback(); virtual void StopMotionCallback(); protected: vtkKWThumbWheel(); ~vtkKWThumbWheel(); // Description: // Create the widget. virtual void CreateWidget(); double Value; double MinimumValue; int ClampMinimumValue; double MaximumValue; int ClampMaximumValue; double Resolution; int ClampResolution; double NonLinearMaximumMultiplier; double LinearThreshold; int ThumbWheelWidth; int ThumbWheelHeight; double SizeOfNotches; double ThumbWheelPositionIndicatorColor[3]; int ResizeThumbWheel; int DisplayLabel; int DisplayEntry; int DisplayEntryAndLabelOnTop; int DisplayThumbWheelPositionIndicator; int DisplayThumbWheelCenterIndicator; int PopupMode; int ExpandEntry; char *Command; char *StartCommand; char *EndCommand; char *EntryCommand; virtual void InvokeThumbWheelCommand(const char *command, double value); virtual void InvokeCommand(double value); virtual void InvokeStartCommand(double value); virtual void InvokeEndCommand(double value); virtual void InvokeEntryCommand(double value); double ThumbWheelShift; int InteractionModes[3]; vtkKWLabel *ThumbWheel; vtkKWEntry *Entry; vtkKWLabel *Label; vtkKWTopLevel *TopLevel; vtkKWPushButton *PopupPushButton; void CreateEntry(); void CreateLabel(); void UpdateThumbWheelImage(double pos = -1.0); void PackWidget(); double GetMousePositionInThumbWheel(); //BTX int State; enum WidgetState { Idle, InMotion }; class LinearMotionState { public: double Value; double ThumbWheelShift; double MousePosition; int InPerform; }; class NonLinearMotionState { public: double Value; double Increment; int InPerform; }; //ETX LinearMotionState StartLinearMotionState; NonLinearMotionState StartNonLinearMotionState; int InInvokeCommand; void RefreshValue(); private: vtkKWThumbWheel(const vtkKWThumbWheel&); // Not implemented void operator=(const vtkKWThumbWheel&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWPresetSelector.h0000644000175000017500000013005111305300761021160 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWPresetSelector.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWPresetSelector - a preset selector. // .SECTION Description // This class is the basis for a preset selector framework. // Presets can be added to the selector and identified by unique IDs. // They can be assigned pre-defined fields like a group, a filename, // a comment, a thumbnail and a screenshot, as well as an unlimited number // of user-defined slots. // Presets are listed vertically in a table list widget (vtkKWMultiColumnList), // one by row. Each column is used to display one of the predefined field. // The class can be used as-is, or extended to support more columns or // features, as examplified in the vtkKWWindowLevelPresetSelector and // vtkKWVolumePropertyPresetSelector sub-classes. // Several callbacks can be specified to enable external code to // add presets, apply presets, update them, etc. // presets. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWWindowLevelPresetSelector vtkKWVolumePropertyPresetSelector #ifndef __vtkKWPresetSelector_h #define __vtkKWPresetSelector_h #include "vtkKWCompositeWidget.h" class vtkImageData; class vtkKWIcon; class vtkKWMultiColumnListWithScrollbars; class vtkKWPresetSelectorInternals; class vtkKWPushButtonSet; class vtkRenderWindow; class vtkKWMenu; class vtkKWToolbar; class vtkKWLabelWithLabel; class KWWidgets_EXPORT vtkKWPresetSelector : public vtkKWCompositeWidget { public: static vtkKWPresetSelector* New(); vtkTypeRevisionMacro(vtkKWPresetSelector, vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Add a new preset to the end of the list, or insert a preset in front // of another preset, given its Id (if passed -1 as Id, insert at the // beginning). // Return the unique Id of the new preset, or -1 on error. virtual int AddPreset(); virtual int InsertPreset(int id); // Description: // Query if pool has given preset. // Return 1 if in the pool, 0 otherwise virtual int HasPreset(int id); // Description: // Set/Get the group associated to a preset. // This provide a way of grouping presets. // The group field is not displayed as a column by default, but this // can be changed using the SetGroupColumnVisibility() method. // This column can not be edited by default, but this can be changed by // a subclass. // Return 1 on success, 0 on error virtual int SetPresetGroup(int id, const char *group); virtual const char* GetPresetGroup(int id); // Description: // Set/Get the visibility of the group column. Hidden by default. // No effect if called before Create(). virtual void SetGroupColumnVisibility(int); virtual int GetGroupColumnVisibility(); vtkBooleanMacro(GroupColumnVisibility, int); // Description: // Set/Get the title of the group column. // No effect if called before Create(). virtual void SetGroupColumnTitle(const char *); virtual const char* GetGroupColumnTitle(); // Description: // Set/Get the comment associated to a preset. // This provide a way to create a small description or comment for // each preset. // The comment field is displayed as a column by default, but this // can be changed using the SetCommentColumnVisibility() method. // This column can be edited by default, by double-clicking // on the corresponding table cell. // Return 1 on success, 0 on error virtual int SetPresetComment(int id, const char *comment); virtual const char* GetPresetComment(int id); // Description: // Set/Get the visibility of the comment column. // No effect if called before Create(). virtual void SetCommentColumnVisibility(int); virtual int GetCommentColumnVisibility(); vtkBooleanMacro(CommentColumnVisibility, int); // Description: // Set/Get the filename associated to a preset. // This field is neither used nor displayed in this implementation // but is provided for subclasses that need to save preset to disks // and keep track of the corresponding filename. // A method is available to retrieve the Id of the preset that has // been assigned a specific filename (if passed a relative name, compare // the filenames without their paths). // Return 1 on success, 0 on error (id on success, -1 otherwise) virtual int SetPresetFileName(int id, const char *filename); virtual const char* GetPresetFileName(int id); virtual int GetIdOfPresetWithFileName(const char *filename); // Description: // Get the creation time of a preset, as returned by // the vtksys::SystemTools::GetTime() method, but in milliseconds. // This field is not displayed in this implementation, but is // used internally in the thumbnail column so that sorting by // "thumbnail" will actually sort by creation time. // Return 0 on error. virtual vtkTypeInt64 GetPresetCreationTime(int id); // Description: // Set/Get the thumbnail and screenshot associated to a preset. // The thumbnail is displayed in the thumbnail column, and the screenshot // is displayed as a pop-up when the user hovers over that thumbnail. // The thumbnail field is not displayed as a column by default, but this // can be changed using the SetThumbnailColumnVisibility() method. // Note that the vtkKWIcon object passed as parameter is neither // stored nor Register()'ed, only a copy is stored (and updated each // time the Set... method is called later on). virtual vtkKWIcon* GetPresetThumbnail(int id); virtual int SetPresetThumbnail(int id, vtkKWIcon *icon); virtual vtkKWIcon* GetPresetScreenshot(int id); virtual int SetPresetScreenshot(int id, vtkKWIcon *icon); // Description: // Set/Get the visibility of the thumbnail column. // No effect if called before Create(). virtual void SetThumbnailColumnVisibility(int); virtual int GetThumbnailColumnVisibility(); vtkBooleanMacro(ThumbnailColumnVisibility, int); // Description: // Build both the thumbnail and screenshot for a specific preset using a // vtkImageData. The thumbnail is constructed by resampling the image to // fit the ThumbnailSize constraint. The screenshot is constructed by // resampling the image to fit the ScreenshotSize constraint. // This method is typically useful to build both thumbnail // and screenshot from a single larger image (or screenshot). // A similar method can be passed a vtkRenderWindow instead of a // vtkImageData; in that case, the window contents is grabbed and used // to build both thumbnail and screenshot. // Both thumbnail and screenshot icons can be retrieved. // Return 1 on success, 0 on error virtual int BuildPresetThumbnailAndScreenshotFromImage( int id, vtkImageData *image); virtual int BuildPresetThumbnailAndScreenshotFromRenderWindow( int id, vtkRenderWindow *win); // Description: // Flip the thumbnail and screenshot vertically for a specific preset // Return 1 on success, 0 on error virtual int FlipPresetThumbnailAndScreenshotVertically(int id); // Description: // Set/Get the thumbnail size. // Changing the size will not resize the current thumbnails, but will // affect the presets added to the selector later on using the // BuildPresetThumbnailAndScreenshotFromImage method. vtkSetClampMacro(ThumbnailSize,int,8,512); vtkGetMacro(ThumbnailSize,int); // Description: // Set/Get the screenshot size, i.e. the image that appears as // a popup when the mouse is on top of the thumbnail. // Changing the size will not resize the current screenshots, but will // affect the presets added to the selector later on using the // BuildPresetThumbnailAndScreenshotFromImage method. vtkSetClampMacro(ScreenshotSize,int,8,2048); vtkGetMacro(ScreenshotSize,int); // Description: // Set/Get a preset user slot. // An unlimited number of slots can be added to a preset. Each slot is // identified by a name (string). Methods are provided to store // and retrieve various types of data (double, int, string, generic pointer, // pointer to vtkObject). Note a SetPresetUserSlotAsObject *does* call // Register() on the object passed as parameter, and will call UnRegister() // once it is time to remove/deallocate all presets (either automatically // when this instance is deleted or programatically). // Note that setting the value of a slot will automatically call // ScheduleUpdatePresetRow for the specific preset if the value was // different than the previous value. // Return 1 on success, 0 on error //BTX enum { UserSlotDoubleType = 0, UserSlotIntType, UserSlotUnsignedLongType, UserSlotInt64Type, UserSlotStringType, UserSlotPointerType, UserSlotObjectType, UserSlotUnknownType }; //ETX virtual int HasPresetUserSlot( int id, const char *slot_name); virtual int GetPresetUserSlotType( int id, const char *slot_name); virtual int DeletePresetUserSlot( int id, const char *slot_name); virtual int SetPresetUserSlotAsDouble( int id, const char *slot_name, double value); virtual double GetPresetUserSlotAsDouble( int id, const char *slot_name); virtual int SetPresetUserSlotAsInt( int id, const char *slot_name, int value); virtual int GetPresetUserSlotAsInt( int id, const char *slot_name); virtual int SetPresetUserSlotAsUnsignedLong( int id, const char *slot_name, unsigned long value); virtual unsigned long GetPresetUserSlotAsUnsignedLong( int id, const char *slot_name); virtual int SetPresetUserSlotAsInt64( int id, const char *slot_name, vtkTypeInt64 value); virtual vtkTypeInt64 GetPresetUserSlotAsInt64( int id, const char *slot_name); virtual int SetPresetUserSlotAsString( int id, const char *slot_name, const char *value); virtual const char* GetPresetUserSlotAsString( int id, const char *slot_name); virtual int SetPresetUserSlotAsPointer( int id, const char *slot_name, void *ptr); virtual void* GetPresetUserSlotAsPointer( int id, const char *slot_name); virtual int SetPresetUserSlotAsObject( int id, const char *slot_name, vtkObject *obj); virtual vtkObject* GetPresetUserSlotAsObject( int id, const char *slot_name); // Description: // Most (if not all) of the information associated to a preset (say group, // comment, filename, creation time, thumbnail and screenshot) is stored // under the hood as user slots using the corresponding API (i.e. // Set/GetPresetUserSlotAs...()). Since each slot requires a unique name, // the following methods are provided to retrieve the slot name for // the default preset fields. This can be useful to avoid collision between // the default slots and your own user slots. Note that the default slot // names can be changed too, but doing so will not transfer the value // stored at the old slot name to the new slot name (it is up to you to do // so, if needed). virtual void SetPresetGroupSlotName(const char *); virtual const char* GetPresetGroupSlotName(); virtual void SetPresetCommentSlotName(const char *); virtual const char* GetPresetCommentSlotName(); virtual void SetPresetFileNameSlotName(const char *); virtual const char* GetPresetFileNameSlotName(); virtual void SetPresetCreationTimeSlotName(const char *); virtual const char* GetPresetCreationTimeSlotName(); virtual void SetPresetThumbnailSlotName(const char *); virtual const char* GetPresetThumbnailSlotName(); virtual void SetPresetScreenshotSlotName(const char *); virtual const char* GetPresetScreenshotSlotName(); // Description: // Set/Get the preset filter constraints. // The preset filter is a set of constraints that a preset has to match // to be visible in the preset list. // Only string and int slots are supported at the moment. // At the moment, constraints are expressed as string values (default) or // regular expressions that have to match specific user slots. An // unlimited number of constraints can be added. // For example, if 'slot_name' is 'Modality', and 'value' is // 'CT', then only those presets which have a 'Modality' user slot with // a string value of 'CT' will be displayed. // Note that the constraint type can be changed from regular expression // to plain character-for-character string comparison using either // SetPresetFilterUserSlotConstraintToRegularExpression or // SetPresetFilterUserSlotConstraintToString; however the constraint needs to // exist for that slot name for this change to be made. When one constraint // is added, its default type is String, not RegularExpression. // Use a NULL value for to remove the constraint on a specific slot or // call DeletePresetFilterUserSlotConstraint virtual void ClearPresetFilter(); virtual void SetPresetFilterUserSlotConstraint( const char *slot_name, const char *value); virtual const char* GetPresetFilterUserSlotConstraint( const char *slot_name); virtual void DeletePresetFilterUserSlotConstraint(const char *slot_name); virtual void SetPresetFilterUserSlotConstraintToRegularExpression( const char *slot_name); virtual void SetPresetFilterUserSlotConstraintToString( const char *slot_name); // Description: // Add a preset filter constraint on the preset group field. virtual void SetPresetFilterGroupConstraint(const char *value); virtual const char* GetPresetFilterGroupConstraint(); // Description: // Query if a given preset matches the current preset filter constraints. // Return 1 if match or if no filter was defined, 0 otherwise virtual int IsPresetFiltered(int id); // Description: // Get the number of presets, or the number of presets with a specific // group, or the number of visible presets, i.e. the presets that are // displayed according to the preset filters for example. virtual int GetNumberOfPresets(); virtual int GetNumberOfPresetsWithGroup(const char *group); virtual int GetNumberOfVisiblePresets(); // Description: // Set/Get the maximum number of presets. When this number is passed, the // oldest preset (according to the PresetCreationTime) is deleted // automatically. Set it to 0 (default) to allow for unlimited number // of presets. vtkGetMacro(MaximumNumberOfPresets, int); virtual void SetMaximumNumberOfPresets(int); // Description: // Query if a given preset is visible (i.e. displayed in the list). // Some presets can be hidden, for example if they do not match // the current preset filter constraints. virtual int GetPresetVisibility(int id); // Description: // Retrieve the Id of the nth-preset, or the id of the // nth preset with a given group. // Return id on success, -1 otherwise virtual int GetIdOfNthPreset(int index); virtual int GetIdOfNthPresetWithGroup(int index, const char *group); // Description: // Retrieve the Id of the preset at a given row in the table, or // the row of a given preset. // Return id or row index on success, -1 otherwise virtual int GetIdOfPresetAtRow(int row_index); virtual int GetPresetRow(int id); // Description: // Retrieve the rank of the nth preset with a given group // (i.e. the nth-preset with a given group). // This rank can then be used to retrieve the preset id using // the GetIdOfNthPreset() method. // Return rank on success, -1 otherwise virtual int GetRankOfNthPresetWithGroup(int index, const char *group); // Description: // Remove a preset, or all of them, or all of the presets // with the same group. // Return 1 on success, 0 on error virtual int RemovePreset(int id); virtual int RemoveAllPresets(); virtual int RemoveAllPresetsWithGroup(const char *group); // Description: // Select a preset, clear the selection. virtual void SelectPreset(int id); virtual void SelectPreviousPreset(); virtual void SelectNextPreset(); virtual void ClearSelection(); virtual int GetIdOfSelectedPreset(); // Description: // Set/Get the list height (in number of items) or width (in chars) // No effect if called before Create(). virtual void SetListHeight(int); virtual int GetListHeight(); virtual void SetListWidth(int); virtual int GetListWidth(); // Description: // Set/Get the base icons to use for the preset buttons (and the toolbar). // The base icon has to be in RGBA format, and will be composited against // a few different smaller icons to represent each action; for example, // a '+' sign will be composited on top of the base icon for the // "Add Preset" button. vtkGetObjectMacro(PresetButtonsBaseIcon, vtkKWIcon); virtual void SetPresetButtonsBaseIcon(vtkKWIcon *icon); virtual void SetPresetButtonsBaseIconToPredefinedIcon(int icon_index); // Description: // Set/Get the visibility of the select spin buttons. // The select spin button are two buttons that can be used // to select the next or previous preset in the list. // Note that if ApplyPresetOnSelection is On, this will also apply // the preset at the same time, thus providing a quick way to // loop over all presets and apply them. virtual void SetSelectSpinButtonsVisibility(int); vtkGetMacro(SelectSpinButtonsVisibility,int); vtkBooleanMacro(SelectSpinButtonsVisibility,int); // Description: // Set/Get the visibility of the locate preset button and the "Locate" menu // entry in the context menu (hidden by default). // If visible, triggering this button will locate all selected presets // by calling the GetPresetFileName method and trying to open // the directory they are in and select the proper file. // Win32 only at the moment. virtual void SetLocateButtonVisibility(int); vtkGetMacro(LocateButtonVisibility,int); vtkBooleanMacro(LocateButtonVisibility,int); vtkSetMacro(LocateMenuEntryVisibility,int); vtkGetMacro(LocateMenuEntryVisibility,int); vtkBooleanMacro(LocateMenuEntryVisibility,int); // Description: // Set/Get the visibility of the email preset button and the "Email" menu // entry in the context menu (hidden by default). // If visible, triggering this button will email all selected presets // as attachments. The attachment location is retrieved by calling // the GetPresetFileName method. Win32/MAPI only at the moment. virtual void SetEmailButtonVisibility(int); vtkGetMacro(EmailButtonVisibility,int); vtkBooleanMacro(EmailButtonVisibility,int); vtkSetMacro(EmailMenuEntryVisibility,int); vtkGetMacro(EmailMenuEntryVisibility,int); vtkBooleanMacro(EmailMenuEntryVisibility,int); // Description: // Set/Get the body of the email that will be sent alongside the attached // preset when the "Email Preset" button or menu entry is triggered. // Note that it will still appear after a shot paragraph describing which // application sent that preset, the location of the preset on the sender's // computer, the comment associated to the preset and its creation time. vtkSetStringMacro(EmailBody); vtkGetStringMacro(EmailBody); // Description: // Set/Get the visibility of the remove preset button or the "Remove" entry // in the context menu (visible by default). // If visible, triggering this button will remove all selected presets and // eventually call the callbacks that was set using SetPresetRemoveCommand. virtual void SetRemoveButtonVisibility(int); vtkGetMacro(RemoveButtonVisibility,int); vtkBooleanMacro(RemoveButtonVisibility,int); vtkGetMacro(RemoveMenuEntryVisibility,int); vtkSetMacro(RemoveMenuEntryVisibility,int); vtkBooleanMacro(RemoveMenuEntryVisibility,int); // Description: // Set/Get the visibility of the filter button (hidden by default). // If visible, clicking on this button will bring the a popup menu // presenting all the unique values that were collected in the // FilterButtonSlotName slot for all presets. // Each one can be turn on and off, which will update the // PresetFilterUserSlotConstraint automatically for that slot. virtual void SetFilterButtonVisibility(int); vtkGetMacro(FilterButtonVisibility,int); vtkBooleanMacro(FilterButtonVisibility,int); vtkSetStringMacro(FilterButtonSlotName); vtkGetStringMacro(FilterButtonSlotName); // Description: // Set/Get the visibility of the help message. virtual void SetHelpLabelVisibility(int); vtkGetMacro(HelpLabelVisibility,int); vtkBooleanMacro(HelpLabelVisibility,int); vtkGetObjectMacro(HelpLabel, vtkKWLabelWithLabel); virtual void SetHelpLabelText(const char *); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the "add preset" button is pressed. // This gives the opportunity for the application to check and collect the // relevant information to store in a new preset. The application is then // free to add the preset (using the AddPreset() method) and set its // fields independently (using the SetPresetGroup(), SetPresetComment(), // SetPreset...() methods). // Note that if not set, the "add preset" button is not visible. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following output is expected from the command: // - the unique id of the preset that was added (by calling AddPreset()), // -1 otherwise virtual void SetPresetAddCommand(vtkObject *object, const char *method); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the "update selected preset" button // is pressed. This gives the opportunity for the application to check and // collect the relevant information to update in the preset. The application // is then free to update the preset's fields independently (using the // SetPresetGroup(), SetPresetComment(), SetPreset...() methods). // Note that if this command is not set, the corresponding // "update selected preset" button is not visible. // Note that if this command is not set, the corresponding "Update" entry // is not shown in the context menu. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the id of the preset to update: int virtual void SetPresetUpdateCommand(vtkObject *object, const char *method); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the "apply selected preset" button is pressed, // or when ApplyPresetOnSelection is On and the user // applies a preset by selecting it directly. This gives the opportunity // for the application to query the preset's fields independently (using the // GetPresetGroup(), GetPresetComment(), GetPreset...() methods) and // apply those values to the relevant objects. // Note that if this command is not set or if ApplyPresetOnSelection is On, // the corresponding "apply selected preset" button is not visible. // Note that if this command is not set, the corresponding "Apply" entry // is not shown in the context menu. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the id of the preset to apply: int virtual void SetPresetApplyCommand(vtkObject *object, const char *method); // Description: // Set/Get if a preset should be applied directly when it is selected by a // single-click, or only when the "apply selected preset" button is pressed. // If set, only one preset can be selected at a time (if not, multiple // preset can be selected, and removed for example). // Note that if set, the "apply selected preset" button is not visible. virtual void SetApplyPresetOnSelection(int); vtkGetMacro(ApplyPresetOnSelection,int); vtkBooleanMacro(ApplyPresetOnSelection,int); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the "remove selected preset" // button is pressed. This command is called *before* the preset is // removed from the pool: this gives the opportunity for the application // to query the preset's fields independently (using the // GetPresetGroup(), GetPresetComment(), GetPreset...() methods), // decide if the preset should be removed or not, and delete it from // its internal structures accordingly, if needed. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the id of the preset to remove: int // The following output is expected from the command: // - whereas the preset is really to be removed (1) or not (0): int virtual void SetPresetRemoveCommand(vtkObject *object, const char *method); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when a preset has been removed as a result of // pressing the "remove selected preset" button. As opposed to the // PresetRemoveCommand, this command is called *after* the preset is // removed from the pool and only if it has been removed (its Id is // therefore not passed to the callback as a parameter). Do not confuse // this command with PresetRemoveCommand which gives the opportunity for // the application to decide if the preset should be removed or not. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetPresetRemovedCommand(vtkObject *object, const char *method); // Description: // Set/Get if the user should be prompted before removing one or // more presets using "remove selected preset" button. vtkSetMacro(PromptBeforeRemovePreset, int); vtkGetMacro(PromptBeforeRemovePreset, int); vtkBooleanMacro(PromptBeforeRemovePreset, int); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the preset has been changed using direct // user-interaction on the widget interface. // This includes double-clicking on a table cell (the comment field for // example) and editing the contents of the cell directly, when allowed. // This gives the opportunity for the application to query the preset's // fields independently (using the GetPresetGroup(), GetPresetComment(), // GetPreset...() methods), and update its internal structures accordingly, // if needed. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the id of the preset that has changed: int virtual void SetPresetHasChangedCommand( vtkObject *object, const char *method); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the "load preset" button is pressed. // This gives the opportunity for the application to invoke a file dialog, // let the user pick a preset file, load it and collect the relevant // information to store in a new preset. The application is then // free to add the preset (using the AddPreset() method) and set its // fields independently (using the SetPresetGroup(), SetPresetComment(), // SetPreset...() methods). // Note that if not set, the "load preset" button is not visible. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following output is expected from the command: // - the unique id of the preset that was loaded and added (by calling // AddPreset()), -1 otherwise virtual void SetPresetLoadCommand(vtkObject *object, const char *method); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the preset filtering has changed, i.e. a filter // constraint has been added/removed (see, ClearPresetFilter or // SetPresetFilterUserSlotConstraint). // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetPresetFilteringHasChangedCommand( vtkObject *object, const char *method); // Description: // Refresh the interface. virtual void Update(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callback used to refresh the contents of the image cell for each preset virtual void PresetCellThumbnailCallback(const char*, int, int, const char*); // Description: // Callback invoked when the user starts editing a specific preset field // located at cell ('row', 'col'), which current contents is 'text'. // This method returns the value that is to become the initial // contents of the temporary embedded widget used for editing: most of the // time, this is the same value as 'text'. // The next step (validation) is handled by PresetCellEditEndCallback virtual const char* PresetCellEditStartCallback( int row, int col, const char *text); // Description: // Callback invoked when the user ends editing a specific preset field // located at cell ('row', 'col'). // The main purpose of this method is to perform a final validation of // the edit window's contents 'text'. // This method returns the value that is to become the new contents // for that cell. // The next step (updating) is handled by PresetCellUpdateCallback virtual const char* PresetCellEditEndCallback( int row, int col, const char *text); // Description: // Callback invoked when the user successfully updated the preset field // located at ('row', 'col') with the new contents 'text', as a result // of editing the corresponding cell interactively. virtual void PresetCellUpdatedCallback(int row, int col, const char *text); // Description: // Retrieve the toolbar. Use that method to set the parent of this object to // a specific widget or toolbar set (vtkKWToolbarSet), before calling // CreateToolbar. virtual vtkKWToolbar* GetToolbar(); // Description: // Create the toolbar. If the toolbar has to be placed in a specific location // in the application, call the GetToolbar method and set the toolbar parent // beforehand. virtual void CreateToolbar(); // Description: // Some constants //BTX static const char *IdColumnName; static const char *ThumbnailColumnName; static const char *GroupColumnName; static const char *CommentColumnName; //ETX // Description: // Callbacks. Internal, do not use. virtual int PresetAddCallback(); virtual void PresetApplyCallback(); virtual void PresetApplyCallback(int id); virtual void PresetUpdateCallback(); virtual void PresetUpdateCallback(int id); virtual void PresetRemoveCallback(); virtual void PresetRemoveAllCallback(); virtual void PresetRemoveCallback(int id); virtual void PresetEmailCallback(); virtual void PresetEmailCallback(int id); virtual void PresetLocateCallback(); virtual void PresetLocateCallback(int id); virtual void PresetSelectionCallback(); virtual void PresetSelectionChangedCallback(); virtual void PresetRightClickCallback(int row, int col, int x, int y); virtual int PresetLoadCallback(); virtual void PresetFilterCallback(); virtual void PresetFilterApplyCallback(const char *regexp); virtual void UpdatePresetRowCallback(int id); virtual void UpdatePresetRowsCallback(); virtual void ColumnSortedCallback(); virtual void RowMovedCallback(); virtual void SchedulePresetSelectionCallback(); virtual void SchedulePresetSelectionChangedCallback(); // Description: // Access to the internal multicolumn list. // This is temporary, this internal widget may change. vtkGetObjectMacro(PresetList, vtkKWMultiColumnListWithScrollbars); // Description: // Set the callbacks to be used to create, update, and set the icons and // help strings on user-defined buttons. These callbacks can be used to // add buttons to the preset selector toolbar(s), without subclassing it. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // Note that each callback will receive the following parameters: // CreateUserPresetButtonsCommand: vtkKWToolbar *toolbar, int use_separators // UpdateUserPresetButtonsCommand: vtkKWToolbar *toolbar // SetUserPresetButtonsIconsCommand: vtkKWToolbar *toolbar // SetUserPresetButtonsHelpStringsCommand: vtkKWToolbar *toolbar virtual void SetCreateUserPresetButtonsCommand( vtkObject *object, const char *method); virtual void SetUpdateUserPresetButtonsCommand( vtkObject *object, const char *method); virtual void SetSetUserPresetButtonsIconsCommand( vtkObject *object, const char *method); virtual void SetSetUserPresetButtonsHelpStringsCommand( vtkObject *object, const char *method); protected: vtkKWPresetSelector(); ~vtkKWPresetSelector(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Create the columns. // Subclasses should override this method to add their own columns and // display their own preset fields (do not forget to call the superclass // first). virtual void CreateColumns(); // Description: // Create the preset buttons in the toolbar. // Subclasses should override this method to add their own toolbar buttons // (do not forget to call the superclass first). virtual void CreateToolbarPresetButtons(vtkKWToolbar*, int use_separators); // Description: // Update the toolbar preset buttons state/visibility. virtual void UpdateToolbarPresetButtons(vtkKWToolbar*); // Description: // Set the toolbar preset buttons icons. // Subclasses should override this method to set their own icons // (do not forget to call the superclass first). virtual void SetToolbarPresetButtonsIcons(vtkKWToolbar*); // Description: // Set the toolbar preset buttons balloon help strings // Subclass can override this method to change the help strings // associated to the buttons. virtual void SetToolbarPresetButtonsHelpStrings(vtkKWToolbar*); // Description: // Configure a new preset. // Subclasses should override this method to configure a newly allocated // preset, i.e. assign its internal values (do not forget to call the // superclass first). virtual void ConfigureNewPreset(int id); // Description: // Deallocate a preset. // Subclasses should override this method to release the memory allocated // by their own preset fields (do not forget to call the superclass // first). virtual void DeAllocatePreset(int id); // Description: // Update the preset row, i.e. add a row for that preset if it is not // displayed already, hide it if it does not match the filters, and // update the table columns with the corresponding preset fields. // Subclass should override this method to display their own fields. // Return 1 on success, 0 if the row was not (or can not be) updated. // Subclasses should call the parent's UpdatePresetRow, and abort // if the result is not 1. virtual int UpdatePresetRow(int id); virtual void ScheduleUpdatePresetRow(int id); // Description: // Update the preset row itself in the list, i.e. add or remove a row // for a specific preset id in the multicolumn list. UpdatePresetRow() and/or // ScheduleUpdatePresetRow() will call this function first, then add // the contents of the row itself. Pass/set is_new to 1 if you are // sure the preset is new and was never inserted in the list. // Return row index on success (can be 0), -1 otherwise. virtual int UpdatePresetRowInMultiColumnList(int id, int is_new = 0); vtkKWMultiColumnListWithScrollbars *PresetList; vtkKWFrame *PresetControlFrame; vtkKWToolbar *PresetButtons; vtkKWToolbar *Toolbar; vtkKWLabelWithLabel *HelpLabel; vtkKWMenu *ContextMenu; vtkKWIcon *PresetButtonsBaseIcon; int ApplyPresetOnSelection; int SelectSpinButtonsVisibility; int EmailButtonVisibility; int EmailMenuEntryVisibility; int LocateButtonVisibility; int LocateMenuEntryVisibility; int RemoveButtonVisibility; int RemoveMenuEntryVisibility; int HelpLabelVisibility; int FilterButtonVisibility; int ThumbnailSize; int ScreenshotSize; int PromptBeforeRemovePreset; int MaximumNumberOfPresets; char *EmailBody; char *FilterButtonSlotName; // Description: // Called when the number of presets has changed. // Note that the name of this function can be a bit misleading: if // MaximumNumberOfPresets is set to a positive number, and the max // has been reached, this function will *still* be called twice, once // when the max is passed as a result of adding a preset, and then another // time when a preset is automatically deleted to get back to the maximum // value (which is, in most case, what you want to know anyway). virtual void NumberOfPresetsHasChanged(); // Description: // Called when preset filtering has changed, i.e. a filter // constraint has been added/removed (see, ClearPresetFilter or // SetPresetFilterUserSlotConstraint). virtual void PresetFilteringHasChanged(); // Description: // Called when preset filtering *may* have changed, the value of a slot has // changed and that slot was filtered (i.e. had a constraint put on it // using SetPresetFilterUserSlotConstraint), therefore it is possible that // preset maybe pass or not pass the filter anymore (IsPresetFiltered). virtual void PresetFilteringMayHaveChanged(); // PIMPL Encapsulation for STL containers //BTX vtkKWPresetSelectorInternals *Internals; //ETX // Description: // Update all rows in the list virtual void UpdatePresetRows(); virtual void ScheduleUpdatePresetRows(); virtual void CancelScheduleUpdatePresetRows(); char *PresetAddCommand; virtual int InvokePresetAddCommand(); char *PresetUpdateCommand; virtual void InvokePresetUpdateCommand(int id); char *PresetApplyCommand; virtual void InvokePresetApplyCommand(int id); char *PresetRemoveCommand; virtual int InvokePresetRemoveCommand(int id); char *PresetRemovedCommand; virtual void InvokePresetRemovedCommand(); char *PresetHasChangedCommand; virtual void InvokePresetHasChangedCommand(int id); char *PresetLoadCommand; virtual int InvokePresetLoadCommand(); char *PresetFilteringHasChangedCommand; virtual void InvokePresetFilteringHasChangedCommand(); char *CreateUserPresetButtonsCommand; virtual void InvokeCreateUserPresetButtonsCommand(vtkKWToolbar *, int); char *UpdateUserPresetButtonsCommand; virtual void InvokeUpdateUserPresetButtonsCommand(vtkKWToolbar *); char *SetUserPresetButtonsIconsCommand; virtual void InvokeSetUserPresetButtonsIconsCommand(vtkKWToolbar *); char *SetUserPresetButtonsHelpStringsCommand; virtual void InvokeSetUserPresetButtonsHelpStringsCommand(vtkKWToolbar *); // Description: // Get the index of a given column. virtual int GetIdColumnIndex(); virtual int GetThumbnailColumnIndex(); virtual int GetGroupColumnIndex(); virtual int GetCommentColumnIndex(); // Description: // Pack virtual void Pack(); // Description: // Populate the pop-up context menu that is displayed when right-clicking // on a give preset. It should replicate the commands available through the // preset buttons. virtual void PopulatePresetContextMenu(vtkKWMenu *menu, int id); // Description: // Some constants //BTX static int SelectPreviousButtonId; static int SelectNextButtonId; static int AddButtonId; static int ApplyButtonId; static int UpdateButtonId; static int RemoveButtonId; static int LocateButtonId; static int EmailButtonId; static int LoadButtonId; static int FilterButtonId; //ETX // Description: // Access to the button label virtual const char* GetSelectPreviousButtonLabel(); virtual const char* GetSelectNextButtonLabel(); virtual const char* GetAddButtonLabel(); virtual const char* GetApplyButtonLabel(); virtual const char* GetUpdateButtonLabel(); virtual const char* GetRemoveButtonLabel(); virtual const char* GetRemoveAllButtonLabel(); virtual const char* GetLocateButtonLabel(); virtual const char* GetEmailButtonLabel(); virtual const char* GetLoadButtonLabel(); virtual const char* GetFilterButtonLabel(); // Description: // Delete all presets, i.e. deallocate all presets and remove them // from the pool. Does not delete/remove any rows, see RemoveAllPresets() // to both delete all presets and update the table accordingly. // Return the number of presets deleted virtual int DeleteAllPresets(); // Description: // Return the number of selected presets with filename virtual int GetNumberOfSelectedPresetsWithFileName(); // Description: // Manage the preset Id to row index cache. virtual void SetPresetIdToRowIndexCacheEntry(int id, int row_index); virtual int GetPresetIdToRowIndexCacheEntry(int id); virtual void InvalidatePresetIdToRowIndexCache(); // Description: // Manage the row index to preset Id cache. virtual void SetRowIndexToPresetIdCacheEntry(int row_index, int id); virtual int GetRowIndexToPresetIdCacheEntry(int row_index); virtual void InvalidateRowIndexToPresetIdCache(); // Description: // Processes the events that are passed through CallbackCommand (or others). // Subclasses can oberride this method to process their own events, but // should call the superclass too. virtual void ProcessCallbackCommandEvents( vtkObject *caller, unsigned long event, void *calldata); // Description: // Constrain the number of presets (given MaximumNumberOfPresets). virtual void ConstrainNumberOfPresets(); // Description: // Set the creation time of a preset. // Not a public method, but subclass may have a need to set it manually, // say if the presets are serialized to disk, one may want to load/bring // them back with the same creation time as when they were first created. // Return 0 on error. virtual int SetPresetCreationTime(int id, vtkTypeInt64 value); private: vtkKWPresetSelector(const vtkKWPresetSelector&); // Not implemented void operator=(const vtkKWPresetSelector&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWFrame.cxx0000644000175000017500000001170310424463536017637 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWFrame.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWFrame.h" #include "vtkKWOptions.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWFrame); vtkCxxRevisionMacro(vtkKWFrame, "$Revision: 1.34 $"); //---------------------------------------------------------------------------- void vtkKWFrame::CreateWidget() { // Call the superclass to set the appropriate flags then create manually if (!vtkKWWidget::CreateSpecificTkWidget(this, "frame", "-highlightthickness 0")) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } } //---------------------------------------------------------------------------- void vtkKWFrame::GetBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWFrame::GetBackgroundColor() { return this->GetConfigurationOptionAsColor("-background"); } //---------------------------------------------------------------------------- void vtkKWFrame::SetBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- void vtkKWFrame::SetHighlightThickness(int width) { this->SetConfigurationOptionAsInt("-highlightthickness", width); } //---------------------------------------------------------------------------- int vtkKWFrame::GetHighlightThickness() { return this->GetConfigurationOptionAsInt("-highlightthickness"); } //---------------------------------------------------------------------------- void vtkKWFrame::SetBorderWidth(int width) { this->SetConfigurationOptionAsInt("-bd", width); } //---------------------------------------------------------------------------- int vtkKWFrame::GetBorderWidth() { return this->GetConfigurationOptionAsInt("-bd"); } //---------------------------------------------------------------------------- void vtkKWFrame::SetRelief(int relief) { this->SetConfigurationOption( "-relief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWFrame::SetReliefToRaised() { this->SetRelief(vtkKWOptions::ReliefRaised); }; void vtkKWFrame::SetReliefToSunken() { this->SetRelief(vtkKWOptions::ReliefSunken); }; void vtkKWFrame::SetReliefToFlat() { this->SetRelief(vtkKWOptions::ReliefFlat); }; void vtkKWFrame::SetReliefToRidge() { this->SetRelief(vtkKWOptions::ReliefRidge); }; void vtkKWFrame::SetReliefToSolid() { this->SetRelief(vtkKWOptions::ReliefSolid); }; void vtkKWFrame::SetReliefToGroove() { this->SetRelief(vtkKWOptions::ReliefGroove); }; //---------------------------------------------------------------------------- int vtkKWFrame::GetRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-relief")); } //---------------------------------------------------------------------------- void vtkKWFrame::SetPadX(int arg) { this->SetConfigurationOptionAsInt("-padx", arg); } //---------------------------------------------------------------------------- int vtkKWFrame::GetPadX() { return this->GetConfigurationOptionAsInt("-padx"); } //---------------------------------------------------------------------------- void vtkKWFrame::SetPadY(int arg) { this->SetConfigurationOptionAsInt("-pady", arg); } //---------------------------------------------------------------------------- int vtkKWFrame::GetPadY() { return this->GetConfigurationOptionAsInt("-pady"); } //---------------------------------------------------------------------------- void vtkKWFrame::SetWidth(int width) { this->SetConfigurationOptionAsInt("-width", width < 0 ? 0 : width); } //---------------------------------------------------------------------------- int vtkKWFrame::GetWidth() { return this->GetConfigurationOptionAsInt("-width"); } //---------------------------------------------------------------------------- void vtkKWFrame::SetHeight(int height) { this->SetConfigurationOptionAsInt("-height", height < 0 ? 0 : height); } //---------------------------------------------------------------------------- int vtkKWFrame::GetHeight() { return this->GetConfigurationOptionAsInt("-height"); } //---------------------------------------------------------------------------- void vtkKWFrame::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWOptionDataBase.h0000644000175000017500000001330210424510673021057 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWOptionDataBase.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWOptionDataBase - an option database // .SECTION Description // This class can be used to store entries specifying how to automatically // override the default settings/look&feel of any vtkKWWidget subclass at // run-time. // // For example, you may want all your vtkKWPushButton objects to use a blue // background by default; this can be done by adding the following entry // to the application's option database at startup: // myapplication->GetOptionDataBase()->AddEntry( // "vtkKWPushButton", "SetBackgroundColor", "0.2 0.2 0.8"); // From then on, anytime a vtkKWPushButton is created (using Create()), its // look&feel is configured and overriden automatically given the entries in // the database (here, its BackgroundColor is set to a blue-ish color). // // Collections of entries can be grouped inside a *theme*, subclass of // vtkKWTheme. Check the Examples/Cxx/Theme for more details. // Each vtkKWApplication object has a unique instance of a vtkKWOptionDataBase. // // Note that each entry is added as a pattern, a command, and a value: // // - the value can be empty if the command does not support any parameter, say: // AddEntry("vtkKWPushButton", "SetReliefToGroove", NULL) // // - the pattern can specify a constraint on the object context, i.e. require // that the command/value should only be applied if the object is of a // specific class *and* has specific parents; this provides a way to // configure widgets only when they are found inside other widgets: // AddEntry("vtkKWMessageDialog*vtkKWPushButton", "SetReliefToGroove",NULL) // => this entry will configure all vtkKWPushButton objects only if // they are found to be a child *or* a sub-child of a vtkKWMessageDialog. // AddEntry("vtkKWFrame.vtkKWPushButton", "SetReliefToGroove",NULL) // => this entry will configure all vtkKWPushButton objects only if // they are found to be an *immediate* child of a vtkKWFrame. // Of course, combinations can be used, say: // AddEntry("vtkKWMessageDialog*vtkKWFrame.vtkKWPushButton", ... // // - the pattern can specify a unique (terminal) slot suffix, that will be // used to configure a sub-object instead of the object itself. The // sub-object is retrieved by calling Get'slot name' on the object. // AddEntry("vtkKWFrameWithLabel:CollapsibleFrame", "SetReliefToSolid", 0); // => this entry will configure the sub-object retrieved by calling // GetCollapsibleFrame on any vtkKWFrameWithLabel object, not the object // itself. This can be useful to customize specific part of a mega-widget. // // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWTheme #ifndef __vtkKWOptionDataBase_h #define __vtkKWOptionDataBase_h #include "vtkKWObject.h" class vtkKWOptionDataBaseInternals; class vtkKWWidget; class KWWidgets_EXPORT vtkKWOptionDataBase : public vtkKWObject { public: static vtkKWOptionDataBase* New(); vtkTypeRevisionMacro(vtkKWOptionDataBase, vtkKWObject); void PrintSelf(ostream& os, vtkIndent indent); void DeepCopy(vtkKWOptionDataBase *p); // Description: // Add a new entry in the database. // Return the unique Id of the entry virtual int AddEntry( const char *pattern, const char *command, const char *value); virtual int AddEntryAsInt( const char *pattern, const char *command, int value); virtual int AddEntryAsInt3( const char *pattern, const char *command, int v0, int v1, int v2); virtual int AddEntryAsInt3( const char *pattern, const char *command, int value3[3]); virtual int AddEntryAsDouble( const char *pattern, const char *command, double value); virtual int AddEntryAsDouble3( const char *pattern, const char *command, double v0, double v1, double v2); virtual int AddEntryAsDouble3( const char *pattern, const char *command, double value3[3]); // Description: // Remove all entries. virtual void RemoveAllEntries(); // Description: // Get number of entries. virtual int GetNumberOfEntries(); // Description: // Configure a widget according to the options in the database. // Return the Id of the entry if found, -1 otherwise virtual void ConfigureWidget(vtkKWWidget *obj); // Description: // Convenience method to set all the known background color options to a // specific color. virtual void AddBackgroundColorOptions(double r, double g, double b); virtual void AddBackgroundColorOptions(double rgb[3]) { this->AddBackgroundColorOptions(rgb[0], rgb[1], rgb[2]); }; // Description: // Convenience method to set all the known font options to a // specific font. virtual void AddFontOptions(const char *font); protected: vtkKWOptionDataBase(); ~vtkKWOptionDataBase(); // PIMPL Encapsulation for STL containers //BTX vtkKWOptionDataBaseInternals *Internals; //ETX private: vtkKWOptionDataBase(const vtkKWOptionDataBase&); // Not implemented void operator=(const vtkKWOptionDataBase&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWApplicationSettingsInterface.cxx0000644000175000017500000006746211075736350024427 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWApplicationSettingsInterface.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWApplicationSettingsInterface.h" #include "vtkKWApplication.h" #include "vtkKWBalloonHelpManager.h" #include "vtkKWCheckButton.h" #include "vtkKWFrame.h" #include "vtkKWFrameWithLabel.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWMenu.h" #include "vtkKWMenuButton.h" #include "vtkKWMenuButtonWithLabel.h" #include "vtkKWMessageDialog.h" #include "vtkKWPushButton.h" #include "vtkKWToolbar.h" #include "vtkKWToolbarSet.h" #include "vtkKWUserInterfaceManagerNotebook.h" #include "vtkKWWindow.h" #include "vtkObjectFactory.h" #include //---------------------------------------------------------------------------- #define VTK_KW_APPLICATION_SETTINGS_DPI_FORMAT "%.1lf" //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWApplicationSettingsInterface); vtkCxxRevisionMacro(vtkKWApplicationSettingsInterface, "$Revision: 1.63 $"); //---------------------------------------------------------------------------- vtkKWApplicationSettingsInterface::vtkKWApplicationSettingsInterface() { this->SetName( ks_("Application Settings Panel|Title|Application Settings")); this->Window = NULL; // Interface settings this->InterfaceSettingsFrame = NULL; this->PromptBeforeExitCheckButton = NULL; this->SendErrorLogBeforeExitCheckButton = NULL; this->SaveUserInterfaceGeometryCheckButton = NULL; this->SplashScreenVisibilityCheckButton = NULL; this->BalloonHelpVisibilityCheckButton = NULL; this->ViewPanelPositionOptionMenu = NULL; // Interface customization this->InterfaceCustomizationFrame = NULL; this->ResetDragAndDropButton = NULL; // Toolbar settings this->ToolbarSettingsFrame = NULL; this->FlatToolbarsCheckButton = NULL; this->FlatToolbarWidgetsCheckButton = NULL; // Print settings this->PrintSettingsFrame = NULL; this->DPIOptionMenu = NULL; } //---------------------------------------------------------------------------- vtkKWApplicationSettingsInterface::~vtkKWApplicationSettingsInterface() { this->SetWindow(NULL); // Interface settings if (this->InterfaceSettingsFrame) { this->InterfaceSettingsFrame->Delete(); this->InterfaceSettingsFrame = NULL; } if (this->PromptBeforeExitCheckButton) { this->PromptBeforeExitCheckButton->Delete(); this->PromptBeforeExitCheckButton = NULL; } if (this->SendErrorLogBeforeExitCheckButton) { this->SendErrorLogBeforeExitCheckButton->Delete(); this->SendErrorLogBeforeExitCheckButton = NULL; } if (this->SaveUserInterfaceGeometryCheckButton) { this->SaveUserInterfaceGeometryCheckButton->Delete(); this->SaveUserInterfaceGeometryCheckButton = NULL; } if (this->SplashScreenVisibilityCheckButton) { this->SplashScreenVisibilityCheckButton->Delete(); this->SplashScreenVisibilityCheckButton = NULL; } if (this->BalloonHelpVisibilityCheckButton) { this->BalloonHelpVisibilityCheckButton->Delete(); this->BalloonHelpVisibilityCheckButton = NULL; } if (this->ViewPanelPositionOptionMenu) { this->ViewPanelPositionOptionMenu->Delete(); this->ViewPanelPositionOptionMenu = NULL; } // Interface customization if (this->InterfaceCustomizationFrame) { this->InterfaceCustomizationFrame->Delete(); this->InterfaceCustomizationFrame = NULL; } if (this->ResetDragAndDropButton) { this->ResetDragAndDropButton->Delete(); this->ResetDragAndDropButton = NULL; } // Toolbar settings if (this->ToolbarSettingsFrame) { this->ToolbarSettingsFrame->Delete(); this->ToolbarSettingsFrame = NULL; } if (this->FlatToolbarsCheckButton) { this->FlatToolbarsCheckButton->Delete(); this->FlatToolbarsCheckButton = NULL; } if (this->FlatToolbarWidgetsCheckButton) { this->FlatToolbarWidgetsCheckButton->Delete(); this->FlatToolbarWidgetsCheckButton = NULL; } // Print settings if (this->PrintSettingsFrame) { this->PrintSettingsFrame->Delete(); this->PrintSettingsFrame = NULL; } if (this->DPIOptionMenu) { this->DPIOptionMenu->Delete(); this->DPIOptionMenu = NULL; } } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::SetWindow(vtkKWWindow *arg) { if (this->Window == arg) { return; } this->Window = arg; this->Modified(); this->Update(); } // --------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::Create() { if (this->IsCreated()) { vtkErrorMacro("The panel is already created."); return; } // Create the superclass instance (and set the application) this->Superclass::Create(); vtksys_ios::ostringstream tk_cmd; vtkKWWidget *page; vtkKWFrame *frame; vtkKWMenu *menu; // -------------------------------------------------------------- // Add a "Preferences" page this->AddPage(this->GetName()); page = this->GetPageWidget(this->GetName()); // -------------------------------------------------------------- // Interface settings : main frame if (!this->InterfaceSettingsFrame) { this->InterfaceSettingsFrame = vtkKWFrameWithLabel::New(); } this->InterfaceSettingsFrame->SetParent(this->GetPagesParentWidget()); this->InterfaceSettingsFrame->Create(); this->InterfaceSettingsFrame->SetLabelText( ks_("Application Settings|Interface Settings")); tk_cmd << "pack " << this->InterfaceSettingsFrame->GetWidgetName() << " -side top -anchor nw -fill x -padx 2 -pady 2 " << " -in " << page->GetWidgetName() << endl; frame = this->InterfaceSettingsFrame->GetFrame(); // -------------------------------------------------------------- // Interface settings : Prompt before exit ? if (!this->PromptBeforeExitCheckButton) { this->PromptBeforeExitCheckButton = vtkKWCheckButton::New(); } this->PromptBeforeExitCheckButton->SetParent(frame); this->PromptBeforeExitCheckButton->Create(); this->PromptBeforeExitCheckButton->SetText( ks_("Application Settings|Confirm on exit")); this->PromptBeforeExitCheckButton->SetCommand(this, "PromptBeforeExitCallback"); this->PromptBeforeExitCheckButton->SetBalloonHelpString( k_("A confirmation dialog will be presented to the user on exit.")); tk_cmd << "pack " << this->PromptBeforeExitCheckButton->GetWidgetName() << " -side top -anchor w -expand no -fill none" << endl; // -------------------------------------------------------------- // Interface settings : Send error log on exit ? if (!this->SendErrorLogBeforeExitCheckButton) { this->SendErrorLogBeforeExitCheckButton = vtkKWCheckButton::New(); } this->SendErrorLogBeforeExitCheckButton->SetParent(frame); this->SendErrorLogBeforeExitCheckButton->Create(); this->SendErrorLogBeforeExitCheckButton->SetText( ks_("Application Settings|Confirm send error log on exit")); this->SendErrorLogBeforeExitCheckButton->SetCommand( this, "SendErrorLogBeforeExitCallback"); this->SendErrorLogBeforeExitCheckButton->SetBalloonHelpString( k_("A confirmation dialog will prompt the user to send the error log " "on exit.")); tk_cmd << "pack " << this->SendErrorLogBeforeExitCheckButton->GetWidgetName() << " -side top -anchor w -expand no -fill none" << endl; // -------------------------------------------------------------- // Interface settings : Save application geometry on exit ? if (!this->SaveUserInterfaceGeometryCheckButton) { this->SaveUserInterfaceGeometryCheckButton = vtkKWCheckButton::New(); } this->SaveUserInterfaceGeometryCheckButton->SetParent(frame); this->SaveUserInterfaceGeometryCheckButton->Create(); this->SaveUserInterfaceGeometryCheckButton->SetText( ks_("Application Settings|Save user interface size and position on exit")); this->SaveUserInterfaceGeometryCheckButton->SetCommand( this, "SaveUserInterfaceGeometryCallback"); this->SaveUserInterfaceGeometryCheckButton->SetBalloonHelpString( k_("Save the user interface size and location on exit and restore it " "on startup.")); tk_cmd << "pack " << this->SaveUserInterfaceGeometryCheckButton->GetWidgetName() << " -side top -anchor w -expand no -fill none" << endl; // -------------------------------------------------------------- // Interface settings : Show splash screen ? if (this->GetApplication()->GetSupportSplashScreen()) { if (!this->SplashScreenVisibilityCheckButton) { this->SplashScreenVisibilityCheckButton = vtkKWCheckButton::New(); } this->SplashScreenVisibilityCheckButton->SetParent(frame); this->SplashScreenVisibilityCheckButton->Create(); this->SplashScreenVisibilityCheckButton->SetText( ks_("Application Settings|Show splash screen")); this->SplashScreenVisibilityCheckButton->SetCommand( this, "SplashScreenVisibilityCallback"); this->SplashScreenVisibilityCheckButton->SetBalloonHelpString( k_("Display the splash information screen at startup.")); tk_cmd << "pack " << this->SplashScreenVisibilityCheckButton->GetWidgetName() << " -side top -anchor w -expand no -fill none" << endl; } // -------------------------------------------------------------- // Interface settings : Show balloon help ? if (!this->BalloonHelpVisibilityCheckButton) { this->BalloonHelpVisibilityCheckButton = vtkKWCheckButton::New(); } this->BalloonHelpVisibilityCheckButton->SetParent(frame); this->BalloonHelpVisibilityCheckButton->Create(); this->BalloonHelpVisibilityCheckButton->SetText( ks_("Application Settings|Show balloon help")); this->BalloonHelpVisibilityCheckButton->SetCommand( this, "BalloonHelpVisibilityCallback"); this->BalloonHelpVisibilityCheckButton->SetBalloonHelpString( k_("Display help in a yellow popup-box on the screen when you rest the " "mouse over an item that supports it.")); tk_cmd << "pack " << this->BalloonHelpVisibilityCheckButton->GetWidgetName() << " -side top -anchor w -expand no -fill none" << endl; // -------------------------------------------------------------- // Interface settings : View Panel Position if (!this->ViewPanelPositionOptionMenu) { this->ViewPanelPositionOptionMenu = vtkKWMenuButtonWithLabel::New(); } this->ViewPanelPositionOptionMenu->SetParent(frame); this->ViewPanelPositionOptionMenu->Create(); this->ViewPanelPositionOptionMenu->GetLabel()->SetText( ks_("Application Settings|Position of view panel:")); menu = this->ViewPanelPositionOptionMenu->GetWidget()->GetMenu(); menu->AddRadioButton(ks_("Position|Left"), this, "ViewPanelPositionCallback"); menu->AddRadioButton(ks_("Position|Right"), this, "ViewPanelPositionCallback"); tk_cmd << "pack " << this->ViewPanelPositionOptionMenu->GetWidgetName() << " -side top -anchor w -padx 2 -pady 2" << endl; // -------------------------------------------------------------- // Interface customization : main frame if (!this->InterfaceCustomizationFrame) { this->InterfaceCustomizationFrame = vtkKWFrameWithLabel::New(); } this->InterfaceCustomizationFrame->SetParent(this->GetPagesParentWidget()); this->InterfaceCustomizationFrame->Create(); this->InterfaceCustomizationFrame->SetLabelText( ks_("Application Settings|Drag & Drop Settings")); tk_cmd << "pack " << this->InterfaceCustomizationFrame->GetWidgetName() << " -side top -anchor nw -fill x -padx 2 -pady 2 " << " -in " << page->GetWidgetName() << endl; frame = this->InterfaceCustomizationFrame->GetFrame(); // -------------------------------------------------------------- // Interface customization : Drag & Drop : Reset if (!this->ResetDragAndDropButton) { this->ResetDragAndDropButton = vtkKWPushButton::New(); } this->ResetDragAndDropButton->SetParent(frame); this->ResetDragAndDropButton->Create(); this->ResetDragAndDropButton->SetText( ks_("Application Settings|Reset Interface To Default State")); this->ResetDragAndDropButton->SetCommand(this, "ResetDragAndDropCallback"); this->ResetDragAndDropButton->SetBalloonHelpString( k_("You can drag & drop elements of the " "interface within the same panel or from one panel to the other. " "To do so, drag the title of a labeled frame to reposition it within " "a panel, or drop it on another tab to move it to a different panel. " "Press this button to reset the placement of all user interface " "elements to their default position. You will need to restart the " "application for the interface to be reset.")); tk_cmd << "pack " << this->ResetDragAndDropButton->GetWidgetName() << " -side top -anchor w -expand y -fill x -padx 2 -pady 2" << endl; // -------------------------------------------------------------- // Toolbar settings : main frame if (!this->ToolbarSettingsFrame) { this->ToolbarSettingsFrame = vtkKWFrameWithLabel::New(); } this->ToolbarSettingsFrame->SetParent(this->GetPagesParentWidget()); this->ToolbarSettingsFrame->Create(); this->ToolbarSettingsFrame->SetLabelText( ks_("Application Settings|Toolbar Settings")); tk_cmd << "pack " << this->ToolbarSettingsFrame->GetWidgetName() << " -side top -anchor nw -fill x -padx 2 -pady 2 " << " -in " << page->GetWidgetName() << endl; frame = this->ToolbarSettingsFrame->GetFrame(); // -------------------------------------------------------------- // Toolbar settings : flat frame if (!this->FlatToolbarsCheckButton) { this->FlatToolbarsCheckButton = vtkKWCheckButton::New(); } this->FlatToolbarsCheckButton->SetParent(frame); this->FlatToolbarsCheckButton->Create(); this->FlatToolbarsCheckButton->SetText( ks_("Application Settings|Toolbar Settings|Flat frame")); this->FlatToolbarsCheckButton->SetCommand(this, "FlatToolbarsCallback"); this->FlatToolbarsCheckButton->SetBalloonHelpString( k_("Display the toolbar frames using a flat aspect.")); tk_cmd << "pack " << this->FlatToolbarsCheckButton->GetWidgetName() << " -side top -anchor w -expand no -fill none" << endl; // -------------------------------------------------------------- // Toolbar settings : flat buttons if (!this->FlatToolbarWidgetsCheckButton) { this->FlatToolbarWidgetsCheckButton = vtkKWCheckButton::New(); } this->FlatToolbarWidgetsCheckButton->SetParent(frame); this->FlatToolbarWidgetsCheckButton->Create(); this->FlatToolbarWidgetsCheckButton->SetText( ks_("Application Settings|Toolbar Settings|Flat buttons")); this->FlatToolbarWidgetsCheckButton->SetCommand(this, "FlatToolbarWidgetsCallback"); this->FlatToolbarWidgetsCheckButton->SetBalloonHelpString( k_("Display the toolbar buttons using a flat aspect.")); tk_cmd << "pack " << this->FlatToolbarWidgetsCheckButton->GetWidgetName() << " -side top -anchor w -expand no -fill none" << endl; // -------------------------------------------------------------- // Print settings : main frame if (!this->PrintSettingsFrame) { this->PrintSettingsFrame = vtkKWFrameWithLabel::New(); } this->PrintSettingsFrame->SetParent(this->GetPagesParentWidget()); this->PrintSettingsFrame->Create(); this->PrintSettingsFrame->SetLabelText( ks_("Application Settings|Print Settings")); tk_cmd << "pack " << this->PrintSettingsFrame->GetWidgetName() << " -side top -anchor nw -fill x -padx 2 -pady 2 " << " -in " << page->GetWidgetName() << endl; frame = this->PrintSettingsFrame->GetFrame(); // -------------------------------------------------------------- // Print settings : DPI if (!this->DPIOptionMenu) { this->DPIOptionMenu = vtkKWMenuButtonWithLabel::New(); } this->DPIOptionMenu->SetParent(frame); this->DPIOptionMenu->Create(); this->DPIOptionMenu->GetLabel()->SetText( ks_("Application Settings|Print Settings|DPI:")); double dpis[] = { 100.0, 150.0, 300.0, 600.0 }; for (unsigned int i = 0; i < sizeof(dpis) / sizeof(double); i++) { char label[128], command[128]; sprintf(command, "DPICallback %lf", dpis[i]); sprintf(label, VTK_KW_APPLICATION_SETTINGS_DPI_FORMAT, dpis[i]); this->DPIOptionMenu->GetWidget()->GetMenu()->AddRadioButton( label, this, command); } tk_cmd << "pack " << this->DPIOptionMenu->GetWidgetName() << " -side top -anchor w -padx 2 -pady 2" << endl; // -------------------------------------------------------------- // Pack this->Script(tk_cmd.str().c_str()); // Update this->Update(); } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::Update() { this->Superclass::Update(); if (!this->IsCreated() || !this->Window) { return; } // Interface settings : Prompt before exit ? if (this->PromptBeforeExitCheckButton) { this->PromptBeforeExitCheckButton->SetSelectedState( vtkKWMessageDialog::RestoreMessageDialogResponseFromRegistry( this->GetApplication(), vtkKWApplication::ExitDialogName) ? 0 : 1); } // Interface settings : Prompt before exit ? if (this->SendErrorLogBeforeExitCheckButton) { this->SendErrorLogBeforeExitCheckButton->SetSelectedState( vtkKWMessageDialog::RestoreMessageDialogResponseFromRegistry( this->GetApplication(), vtkKWApplication::SendErrorLogDialogName)?0:1); } // Interface settings : Save application geometry on exit ? if (this->SaveUserInterfaceGeometryCheckButton) { this->SaveUserInterfaceGeometryCheckButton->SetSelectedState( this->GetApplication()->GetSaveUserInterfaceGeometry()); } // Interface settings : Show splash screen ? if (this->SplashScreenVisibilityCheckButton) { this->SplashScreenVisibilityCheckButton->SetSelectedState( this->GetApplication()->GetSplashScreenVisibility()); } // Interface settings : Show balloon help ? if (this->BalloonHelpVisibilityCheckButton) { vtkKWBalloonHelpManager *mgr = this->GetApplication()->GetBalloonHelpManager(); if (mgr) { this->BalloonHelpVisibilityCheckButton->SetSelectedState( mgr->GetVisibility()); } } // Interface settings : View Panel Position if (this->ViewPanelPositionOptionMenu && this->ViewPanelPositionOptionMenu->GetWidget() && this->Window) { if (this->Window->GetViewPanelPosition() == vtkKWWindow::ViewPanelPositionLeft) { this->ViewPanelPositionOptionMenu->GetWidget()->SetValue( ks_("Position|Left")); } else if (this->Window->GetViewPanelPosition() == vtkKWWindow::ViewPanelPositionRight) { this->ViewPanelPositionOptionMenu->GetWidget()->SetValue( ks_("Position|Right")); } } // Interface customization : Drag & Drop : Enable // Instead of disabling, we hide the D&D section alltogether if it's not // supported in order not to confuse the user about this 'missing' feature. vtkKWUserInterfaceManagerNotebook *uim_nb = NULL; if (this->Window->HasMainUserInterfaceManager()) { uim_nb = vtkKWUserInterfaceManagerNotebook::SafeDownCast( this->Window->GetMainUserInterfaceManager()); } if (this->InterfaceCustomizationFrame) { if (!uim_nb || !uim_nb->GetEnableDragAndDrop()) { this->Script( "pack forget %s", this->InterfaceCustomizationFrame->GetWidgetName()); if (this->ResetDragAndDropButton) { this->ResetDragAndDropButton->SetEnabled(0); } } else { this->Script( "pack %s -side top -anchor nw -fill x -padx 2 -pady 2 -in %s ", this->InterfaceCustomizationFrame->GetWidgetName(), this->GetPageWidget(this->GetName())->GetWidgetName()); } } // Toolbar settings : flat frame if (this->FlatToolbarsCheckButton) { switch (vtkKWToolbar::GetGlobalToolbarAspect()) { case vtkKWToolbar::ToolbarAspectFlat: this->FlatToolbarsCheckButton->SetSelectedState(1); break; case vtkKWToolbar::ToolbarAspectRelief: this->FlatToolbarsCheckButton->SetSelectedState(0); break; } this->FlatToolbarsCheckButton->SetEnabled( (vtkKWToolbar::GetGlobalToolbarAspect() == vtkKWToolbar::ToolbarAspectUnChanged) ? 0 : this->GetEnabled()); } // Toolbar settings : flat buttons if (this->FlatToolbarWidgetsCheckButton) { switch (vtkKWToolbar::GetGlobalWidgetsAspect()) { case vtkKWToolbar::WidgetsAspectFlat: this->FlatToolbarWidgetsCheckButton->SetSelectedState(1); break; case vtkKWToolbar::WidgetsAspectRelief: this->FlatToolbarWidgetsCheckButton->SetSelectedState(0); break; } this->FlatToolbarWidgetsCheckButton->SetEnabled( (vtkKWToolbar::GetGlobalWidgetsAspect() == vtkKWToolbar::WidgetsAspectUnChanged) ? 0 : this->GetEnabled()); } // Print settings if (this->DPIOptionMenu && this->DPIOptionMenu->GetWidget() && this->Window) { char buffer[128]; sprintf(buffer, VTK_KW_APPLICATION_SETTINGS_DPI_FORMAT, this->GetApplication()->GetPrintTargetDPI()); this->DPIOptionMenu->GetWidget()->SetValue(buffer); } } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::PromptBeforeExitCallback(int state) { vtkKWMessageDialog::SaveMessageDialogResponseToRegistry( this->GetApplication(), vtkKWApplication::ExitDialogName, state ? 0 : 1); } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::SendErrorLogBeforeExitCallback( int state) { vtkKWMessageDialog::SaveMessageDialogResponseToRegistry( this->GetApplication(), vtkKWApplication::SendErrorLogDialogName, state ? 0 : -1); } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::SaveUserInterfaceGeometryCallback( int state) { this->GetApplication()->SetSaveUserInterfaceGeometry(state ? 1 : 0); } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::SplashScreenVisibilityCallback( int state) { this->GetApplication()->SetSplashScreenVisibility(state ? 1 : 0); } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::BalloonHelpVisibilityCallback( int state) { vtkKWBalloonHelpManager *mgr = this->GetApplication()->GetBalloonHelpManager(); if (mgr) { mgr->SetVisibility(state ? 1 : 0); } } //--------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::ViewPanelPositionCallback() { if (this->ViewPanelPositionOptionMenu && this->ViewPanelPositionOptionMenu->GetWidget() && this->Window) { const char *pos = this->ViewPanelPositionOptionMenu->GetWidget()->GetValue(); if (pos) { if (!strcmp(pos, ks_("Position|Left"))) { this->Window->SetViewPanelPositionToLeft(); } else if (!strcmp(pos, ks_("Position|Right"))) { this->Window->SetViewPanelPositionToRight(); } } } } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::ResetDragAndDropCallback() { if (!this->Window || !this->IsCreated()) { return; } vtkKWMessageDialog::PopupMessage( this->GetApplication(), this->Window, ks_("Application Settings|Reset Interface"), k_("All Drag & Drop events performed so far will be discarded. " "Note that the interface will be reset the next time you " "start this application."), vtkKWMessageDialog::WarningIcon); if (this->Window->HasMainUserInterfaceManager()) { vtkKWUserInterfaceManagerNotebook *uim_nb = vtkKWUserInterfaceManagerNotebook::SafeDownCast( this->Window->GetMainUserInterfaceManager()); if (uim_nb) { uim_nb->DeleteAllDragAndDropEntries(); } } } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::FlatToolbarsCallback(int state) { vtkKWToolbar::SetGlobalToolbarAspect( state ? vtkKWToolbar::ToolbarAspectFlat : vtkKWToolbar::ToolbarAspectRelief); if (this->Window) { this->Window->UpdateToolbarState(); } } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::FlatToolbarWidgetsCallback(int state) { vtkKWToolbar::SetGlobalWidgetsAspect( state ? vtkKWToolbar::WidgetsAspectFlat : vtkKWToolbar::WidgetsAspectRelief); if (this->Window) { this->Window->UpdateToolbarState(); } } //--------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::DPICallback(double dpi) { if (this->GetApplication()) { this->GetApplication()->SetPrintTargetDPI(dpi); } } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::UpdateEnableState() { this->Superclass::UpdateEnableState(); // Interface settings if (this->InterfaceSettingsFrame) { this->InterfaceSettingsFrame->SetEnabled(this->GetEnabled()); } if (this->PromptBeforeExitCheckButton) { this->PromptBeforeExitCheckButton->SetEnabled(this->GetEnabled()); } if (this->SendErrorLogBeforeExitCheckButton) { this->SendErrorLogBeforeExitCheckButton->SetEnabled(this->GetEnabled()); } if (this->SaveUserInterfaceGeometryCheckButton) { this->SaveUserInterfaceGeometryCheckButton->SetEnabled(this->GetEnabled()); } if (this->SplashScreenVisibilityCheckButton) { this->SplashScreenVisibilityCheckButton->SetEnabled(this->GetEnabled()); } if (this->BalloonHelpVisibilityCheckButton) { this->BalloonHelpVisibilityCheckButton->SetEnabled(this->GetEnabled()); } if (this->ViewPanelPositionOptionMenu) { this->ViewPanelPositionOptionMenu->SetEnabled(this->GetEnabled()); } // Interface customization if (this->InterfaceCustomizationFrame) { this->InterfaceCustomizationFrame->SetEnabled(this->GetEnabled()); } if (this->ResetDragAndDropButton) { this->ResetDragAndDropButton->SetEnabled(this->GetEnabled()); } // Toolbar settings if (this->ToolbarSettingsFrame) { this->ToolbarSettingsFrame->SetEnabled(this->GetEnabled()); } if (this->FlatToolbarsCheckButton) { this->FlatToolbarsCheckButton->SetEnabled(this->GetEnabled()); } if (this->FlatToolbarWidgetsCheckButton) { this->FlatToolbarWidgetsCheckButton->SetEnabled(this->GetEnabled()); } // Print settings if (this->PrintSettingsFrame) { this->PrintSettingsFrame->SetEnabled(this->GetEnabled()); } if (this->DPIOptionMenu) { this->DPIOptionMenu->SetEnabled(this->GetEnabled()); } } //---------------------------------------------------------------------------- void vtkKWApplicationSettingsInterface::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Window: " << this->Window << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWTclInteractor.h0000644000175000017500000000643610537613527021020 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTclInteractor.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWTclInteractor - a KW version of interactor.tcl // .SECTION Description // A widget to interactively execute Tcl commands #ifndef __vtkKWTclInteractor_h #define __vtkKWTclInteractor_h #include "vtkKWTopLevel.h" class vtkKWFrame; class vtkKWPushButton; class vtkKWEntry; class vtkKWLabel; class vtkKWTextWithScrollbars; class KWWidgets_EXPORT vtkKWTclInteractor : public vtkKWTopLevel { public: static vtkKWTclInteractor* New(); vtkTypeRevisionMacro(vtkKWTclInteractor, vtkKWTopLevel); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Append text to the display window. Can be used for sending // debugging information to the command prompt when no standard // output is available. virtual void AppendText(const char* text); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Specifies the font to use when drawing text inside the widget. // You can use predefined font names (e.g. 'system'), or you can specify // a set of font attributes with a platform-independent name, for example, // 'times 12 bold'. In this example, the font is specified with a three // element list: the first element is the font family, the second is the // size, the third is a list of style parameters (normal, bold, roman, // italic, underline, overstrike). Example: 'times 12 {bold italic}'. // The Times, Courier and Helvetica font families are guaranteed to exist // and will be matched to the corresponding (closest) font on your system. // If you are familiar with the X font names specification, you can also // describe the font that way (say, '*times-medium-r-*-*-12*'). virtual void SetFont(const char *font); virtual const char* GetFont(); // Description: // Callbacks. Internal, do not use. virtual void EvaluateCallback(); virtual void DownCallback(); virtual void UpCallback(); protected: vtkKWTclInteractor(); ~vtkKWTclInteractor(); // Description: // Create the widget. virtual void CreateWidget(); vtkKWFrame *ButtonFrame; vtkKWPushButton *DismissButton; vtkKWFrame *CommandFrame; vtkKWLabel *CommandLabel; vtkKWEntry *CommandEntry; vtkKWTextWithScrollbars *DisplayText; int TagNumber; int CommandIndex; private: vtkKWTclInteractor(const vtkKWTclInteractor&); // Not implemented void operator=(const vtkKWTclInteractor&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWCompositeWidget.h0000644000175000017500000000344310424463536021342 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWCompositeWidget.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWCompositeWidget - a composite widget. // .SECTION Description // A superclass for all composite widgets, i.e. widgets made of // an assembly of sub-widgets. // This superclass provides the container for the sub-widgets. // Right now, it can be safely assumed to be a frame (similar to a // vtkKWFrame). // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. #ifndef __vtkKWCompositeWidget_h #define __vtkKWCompositeWidget_h #include "vtkKWFrame.h" class KWWidgets_EXPORT vtkKWCompositeWidget : public vtkKWFrame { public: static vtkKWCompositeWidget* New(); vtkTypeRevisionMacro(vtkKWCompositeWidget, vtkKWFrame); void PrintSelf(ostream& os, vtkIndent indent); protected: vtkKWCompositeWidget() {}; ~vtkKWCompositeWidget() {}; // Description: // Create the widget. virtual void CreateWidget(); private: vtkKWCompositeWidget(const vtkKWCompositeWidget&); // Not implemented void operator=(const vtkKWCompositeWidget&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWSpinBox.h0000644000175000017500000003052210753100764017610 0ustar domibeldomibel/*========================================================================= Module: vtkKWSpinBox.h,v Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWSpinBox - SpinBox // .SECTION Description // A widget with up and down arrow controls and direct text editing. // Typically used with integer fields that users increment by 1 (or // decrement) by clicking on the arrows. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. #ifndef __vtkKWSpinBox_h #define __vtkKWSpinBox_h #include "vtkKWCoreWidget.h" class vtkKWMenu; class KWWidgets_EXPORT vtkKWSpinBox : public vtkKWCoreWidget { public: static vtkKWSpinBox* New(); vtkTypeRevisionMacro(vtkKWSpinBox,vtkKWCoreWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set the range. Default to [0, 10] virtual void SetRange(double from, double to); // Description: // Set the increment value. Default to 1. virtual void SetIncrement(double increment); virtual double GetIncrement(); // Description: // Set/Get the current value. virtual void SetValue(double value); virtual double GetValue(); // Description: // Set/Get the string used to format the value. // Specifies an alternate format to use when setting the string value when // using the range. This must be a format specifier of the // form %.f, as it will format a floating-point number. virtual void SetValueFormat(const char *format); virtual const char* GetValueFormat(); // Description: // Set/Get the wrap. If on, values at edges of range wrap around to the // other side of the range when clicking on the up/down arrows. virtual void SetWrap(int wrap); virtual int GetWrap(); vtkBooleanMacro(Wrap, int); // Description: // Restrict the value to a given type (integer, double, or no restriction). // Note: checks against RestrictValue are performed before ValidationCommand. //BTX enum { RestrictNone = 0, RestrictInteger, RestrictDouble }; //ETX vtkGetMacro(RestrictValue, int); virtual void SetRestrictValue(int); virtual void SetRestrictValueToInteger(); virtual void SetRestrictValueToDouble(); virtual void SetRestrictValueToNone(); // Description: // Specifies a command to associate with this step. This command can // be used to validate the contents of the widget. // Note: checks against RestrictValue are performed before ValidationCommand. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // This command should return 1 if the contents is valid, 0 otherwise. // The following parameters are also passed to the command: // - current value: const char* virtual void SetValidationCommand(vtkObject *object, const char *method); virtual int InvokeValidationCommand(const char *value); // Description: // Set/Get the width of the spinbox in number of characters. virtual void SetWidth(int); virtual int GetWidth(); // Description: // Set/Get the background color of the widget. virtual void GetBackgroundColor(double *r, double *g, double *b); virtual double* GetBackgroundColor(); virtual void SetBackgroundColor(double r, double g, double b); virtual void SetBackgroundColor(double rgb[3]) { this->SetBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget. virtual void GetForegroundColor(double *r, double *g, double *b); virtual double* GetForegroundColor(); virtual void SetForegroundColor(double r, double g, double b); virtual void SetForegroundColor(double rgb[3]) { this->SetForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the background color of the widget when it is disabled. virtual void GetDisabledBackgroundColor(double *r, double *g, double *b); virtual double* GetDisabledBackgroundColor(); virtual void SetDisabledBackgroundColor(double r, double g, double b); virtual void SetDisabledBackgroundColor(double rgb[3]) { this->SetDisabledBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget when it is disabled. virtual void GetDisabledForegroundColor(double *r, double *g, double *b); virtual double* GetDisabledForegroundColor(); virtual void SetDisabledForegroundColor(double r, double g, double b); virtual void SetDisabledForegroundColor(double rgb[3]) { this->SetDisabledForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the background color of the widget when it is read-only. virtual void GetReadOnlyBackgroundColor(double *r, double *g, double *b); virtual double* GetReadOnlyBackgroundColor(); virtual void SetReadOnlyBackgroundColor(double r, double g, double b); virtual void SetReadOnlyBackgroundColor(double rgb[3]) { this->SetReadOnlyBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the background color of the spin-buttons. virtual void GetButtonBackgroundColor(double *r, double *g, double *b); virtual double* GetButtonBackgroundColor(); virtual void SetButtonBackgroundColor(double r, double g, double b); virtual void SetButtonBackgroundColor(double rgb[3]) { this->SetButtonBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the highlight thickness, a non-negative value indicating the // width of the highlight rectangle to draw around the outside of the // widget when it has the input focus. virtual void SetHighlightThickness(int); virtual int GetHighlightThickness(); // Description: // Set/Get the active background color of the widget. An element // (a widget or portion of a widget) is active if the mouse cursor is // positioned over the element and pressing a mouse button will cause some // action to occur. virtual void GetActiveBackgroundColor(double *r, double *g, double *b); virtual double* GetActiveBackgroundColor(); virtual void SetActiveBackgroundColor(double r, double g, double b); virtual void SetActiveBackgroundColor(double rgb[3]) { this->SetActiveBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the border width, a non-negative value indicating the width of // the 3-D border to draw around the outside of the widget (if such a border // is being drawn; the Relief option typically determines this). virtual void SetBorderWidth(int); virtual int GetBorderWidth(); // Description: // Set/Get the 3-D effect desired for the widget. // The value indicates how the interior of the widget should appear // relative to its exterior. // Valid constants can be found in vtkKWOptions::ReliefType. virtual void SetRelief(int); virtual int GetRelief(); virtual void SetReliefToRaised(); virtual void SetReliefToSunken(); virtual void SetReliefToFlat(); virtual void SetReliefToRidge(); virtual void SetReliefToSolid(); virtual void SetReliefToGroove(); // Description: // Specifies the font to use when drawing text inside the widget. // You can use predefined font names (e.g. 'system'), or you can specify // a set of font attributes with a platform-independent name, for example, // 'times 12 bold'. In this example, the font is specified with a three // element list: the first element is the font family, the second is the // size, the third is a list of style parameters (normal, bold, roman, // italic, underline, overstrike). Example: 'times 12 {bold italic}'. // The Times, Courier and Helvetica font families are guaranteed to exist // and will be matched to the corresponding (closest) font on your system. // If you are familiar with the X font names specification, you can also // describe the font that way (say, '*times-medium-r-*-*-12*'). virtual void SetFont(const char *font); virtual const char* GetFont(); // Description: // Specifies whether or not a selection in the widget should also be the X // selection. If the selection is exported, then selecting in the widget // deselects the current X selection, selecting outside the widget deselects // any widget selection, and the widget will respond to selection retrieval // requests when it has a selection. virtual void SetExportSelection(int); virtual int GetExportSelection(); vtkBooleanMacro(ExportSelection, int); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the return key is pressed, or the focus is lost, // as specified by the CommandTrigger variable. It is also invoked when // the spinbuttons are pressed. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the current value: int (if Increment is integer); double otherwise // Note: the 'int' signature is for convenience, so that the command can // be set to a callback accepting 'int'. In doubt, implement the callback // using a 'double' signature that will accept both 'int' and 'double'. virtual void SetCommand(vtkObject *object, const char *method); virtual void InvokeCommand(double value); // Description: // Specify when Command should be invoked. Default to losing focus and // return key. //BTX enum { TriggerOnFocusOut = 1, TriggerOnReturnKey = 2, TriggerOnAnyChange = 4 }; //ETX vtkGetMacro(CommandTrigger, int); virtual void SetCommandTrigger(int); virtual void SetCommandTriggerToReturnKeyAndFocusOut(); virtual void SetCommandTriggerToAnyChange(); // Description: // Events. The SpinBoxValueChangedEvent is triggered when the widget value // is changed. It is similar in concept to the 'Command' callback but can be // used by multiple listeners/observers at a time. // Important: since there is no way to robustly find out when the user // is done inputing characters in the text entry part of the spinbox, the // SpinBoxValueChangedEvent event is also generated when is pressed, // or the spinbox widget is losing focus (i.e. the user clicked outside the // text field). // The following parameters are also passed as client data: // - the current value: double //BTX enum { SpinBoxValueChangedEvent = 10000 }; //ETX // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void ValueCallback(); virtual int ValidationCallback(const char *value); virtual void TracedVariableChangedCallback( const char *, const char *, const char *); virtual void RightClickCallback(int x, int y); protected: vtkKWSpinBox(); ~vtkKWSpinBox(); // Description: // Create the widget. virtual void CreateWidget(); int RestrictValue; int CommandTrigger; char *Command; char *ValidationCommand; vtkKWMenu *ContextMenu; // Description: // Populate the context menu virtual void PopulateContextMenu(vtkKWMenu*); // Description: // Configure. virtual void Configure(); virtual void ConfigureValidation(); private: vtkKWSpinBox(const vtkKWSpinBox&); // Not implemented void operator=(const vtkKWSpinBox&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWKeyBindingsWidget.cxx0000644000175000017500000003063611207520705022155 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWKeyBindingsWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWKeyBindingsWidget.h" #ifdef _MSC_VER // Let us get rid of "decorated name length exceeded, name was truncated" // http://msdn.microsoft.com/en-us/library/074af4b6(VS.80).aspx // VS6 support might get discontinued anyway... #pragma warning( disable : 4503 ) #endif #include "vtkKWApplication.h" #include "vtkKWFrameWithLabel.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" #include "vtkKWMultiColumnList.h" #include "vtkKWMultiColumnListWithScrollbars.h" #include "vtkKWLoadSaveButton.h" #include "vtkKWLoadSaveDialog.h" #include "vtkKWPushButton.h" #include "vtkKWText.h" #include "vtkKWTextWithScrollbars.h" #include "vtkKWTkUtilities.h" #include "vtkKWToolbar.h" #include "vtkKWKeyBindingsManager.h" #include "vtkObjectFactory.h" #include #include #include #include #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWKeyBindingsWidget ); vtkCxxRevisionMacro(vtkKWKeyBindingsWidget, "$Revision: 1.2 $"); //---------------------------------------------------------------------------- class vtkKWKeyBindingsWidgetInternals { public: }; //---------------------------------------------------------------------------- vtkKWKeyBindingsWidget::vtkKWKeyBindingsWidget() { this->Internals = new vtkKWKeyBindingsWidgetInternals; this->Toolbar = NULL; this->KeyBindingsList = NULL; this->SaveButton = NULL; this->DetailFrame = NULL; this->DetailText = NULL; this->KeyBindingsManager = NULL; } //---------------------------------------------------------------------------- vtkKWKeyBindingsWidget::~vtkKWKeyBindingsWidget() { if (this->KeyBindingsManager ) { this->SetKeyBindingsManager(NULL); } if (this->Internals) { delete this->Internals; } if (this->KeyBindingsList) { this->KeyBindingsList->Delete(); } if (this->SaveButton) { this->SaveButton->Delete(); } if (this->DetailFrame) { this->DetailFrame->Delete(); } if (this->DetailText) { this->DetailText->Delete(); } if (this->Toolbar) { this->Toolbar->Delete(); } } //---------------------------------------------------------------------------- void vtkKWKeyBindingsWidget::SetKeyBindingsManager(vtkKWKeyBindingsManager *arg) { if (this->KeyBindingsManager == arg) { return; } if (this->KeyBindingsManager) { this->KeyBindingsManager->UnRegister(this); } this->KeyBindingsManager = arg; if (this->KeyBindingsManager) { this->KeyBindingsManager->Register(this); } this->Update(); this->Modified(); } //---------------------------------------------------------------------------- void vtkKWKeyBindingsWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Setup toolbar if (!this->Toolbar) { this->Toolbar = vtkKWToolbar::New(); } this->Toolbar->SetParent(this); this->Toolbar->Create(); this->Toolbar->SetToolbarAspectToFlat(); this->Toolbar->SetWidgetsAspectToFlat(); this->Script("pack %s -side top -anchor nw -padx 0 -pady 0", this->Toolbar->GetWidgetName()); // Save Button if (!this->SaveButton) { this->SaveButton = vtkKWLoadSaveButton::New(); } this->SaveButton->SetParent(this->Toolbar->GetFrame()); this->SaveButton->Create(); this->SaveButton->SetImageToPredefinedIcon( vtkKWIcon::IconNuvola16x16ActionsFileSave); this->SaveButton->SetBalloonHelpString( "Write shortcuts to a tab-delimited text file"); this->SaveButton->SetCommand(this, "WriteKeyBindingsToFileCallback"); this->SaveButton->GetLoadSaveDialog()->SaveDialogOn(); this->SaveButton->GetLoadSaveDialog()->SetDefaultExtension(".txt"); this->SaveButton->GetLoadSaveDialog()->SetFileTypes("{ {Text} {*.txt} }"); this->SaveButton->GetLoadSaveDialog()->RetrieveLastPathFromRegistry( "OpenPath"); this->Toolbar->AddWidget(this->SaveButton); // Setup multicolumn list if (!this->KeyBindingsList) { this->KeyBindingsList = vtkKWMultiColumnListWithScrollbars::New(); } this->KeyBindingsList->SetParent(this); this->KeyBindingsList->Create(); vtkKWMultiColumnList *tablelist = this->KeyBindingsList->GetWidget(); tablelist->MovableColumnsOn(); tablelist->SetWidth(0); tablelist->SetHeight(21); tablelist->ExportSelectionOff(); tablelist->SetColumnSeparatorsVisibility(0); tablelist->SetStripeHeight(0); tablelist->ColorSortedColumnOn(); tablelist->ClearStripeBackgroundColor(); tablelist->SetRowSpacing(0); tablelist->SetSelectionModeToSingle(); tablelist->SetSelectionChangedCommand(this, "SelectionChangedCallback"); int col_index; col_index = tablelist->AddColumn("Key"); col_index = tablelist->AddColumn("Context"); col_index = tablelist->AddColumn("Description"); for (int i = 0; i < tablelist->GetNumberOfColumns(); i++) { tablelist->SetColumnEditable(i, 0); } this->Script( "pack %s -side top -fill both -expand true -padx 0 -pady 2", this->KeyBindingsList->GetWidgetName()); // Description Text Frame if (!this->DetailFrame) { this->DetailFrame = vtkKWFrameWithLabel::New(); } this->DetailFrame->SetParent(this); this->DetailFrame->Create(); this->DetailFrame->SetLabelText("Selected key binding Description"); #if 0 this->Script("pack %s -side top -anchor nw -fill x -padx 0 -pady 0", this->DetailFrame->GetWidgetName()); #endif // Description Text Box if (!this->DetailText) { this->DetailText = vtkKWTextWithScrollbars::New(); } this->DetailText->SetParent(this->DetailFrame->GetFrame()); this->DetailText->Create(); this->DetailText->GetWidget()->SetHeight(8); this->DetailText->GetWidget()->SetReadOnly(1); // Not used yet this->Script("pack %s -side top -fill both -expand true", this->DetailText->GetWidgetName()); this->Update(); } //---------------------------------------------------------------------------- void vtkKWKeyBindingsWidget::Update() { if (!this->IsCreated()) { return; } this->UpdateEnableState(); if (!this->KeyBindingsList || !this->KeyBindingsManager) { return; } vtkKWMultiColumnList *tablelist = this->KeyBindingsList->GetWidget(); tablelist->DeleteAllRows(); typedef vtksys_stl::map StringToStringContainer; typedef vtksys_stl::map::iterator StringToStringIterator ; typedef vtksys_stl::map StringToStringToStringContainer; typedef vtksys_stl::map::iterator StringToStringToStringIterator; StringToStringToStringContainer keybindings; // Iterate over all key bindings and store unique ones int nb_targets = this->KeyBindingsManager->GetNumberOfTargets(); int t; for (t = 0; t < nb_targets; ++t) { vtkObject *target = this->KeyBindingsManager->GetNthTarget(t); int nb_bindings = this->KeyBindingsManager->GetNumberOfBindings(target); int b; for (b = 0; b < nb_bindings; ++b) { const char *binding = this->KeyBindingsManager->GetNthBinding(target, b); int nb_callback_objects = this->KeyBindingsManager->GetNumberOfCallbackObjects(target, binding); int o; for (o = 0; o < nb_callback_objects; ++o) { vtkObject *callback_object = this->KeyBindingsManager->GetNthCallbackObject(target, binding, o); int nb_key_bindings = this->KeyBindingsManager->GetNumberOfKeyBindings( target, binding, callback_object); int k; for (k = 0; k < nb_key_bindings; ++k) { const char *context = this->KeyBindingsManager->GetNthContext( target, binding, callback_object, k); const char *desc = this->KeyBindingsManager->GetNthDescription( target, binding, callback_object, k); // Store unique key bindings keybindings[context][binding] = desc; } } } } // Iterate over unique context/binding/description bindings // and populate the list int row = 0; StringToStringToStringIterator it = keybindings.begin(); StringToStringToStringIterator end = keybindings.end(); for (;it != end; ++it) { StringToStringIterator it2 = (it->second).begin(); StringToStringIterator end2 = (it->second).end(); for (;it2 != end2; ++it2) { const char *binding = this->KeyBindingsManager->GetPrettyBinding((it2->first).c_str()); const char *context = this->KeyBindingsManager->GetPrettyContext((it->first).c_str()); const char *desc = (it2->second).c_str(); tablelist->AddRow(); tablelist->SetCellText(row, 0, binding); tablelist->SetCellText(row, 1, context); tablelist->SetCellText(row, 2, desc); ++row; } } } //---------------------------------------------------------------------------- int vtkKWKeyBindingsWidget::WriteKeyBindingsToStream(ostream& os) { if (!this->KeyBindingsList || !this->KeyBindingsList->IsCreated()) { return 0; } // Write all keybindings vtkKWMultiColumnList *keybinding_list = this->KeyBindingsList->GetWidget(); int numrows = keybinding_list->GetNumberOfRows(); for (int i = 0; i < numrows; i++) { const char *tmp = keybinding_list->GetCellText(i, 0); if (tmp) { vtksys_stl::string binding(tmp); tmp = keybinding_list->GetCellText(i, 1); vtksys_stl::string context(tmp ? tmp : ""); tmp = keybinding_list->GetCellText(i, 2); vtksys_stl::string desc(tmp ? tmp : ""); os << binding << '\t' << context << '\t' << desc << endl; } } return 1; } //---------------------------------------------------------------------------- int vtkKWKeyBindingsWidget::WriteKeyBindingsToFile(const char* filename) { // Make sure the user specified a filename if (!filename || !(*filename)) { vtkErrorMacro(<< "Please specify a valid file name!"); return 0; } // Open text file ofstream fout(filename, ios::out | ios::trunc); if (fout.fail()) { vtkWarningMacro(<< "Unable to open file to write: " << filename); return 0; } // Write all keybindings int res = this->WriteKeyBindingsToStream(fout); fout.close(); return res; } //---------------------------------------------------------------------------- void vtkKWKeyBindingsWidget::SelectionChangedCallback() { } //---------------------------------------------------------------------------- void vtkKWKeyBindingsWidget::WriteKeyBindingsToFileCallback() { if (this->SaveButton && this->SaveButton->IsCreated()) { this->SaveButton->SetText(NULL); if (this->SaveButton->GetLoadSaveDialog()->GetStatus() == vtkKWDialog::StatusOK) { this->SaveButton->GetLoadSaveDialog()->SaveLastPathToRegistry( "OpenPath"); this->WriteKeyBindingsToFile(this->SaveButton->GetFileName()); } } } //---------------------------------------------------------------------------- void vtkKWKeyBindingsWidget::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->KeyBindingsList); this->PropagateEnableState(this->Toolbar); this->PropagateEnableState(this->SaveButton); } //---------------------------------------------------------------------------- void vtkKWKeyBindingsWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "KeyBindingsManager: "; if (this->KeyBindingsManager) { os << this->KeyBindingsManager << endl; } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWVolumeMaterialPropertyWidget.h0000644000175000017500000000746710424463540024100 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWVolumeMaterialPropertyWidget.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWVolumeMaterialPropertyWidget - widget to control the material property of a volume (vtkVolumeProperty) // .SECTION Description #ifndef __vtkKWVolumeMaterialPropertyWidget_h #define __vtkKWVolumeMaterialPropertyWidget_h #include "vtkKWMaterialPropertyWidget.h" class vtkKWCheckButtonWithLabel; class vtkKWScalarComponentSelectionWidget; class vtkVolumeProperty; class KWWidgets_EXPORT vtkKWVolumeMaterialPropertyWidget : public vtkKWMaterialPropertyWidget { public: static vtkKWVolumeMaterialPropertyWidget *New(); vtkTypeRevisionMacro(vtkKWVolumeMaterialPropertyWidget, vtkKWMaterialPropertyWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the volume property to edit with this widget virtual void SetVolumeProperty(vtkVolumeProperty *prop); vtkGetObjectMacro(VolumeProperty, vtkVolumeProperty); // Description: // Set/Get the component controlled by the widget virtual void SetSelectedComponent(int); vtkGetMacro(SelectedComponent, int); vtkGetObjectMacro(ComponentSelectionWidget, vtkKWScalarComponentSelectionWidget); // Description: // Set/Get the number of components controlled by the widget virtual void SetNumberOfComponents(int); vtkGetMacro(NumberOfComponents, int); // Description: // Allow enable shading per component virtual void SetAllowEnableShading(int); vtkBooleanMacro(AllowEnableShading, int); vtkGetMacro(AllowEnableShading, int); // Description: // Refresh the interface given the value extracted from the current property. virtual void Update(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void EnableShadingCallback(int state); virtual void SelectedComponentCallback(int); protected: vtkKWVolumeMaterialPropertyWidget(); ~vtkKWVolumeMaterialPropertyWidget(); // Description: // Create the widget. virtual void CreateWidget(); vtkVolumeProperty *VolumeProperty; int SelectedComponent; int NumberOfComponents; int AllowEnableShading; // UI vtkKWScalarComponentSelectionWidget *ComponentSelectionWidget; vtkKWCheckButtonWithLabel *EnableShadingCheckButton; // Description: // Pack virtual void Pack(); // Description: // Update the property from the interface values or a preset // Return 1 if the property was modified, 0 otherwise virtual int UpdatePropertyFromInterface(); virtual int UpdatePropertyFromPreset(const Preset *preset); // Description: // Send an event representing the state of the widget virtual void SendStateEvent(int event); // Description: // Return 1 if the controls should be enabled. virtual int AreControlsEnabled(); private: vtkKWVolumeMaterialPropertyWidget(const vtkKWVolumeMaterialPropertyWidget&); //Not implemented void operator=(const vtkKWVolumeMaterialPropertyWidget&); //Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWTkUtilities.h0000644000175000017500000010173311171455633020506 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTkUtilities.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWTkUtilities - class that supports basic Tk functions // .SECTION Description // vtkKWTkUtilities provides methods to perform common Tk operations. #ifndef __vtkKWTkUtilities_h #define __vtkKWTkUtilities_h #include "vtkObject.h" #include "vtkKWWidgets.h" // Needed for export symbols directives // This has to be here because on HP varargs are included in // tcl.h and they have different prototypes for va_start so // the build fails. Defining HAS_STDARG prevents that. #if defined(__hpux) && !defined(HAS_STDARG) #define HAS_STDARG #endif #include // Needed for "va_list" argument of EstimateFormatLength. class vtkKWWidget; class vtkKWCoreWidget; class vtkKWApplication; class vtkKWIcon; class vtkRenderWindow; struct Tcl_Interp; class KWWidgets_EXPORT vtkKWTkUtilities : public vtkObject { public: static vtkKWTkUtilities* New(); vtkTypeRevisionMacro(vtkKWTkUtilities,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Return the Tcl name of a VTK object static const char* GetTclNameFromPointer( Tcl_Interp *interp, vtkObject *obj); static const char* GetTclNameFromPointer( vtkKWApplication *app, vtkObject *obj); // Description: // Evaluate a Tcl string. The string is passed to printf() first (as format // specifier) along with the remaining arguments. // The second prototype can be used by similar variable arguments method: it // needs to walk through the var_args list twice though. The only // portable way to do this is to pass two copies of the list's start // pointer. // Convenience methods are provided to specify a vtkKWApplication // instead of the Tcl interpreter. // Return a pointer to the Tcl interpreter result buffer. //BTX static const char* EvaluateString( Tcl_Interp *interp, const char *format, ...); static const char* EvaluateString( vtkKWApplication *app, const char *format, ...); //ETX static const char* EvaluateStringFromArgs( Tcl_Interp *interp, const char *format, va_list var_args1, va_list var_args2); static const char* EvaluateStringFromArgs( vtkKWApplication *app, const char *format, va_list var_args1, va_list var_args2); static const char* EvaluateSimpleString( Tcl_Interp *interp, const char *str); static const char* EvaluateSimpleString( vtkKWApplication *app, const char *str); // Description: // Evaluate a Tcl string that was encoded in a buffer using zlib // and/or base64. static const char* EvaluateEncodedString( Tcl_Interp *interp, const unsigned char *buffer, unsigned long length, unsigned long decoded_length); // Description: // Create a Tcl callback command. // The 'command' argument is a pointer to the command to be created. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // Note that 'command' is allocated automatically using the 'new' // operator. If it is not NULL, it is deallocated first using 'delete []'. static void CreateObjectMethodCommand( vtkKWApplication *app, char **command, vtkObject *object, const char *method); static void CreateObjectMethodCommand( Tcl_Interp *interp, char **command, vtkObject *object, const char *method); // Description: // Get the RGB components that correspond to 'color' (say, #223344) // in the widget given by 'widget' (say, .foo.bar). Color may be specified // in any of the forms acceptable for a Tk color option. // A convenience method is provided to query a vtkKWWidget directly. static void GetRGBColor(Tcl_Interp *interp, const char *widget, const char *color, double *r, double *g, double *b); static void GetRGBColor(vtkKWWidget *widget, const char *color, double *r, double *g, double *b); // Description: // Get the RGB components that correspond to the color 'option' // (say -bg, -fg, etc.) of the widget given by 'widget' (say, .foo.bar). // A convenience method is provided to query a vtkKWWidget directly. static void GetOptionColor(Tcl_Interp *interp, const char *widget, const char *option, double *r, double *g, double *b); static void GetOptionColor(vtkKWWidget *widget, const char *option, double *r, double *g, double *b); static double* GetOptionColor(vtkKWWidget *widget, const char *option); // Description: // Get the RGB components that correspond to the default color 'option' // (say the default value for -bg, -fg, etc.) of the widget given by // 'widget' (say, .foo.bar). // A convenience method is provided to query a vtkKWWidget directly. static void GetDefaultOptionColor(Tcl_Interp *interp, const char *widget, const char *option, double *r, double *g, double *b); static void GetDefaultOptionColor(vtkKWWidget *widget, const char *option, double *r, double *g, double *b); static double* GetDefaultOptionColor(vtkKWWidget *widget, const char *option); // Description: // Set the RGB components of the color 'option' // (say -bg, -fg, etc.) of the widget given by 'widget' (say, .foo.bar). // A convenience method is provided to query a vtkKWWidget directly. static void SetOptionColor(Tcl_Interp *interp, const char *widget, const char *option, double r, double g, double b); static void SetOptionColor(vtkKWWidget *widget, const char *option, double r, double g, double b); // Description: // Query user for color using a Tk color dialog // Return 1 on success, 0 otherwise. static int QueryUserForColor(vtkKWApplication *app, vtkKWWidget *dialog_parent, const char *dialog_title, double in_r, double in_g, double in_b, double *out_r, double *out_g, double *out_b); // Description: // Get the geometry of a widget given by 'widget' (say, .foo.bar). // The geometry is the width, height and position of the widget. // Any of them can be a NULL pointer, they will be safely ignored. // Return 1 on success, 0 otherwise. // A convenience method is provided to query a vtkKWWidget directly. static int GetGeometry(Tcl_Interp *interp, const char *widget, int *width, int *height, int *x, int *y); static int GetGeometry(vtkKWWidget *widget, int *width, int *height, int *x, int *y); // Description: // Check if a pair of screen coordinates (x, y) are within the area defined // by the widget given by 'widget' (say, .foo.bar). // Return 1 if inside, 0 otherwise. // A convenience method is provided to query a vtkKWWidget directly. // ContainsCoordinatesForSpecificType will check if 'widget' is of a // specific type (or a subclass of that type), and if not will inspect // its children. It will return the widget that contains the coordinates // or NULL if not found. static int ContainsCoordinates(Tcl_Interp *interp, const char *widget, int x, int y); static int ContainsCoordinates(vtkKWWidget *widget, int x, int y); static vtkKWWidget* ContainsCoordinatesForSpecificType( vtkKWWidget *widget, int x, int y, const char *classname); // Description: // Update a Tk photo given by its name 'photo_name' using pixels stored in // 'pixels' and structured as a 'width' x 'height' x 'pixel_size' (number // of bytes per pixel, 3 for RGB for example). // If 'buffer_length' is 0, compute it automatically by multiplying // 'pixel_size', 'width' and 'height' together. // If UPDATE_PHOTO_OPTION_FLIP_V is set in 'update_option', flip the image // buffer vertically. // A convenience method is provided to specify the vtkKWApplication this // photo belongs to, instead of the Tcl interpreter. // Return 1 on success, 0 otherwise. //BTX enum { UpdatePhotoOptionFlipVertical = 1 }; //ETX static int UpdatePhoto(Tcl_Interp *interp, const char *photo_name, const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length = 0, int update_options = 0); static int UpdatePhoto(vtkKWApplication *app, const char *photo_name, const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length = 0, int update_options = 0); // Description: // Update a Tk photo given by its name 'photo_name' using pixels stored in // the icon 'icon'. static int UpdatePhotoFromIcon(vtkKWApplication *app, const char *photo_name, vtkKWIcon *icon, int update_options = 0); static int UpdatePhotoFromPredefinedIcon(vtkKWApplication *app, const char *photo_name, int icon_index, int update_options = 0); // Description: // Update a Tk photo given by its name 'photo_name' using pixels stored in // 'pixels' and structured as a 'width' x 'height' x 'pixel_size' (number // of bytes per pixel, 3 for RGB for example). // If a file 'file_name'.png is found in 'directory' or // 'directory/Resources' then an attempt is made to update the photo using // this file. If no file is found, the remaining parameters are used // to update the photo by calling UpdatePhoto(). // As a convenience, if 'photo_name' is NULL, 'file_name' is used instead. // Note that only the PNG file format is supported so far (do not provide // the .png extension to 'file_name'). // Return 1 on success, 0 otherwise. // A convenience method is provided to specify the vtkKWApplication this // photo belongs to, instead of the Tcl interpreter. static int UpdateOrLoadPhoto(Tcl_Interp *interp, const char *photo_name, const char *file_name, const char *directory, const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length = 0); static int UpdateOrLoadPhoto(vtkKWApplication *app, const char *photo_name, const char *file_name, const char *directory, const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length = 0); // Description: // Specifies an image to display in a widget. Typically, if the image // is specified then it overrides other options that specify a bitmap or // textual value to display in the widget. // Set the image option using pixel data. The parameters are the same // as the one used in UpdatePhoto(). // An image is created and associated to the Tk -image option or // image_option if not NULL (ex: -selectimage). static void SetImageOptionToPixels( vtkKWCoreWidget *widget, const unsigned char *pixels, int width, int height, int pixel_size = 4, unsigned long buffer_length = 0, const char *image_option = 0); // Description: // Query if a Tk photo given by its name 'photo_name' exists. // A convenience method is provided to specify the vtkKWApplication this // photo belongs to, instead of the Tcl interpreter. static int FindPhoto(Tcl_Interp *interp, const char *photo_name); static int FindPhoto(vtkKWApplication *app, const char *photo_name); // Description: // Get the height of a Tk photo given by its name 'photo_name'. // If the photo does not exist, return 0 and issue a warning. // A convenience method is provided to specify the vtkKWApplication this // photo belongs to, instead of the Tcl interpreter. // A convenience method is provided to specify a vtkKWWidget this photo // has been assigned to using the -image Tk option. static int GetPhotoHeight(Tcl_Interp *interp, const char *photo_name); static int GetPhotoHeight(vtkKWApplication *app, const char *photo_name); static int GetPhotoHeight(vtkKWWidget *widget); // Description: // Get the width of a Tk photo given by its name 'photo_name'. // If the photo does not exist, return 0 and issue a warning. // A convenience method is provided to specify the vtkKWApplication this // photo belongs to, instead of the Tcl interpreter. static int GetPhotoWidth(Tcl_Interp *interp, const char *photo_name); static int GetPhotoWidth(vtkKWApplication *app, const char *photo_name); // Description: // Change the weight attribute of a Tk font specification given by 'font'. // The new font specification is copied to 'new_font'. // It is up to the caller to allocate enough space in 'new_font'. // Return 1 on success, 0 otherwise. static int ChangeFontWeightToBold( Tcl_Interp *interp, const char *font, char *new_font); static int ChangeFontWeightToNormal( Tcl_Interp *interp, const char *font, char *new_font); // Description: // Change the weight attribute of a 'widget' -font option. // A convenience method is provided to query a vtkKWWidget directly. // Return 1 on success, 0 otherwise. static int ChangeFontWeightToBold(Tcl_Interp *interp, const char *widget); static int ChangeFontWeightToBold(vtkKWWidget *widget); static int ChangeFontWeightToNormal(Tcl_Interp *interp, const char *widget); static int ChangeFontWeightToNormal(vtkKWWidget *widget); // Description: // Change the slant attribute of a Tk font specification given by 'font'. // The new font specification is copied to 'new_font'. // It is up to the caller to allocate enough space in 'new_font'. // Return 1 on success, 0 otherwise. static int ChangeFontSlantToItalic( Tcl_Interp *interp, const char *font, char *new_font); static int ChangeFontSlantToRoman( Tcl_Interp *interp, const char *font, char *new_font); // Description: // Change the slant attribute of a 'widget' -font option. // A convenience method is provided to query a vtkKWWidget directly. // Return 1 on success, 0 otherwise. static int ChangeFontSlantToItalic(Tcl_Interp *interp, const char *widget); static int ChangeFontSlantToItalic(vtkKWWidget *widget); static int ChangeFontSlantToRoman(Tcl_Interp *interp, const char *widget); static int ChangeFontSlantToRoman(vtkKWWidget *widget); // Description: // Change the size attribute of a Tk font specification given by 'font'. // The new font specification is copied to 'new_font'. // It is up to the caller to allocate enough space in 'new_font'. // Return 1 on success, 0 otherwise. static int ChangeFontSize( Tcl_Interp *interp, const char *font, int new_size, char *new_font); // Description: // Change the size attribute of a 'widget' -font option. // A convenience method is provided to query a vtkKWWidget directly. // Return 1 on success, 0 otherwise. static int ChangeFontSize( Tcl_Interp *interp, const char *widget, int new_size); static int ChangeFontSize(vtkKWWidget *widget, int new_size); // Description: // Get the real actual font (i.e. its list of attributes) given a font, // font name, or incomplete font specification. // It is up to the caller to allocate enough space in 'real_font'. // Return 1 on success, 0 otherwise. static int GetRealActualFont( Tcl_Interp *interp, const char *font, char *real_font); // Description: // Get the amount of space the string txt when displayed in widget (using // the default widget's -font parameter). Store the result in 'w'. // Return 1 on success, 0 otherwise. static int GetFontMeasure(vtkKWWidget *widget, const char *txt, int *w); // Description: // Get the number of colums and rows defined in the grid layout of // the widget given by 'widget' (say, .foo.bar). // A convenience method is provided to query a vtkKWWidget directly. // Return 1 on success, 0 otherwise. static int GetGridSize(Tcl_Interp *interp, const char *widget, int *nb_of_cols, int *nb_of_rows); static int GetGridSize(vtkKWWidget *widget, int *nb_of_cols, int *nb_of_rows); // Description: // Get the grid position (column, row) of the widget given by 'widget' // (say, .foo.bar). // We assume that the current widget layout is a Tk grid. // A convenience method is provided to query a vtkKWWidget directly. // Return 1 on success, 0 otherwise. static int GetWidgetPositionInGrid(Tcl_Interp *interp, const char *widget, int *col, int *row); static int GetWidgetPositionInGrid(vtkKWWidget *widget, int *col, int *row); // Description: // Get the bounding box size (width, height) of the slaves packed in the // widget given by 'widget' (say, .foo.bar), i.e. the largest width // and height of the slaves packed in the widget, including padding options. // We assume that the current widget layout is a Tk pack. // A convenience method is provided to query a vtkKWWidget directly. // Return 1 on success, 0 otherwise. static int GetSlavesBoundingBoxInPack(Tcl_Interp *interp, const char *widget, int *width, int *height); static int GetSlavesBoundingBoxInPack(vtkKWWidget *widget, int *width, int *height); // Description: // Get the horizontal position 'x' in pixels of a slave widget given by // 'slave' (say .foo.bar.sl) in the widget given by 'widget' (say .foo.bar). // This can be used in case 'winfo x' does not work because the widget // has not been mapped yet. // We assume that the current widget layout is a Tk pack. // A convenience method is provided to query vtkKWWidget(s) directly. // Return 1 on success, 0 otherwise. static int GetSlaveHorizontalPositionInPack(Tcl_Interp *interp, const char *widget, const char *slave, int *x); static int GetSlaveHorizontalPositionInPack(vtkKWWidget *widget, vtkKWWidget *slave, int *x); // Description: // Get the padding values of the widget given by 'widget' (say .foo.bar) // in its layout. // We assume that the current widget layout is a Tk pack. // Return 1 on success, 0 otherwise. static int GetWidgetPaddingInPack(Tcl_Interp *interp, const char *widget, int *ipadx, int *ipady, int *padx, int *pady); // Description: // Get the container a widget given by 'widget' (say .foo.bar) is packed in. // This is similar to the Tk -in pack option. // Write the container widget name to the output stream 'in'. // We assume that the current widget layout is a Tk pack. // A convenience method is provided to query a vtkKWWidget directly. // Return 1 on success, 0 otherwise. static int GetMasterInPack(Tcl_Interp *interp, const char *widget, ostream &in); static int GetMasterInPack(vtkKWWidget *widget, ostream &in); // Description: // Get the column widths of a grid (i.e. a master widget that has been grid). // If 'allocate' is true, the resulting array (col_widths) is allocated // by the function to match the number of columns. // The function iterates over cells to request the width of // each slave (winfo reqwidth). static int GetGridColumnWidths(Tcl_Interp *interp, const char *widget, int *nb_of_cols, int **col_widths, int allocate = 0); // Description: // Synchronize the columns minimum size of different widgets that have // been grid. If 'factors' is non-null, it is used as an array of // multiplication factor to apply to each column minimum size. // If 'weights' is non-null, it is used as an array of weight // to apply to each column through columnconfigure -weight. static int SynchroniseGridsColumnMinimumSize(Tcl_Interp *interp, int nb_of_widgets, const char **widgets, const float *factors = 0, const int *weights = 0); // Description: // Synchronize the width of a set of labels given by an array // of 'nb_of_widgets' widgets stored in 'widgets'. The maximum size of // the labels is found and assigned to each label. // Additionally it will apply the 'options' to/ each widget (if any). // A convenience method is provided to specify the vtkKWApplication these // widgets belongs to, instead of the Tcl interpreter. // Return 1 on success, 0 otherwise. static int SynchroniseLabelsMaximumWidth(Tcl_Interp *interp, int nb_of_widgets, const char **widgets, const char *options = 0); static int SynchroniseLabelsMaximumWidth(vtkKWApplication *app, int nb_of_widgets, const char **widgets, const char *options = 0); // Description: // Store the slaves packed in the widget given by 'widget' (say, .foo.bar) // in the array 'slaves'. This array is allocated automatically. // We assume that the current widget layout is a Tk pack. // A convenience method is provided to query a vtkKWWidget directly. // Return the number of slaves. static int GetSlavesInPack(Tcl_Interp *interp, const char *widget, char ***slaves); static int GetSlavesInPack(vtkKWWidget *widget, char ***slaves); // Description: // Browse all the slaves of the widget given by 'widget' (say, .foo.bar) // and store the slave packed before 'slave' in 'previous_slave', and the // slave packed after 'slave' in 'next_slave' // We assume that the current widget layout is a Tk pack. // A convenience method is provided to query a vtkKWWidget directly. // Return 1 if 'slave' was found, 0 otherwise static int GetPreviousAndNextSlaveInPack(Tcl_Interp *interp, const char *widget, const char *slave, ostream &previous_slave, ostream &next_slave); static int GetPreviousAndNextSlaveInPack(vtkKWWidget *widget, vtkKWWidget *slave, ostream &previous_slave, ostream &next_slave); // Description: // Take screendump of the widget given by 'widget' (say, .foo.bar) and store // it into a png file given by 'fname'. // A convenience method is provided to query a vtkKWWidget directly. // Return 1 on success, 0 otherwise. static int TakeScreenDump(Tcl_Interp *interp, const char *wname, const char *fname, int top = 0, int bottom = 0, int left = 0, int right = 0); static int TakeScreenDump(vtkKWWidget *widget, const char *fname, int top = 0, int bottom = 0, int left = 0, int right = 0); // Description: // Set widget's toplevel mouse cursor. // Provide a NULL or empty cursor to reset it to default. static int SetTopLevelMouseCursor(Tcl_Interp *interp, const char *widget, const char *cursor); static int SetTopLevelMouseCursor(vtkKWWidget *widget, const char *cursor); // Description: // Return 1 if window is a toplevel, 0 otherwise static int IsTopLevel(Tcl_Interp *interp, const char *widget); static int IsTopLevel(vtkKWWidget *widget); // Description: // Withdraw toplevel static void WithdrawTopLevel(Tcl_Interp *interp, const char *widget); static void WithdrawTopLevel(vtkKWWidget *widget); // Description: // If a Tcl script file is currently being evaluated (i.e. there is a call // to Tcl_EvalFile active or there is an active invocation of the source // command), then this command returns the name of the innermost file // being processed. static const char *GetCurrentScript(Tcl_Interp *interp); static const char *GetCurrentScript(vtkKWApplication *app); // Description: // Create a timer handler, i.e. arranges for a command to be executed // exactly once 'ms' milliseconds later, or when the application is idle, // i.e. the next time the event loop is entered and there are no events to // process. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // Returns a string identifier that can be used to cancel the timer. static const char* CreateTimerHandler( Tcl_Interp *interp, unsigned long ms, vtkObject *object, const char *method); static const char* CreateTimerHandler( vtkKWApplication *app, unsigned long ms, vtkObject *object, const char *method); static const char* CreateIdleTimerHandler( Tcl_Interp *interp, vtkObject *object, const char *method); static const char* CreateIdleTimerHandler( vtkKWApplication *app, vtkObject *object, const char *method); // Description: // Cancel one or all event handlers, i.e. cancel all delayed command that // were registered using the 'after' command or CreateTimerHandler methods. static void CancelTimerHandler(Tcl_Interp *interp, const char *id); static void CancelTimerHandler(vtkKWApplication *app, const char *id); static void CancelAllTimerHandlers(Tcl_Interp *interp); static void CancelAllTimerHandlers(vtkKWApplication *app); // Description: // Rings the bell on the display of the application's main window static void Bell(Tcl_Interp *interp); static void Bell(vtkKWApplication *app); // Description: // Process/update pending events. This command is used to bring the // application "up to date" by entering the event loop repeatedly until // all pending events (including idle callbacks) have been processed. static void ProcessPendingEvents(Tcl_Interp *interp); static void ProcessPendingEvents(vtkKWApplication *app); // Description: // Process/update idle tasks. This causes operations that are normally // deferred, such as display updates and window layout calculations, to be // performed immediately. static void ProcessIdleTasks(Tcl_Interp *interp); static void ProcessIdleTasks(vtkKWApplication *app); // Description: // Check for pending interaction events, i.e. mouse button up/down, window // being dragged/resized/moved, paint, window activation, etc. // On Unix, one needs to pass a vtkRenderWindow (on Win32, NULL is fine) // Return 1 if events are pending, 0 otherwise static int CheckForPendingInteractionEvents(vtkRenderWindow *win); // Description: // Get the coordinates of the mouse pointer in the screen widget is in. // Return 1 on success, 0 otherwise. static int GetMousePointerCoordinates( Tcl_Interp *interp, const char *widget, int *x, int *y); static int GetMousePointerCoordinates( vtkKWWidget *widget, int *x, int *y); // Description: // Get the coordinates of the upper-left corner of widget in its screen. // Return 1 on success, 0 otherwise. static int GetWidgetCoordinates( Tcl_Interp *interp, const char *widget, int *x, int *y); static int GetWidgetCoordinates( vtkKWWidget *widget, int *x, int *y); // Description: // Get the relative coordinates of the upper-left corner of widget in its // widget's parent. // Return 1 on success, 0 otherwise. static int GetWidgetRelativeCoordinates( Tcl_Interp *interp, const char *widget, int *x, int *y); static int GetWidgetRelativeCoordinates( vtkKWWidget *widget, int *x, int *y); // Description: // Get the width and height of widget in its screen. // When a window is first created its width will be 1 pixel; the width will // eventually be changed by a geometry manager to fulfill the window's needs. // If you need the true width immediately after creating a widget, invoke // ProcessPendingEvents to force the geometry manager to arrange it, or use // GetWidgetRequestedSize to get the window's requested size instead of its // actual size. // Return 1 on success, 0 otherwise. static int GetWidgetSize( Tcl_Interp *interp, const char *widget, int *w, int *h); static int GetWidgetSize( vtkKWWidget *widget, int *w, int *h); // Description: // Get the requested width and height of widget in its screen. // This is the value used by window's geometry manager to compute its // geometry. // Return 1 on success, 0 otherwise. static int GetWidgetRequestedSize( Tcl_Interp *interp, const char *widget, int *w, int *h); static int GetWidgetRequestedSize( vtkKWWidget *widget, int *w, int *h); // Description: // Get the widget class (i.e. Tk type). static const char* GetWidgetClass( Tcl_Interp *interp, const char *widget); static const char* GetWidgetClass( vtkKWWidget *widget); // Description: // Get the width and height (in pixels) of the screen the widget is in. // Return 1 on success, 0 otherwise. static int GetScreenSize( Tcl_Interp *interp, const char *widget, int *w, int *h); static int GetScreenSize( vtkKWWidget *widget, int *w, int *h); // Description: // Get windowing system. // Returns the current Tk windowing system, one of x11 (X11-based), // win32 (MS Windows), classic (Mac OS Classic), or aqua (Mac OS X Aqua). static const char* GetWindowingSystem(vtkKWApplication *app); static const char* GetWindowingSystem(Tcl_Interp *interp); protected: vtkKWTkUtilities() {}; ~vtkKWTkUtilities() {}; //BTX //ETX static int ChangeFontWeight( Tcl_Interp *interp, const char *widget, int bold); static int ChangeFontWeight( Tcl_Interp *interp, const char *font, int bold, char *new_font); static int ChangeFontSlant( Tcl_Interp *interp, const char *widget, int italic); static int ChangeFontSlant( Tcl_Interp *interp, const char *font, int italic, char *new_font); static const char* EvaluateStringFromArgsInternal( Tcl_Interp *interp, vtkObject *obj, const char *format, va_list var_args1, va_list var_args2); static const char* EvaluateSimpleStringInternal( Tcl_Interp *interp, vtkObject *obj, const char *str); private: vtkKWTkUtilities(const vtkKWTkUtilities&); // Not implemented void operator=(const vtkKWTkUtilities&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/Testing/0000755000175000017500000000000011461110202016462 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Testing/CMakeLists.txt0000644000175000017500000000064211006107366021240 0ustar domibeldomibelsubdirs(Tcl) subdirs(Cxx) if (VTK_WRAP_PYTHON) subdirs(Python) endif (VTK_WRAP_PYTHON) if(PYTHON_EXECUTABLE AND VTK_HEADER_TESTING_PY) add_test(KWWidgets-HeaderTesting ${PYTHON_EXECUTABLE} ${VTK_HEADER_TESTING_PY} "${KWWidgets_SOURCE_DIR}" vtkKWEvent.h vtkKWWidgets.h vtkKWFileBrowserUtilities.h vtkKWRenderWidgetCallbackCommand.h ) endif(PYTHON_EXECUTABLE AND VTK_HEADER_TESTING_PY) kwwidgets-1.0.0~cvs20100930/Testing/Cxx/0000755000175000017500000000000011461110202017224 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Testing/Cxx/TestStateMachine.cxx0000644000175000017500000000623710533620246023202 0ustar domibeldomibel#include "vtkKWStateMachine.h" #include "vtkKWStateMachineState.h" #include "vtkKWStateMachineInput.h" #include "vtkKWStateMachineTransition.h" #include "vtkKWStateMachineDOTWriter.h" #include "vtkKWStateMachineCluster.h" int main() { // State machine vtkKWStateMachine *state_machine = vtkKWStateMachine::New(); // States vtkKWStateMachineState *state_1 = vtkKWStateMachineState::New(); state_1->SetName("Start"); state_machine->AddState(state_1); state_1->Delete(); vtkKWStateMachineState *state_2 = vtkKWStateMachineState::New(); state_machine->AddState(state_2); state_2->Delete(); vtkKWStateMachineState *state_3 = vtkKWStateMachineState::New(); state_machine->AddState(state_3); state_3->Delete(); // Inputs vtkKWStateMachineInput *input_next = vtkKWStateMachineInput::New(); input_next->SetName("next"); state_machine->AddInput(input_next); input_next->Delete(); vtkKWStateMachineInput *input_skip = vtkKWStateMachineInput::New(); input_skip->SetName("skip"); state_machine->AddInput(input_skip); input_skip->Delete(); vtkKWStateMachineInput *input_invalid = vtkKWStateMachineInput::New(); input_invalid->SetName("invalid"); state_machine->AddInput(input_invalid); input_invalid->Delete(); // Transition: state_1 / input_next => state_2 vtkKWStateMachineTransition *trans_a = vtkKWStateMachineTransition::New(); trans_a->SetOriginState(state_1); trans_a->SetInput(input_next); trans_a->SetDestinationState(state_2); state_machine->AddTransition(trans_a); trans_a->Delete(); // Transition: state_1 / input_skip => state_3 // Transition: state_2 / input_next => state_3 // Transition: state_3 / input_next => state_1 // Transition: state_2 / input_invalid => state_2 state_machine->CreateTransition(state_1, input_skip, state_3); state_machine->CreateTransition(state_2, input_next, state_3); state_machine->CreateTransition(state_3, input_next, state_1); state_machine->CreateTransition(state_2, input_invalid, state_2); // For I/O purposes, let's group some states inside a cluster vtkKWStateMachineCluster *cluster = vtkKWStateMachineCluster::New(); cluster->AddState(state_2); cluster->AddState(state_3); state_machine->AddCluster(cluster); cluster->Delete(); // Run the state machine state_machine->SetInitialState(state_1); state_1->AcceptingOn(); state_machine->PushInput(input_next); // state_1 to state_2 state_machine->PushInput(input_invalid); // state_2 to state_2 state_machine->PushInput(input_next); // state_2 to state_3 state_machine->ProcessInputs(); state_machine->PushInput(input_next); // state_3 to state_1 state_machine->PushInput(input_skip); // state_1 to state_3 state_machine->ProcessInputs(); #if 0 vtkKWStateMachineDOTWriter *writer = vtkKWStateMachineDOTWriter::New(); writer->SetInput(state_machine); writer->SetGraphLabel("State Machine Example"); writer->WriteToStream(cout); writer->Delete(); #endif int res = 0; if (state_machine->GetCurrentState() != state_3) { cout << "Error! The state machine did not reach the expected state!" << endl; res = 1; } state_machine->Delete(); return res; } kwwidgets-1.0.0~cvs20100930/Testing/Cxx/CMakeLists.txt0000644000175000017500000000055411006107367022005 0ustar domibeldomibelinclude("${KWWidgets_CMAKE_DIR}/KWWidgetsTestingMacros.cmake") set(TESTS Random Registry StateMachine ) foreach(TEST ${TESTS}) set(EXE_NAME KWWidgetsTest${TEST}) add_executable(${EXE_NAME} Test${TEST}.cxx) target_link_libraries(${EXE_NAME} ${KWWidgets_LIBRARIES}) kwwidgets_add_test_with_launcher(KWWidgets-${TEST} ${EXE_NAME}) endforeach(TEST) kwwidgets-1.0.0~cvs20100930/Testing/Cxx/TestRegistry.cxx0000644000175000017500000000653310223337713022444 0ustar domibeldomibel/*========================================================================= Program: ParaView Module: $RCSfile: TestRegistry.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWRegistryHelper.h" #define IFT(x,res) if ( !x ) \ { \ res = 1; \ cout << "Error in: " << #x << endl; \ } #define IFNT(x,res) if ( x ) \ { \ res = 1; \ cout << "Error in: " << #x << endl; \ } #define CHE(x,y,res) if ( strcmp(x,y) ) \ { \ res = 1; \ cout << "Error, " << x << " != " << y << endl; \ } int main(int vtkNotUsed(argc), char** vtkNotUsed(argv)) { int res = 0; vtkKWRegistryHelper *reg = vtkKWRegistryHelper::New(); reg->SetTopLevel("TestRegistry"); IFT(reg->SetValue("TestSubkey", "TestKey1", "Test Value 1"), res); IFT(reg->SetValue("TestSubkey1", "TestKey2", "Test Value 2"), res); IFT(reg->SetValue("TestSubkey", "TestKey3", "Test Value 3"), res); IFT(reg->SetValue("TestSubkey2", "TestKey4", "Test Value 4"), res); char buffer[1024]; IFT(reg->ReadValue("TestSubkey", "TestKey1", buffer), res); CHE(buffer, "Test Value 1", res); IFT(reg->ReadValue("TestSubkey1", "TestKey2", buffer), res); CHE(buffer, "Test Value 2", res); IFT(reg->ReadValue("TestSubkey", "TestKey3", buffer), res); CHE(buffer, "Test Value 3", res); IFT(reg->ReadValue("TestSubkey2", "TestKey4", buffer), res); CHE(buffer, "Test Value 4", res); IFT(reg->SetValue("TestSubkey", "TestKey1", "New Test Value 1"), res); IFT(reg->SetValue("TestSubkey1", "TestKey2", "New Test Value 2"), res); IFT(reg->SetValue("TestSubkey", "TestKey3", "New Test Value 3"), res); IFT(reg->SetValue("TestSubkey2", "TestKey4", "New Test Value 4"), res); IFT(reg->ReadValue("TestSubkey", "TestKey1", buffer), res); CHE(buffer, "New Test Value 1", res); IFT(reg->ReadValue("TestSubkey1", "TestKey2", buffer), res); CHE(buffer, "New Test Value 2", res); IFT(reg->ReadValue("TestSubkey", "TestKey3", buffer), res); CHE(buffer, "New Test Value 3", res); IFT(reg->ReadValue("TestSubkey2", "TestKey4", buffer), res); CHE(buffer, "New Test Value 4", res); IFT( reg->DeleteValue("TestSubkey", "TestKey1"), res); IFNT(reg->ReadValue( "TestSubkey", "TestKey1", buffer), res); IFT( reg->DeleteValue("TestSubkey1", "TestKey2"), res); IFNT(reg->ReadValue( "TestSubkey1", "TestKey2", buffer), res); IFT( reg->DeleteValue("TestSubkey", "TestKey3"), res); IFNT(reg->ReadValue( "TestSubkey", "TestKey3", buffer), res); IFT( reg->DeleteValue("TestSubkey2", "TestKey4"), res); IFNT(reg->ReadValue( "TestSubkey2", "TestKey5", buffer), res); reg->Delete(); if ( res ) { cout << "Test failed" << endl; } return res; } kwwidgets-1.0.0~cvs20100930/Testing/Cxx/TestRandom.cxx0000644000175000017500000000223711012414244022041 0ustar domibeldomibel#include "vtkKWEvent.h" #include "vtkKWObject.h" #include "vtkToolkits.h" /* Let's check if VTK >= 5.2 is exporting its headers correctly */ #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION >= 2) // MetaIO #ifdef VTK_USE_METAIO #include "vtkmetaio/metaLine.h" #endif // DICOM Parser #include "DICOMParser.h" // Verdict #include "verdict.h" #endif // VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION >= 2) int main() { #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION >= 2) // MetaIO #ifdef VTK_USE_METAIO vtkmetaio::MetaLine line; (void)line; #endif // DICOM Parser DICOMParser parser; (void)parser; // Verdict HexMetricVals hex_metric; (void)hex_metric; #endif // VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION >= 2) int res = 0; const char *event = vtkKWEvent::GetStringFromEventId(2001); if (!event || strcmp("MessageDialogInvokeEvent", event)) { cout << "Problem with vtkKWEvent::GetStringFromEventId. Requested:" << 2001 << "(MessageDialogInvokeEvent) got: " << event << endl; res = 1; } return res; } kwwidgets-1.0.0~cvs20100930/Testing/Python/0000755000175000017500000000000011461110202017743 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Testing/Python/CMakeLists.txt0000644000175000017500000000000007526001301022477 0ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Testing/Tcl/0000755000175000017500000000000011461110202017204 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Testing/Tcl/CMakeLists.txt0000644000175000017500000000064011006107367021761 0ustar domibeldomibelif(VTK_PRINT_SELF_CHECK_TCL AND TCL_TCLSH) add_test(KWWidgets-PrintSelf ${TCL_TCLSH} ${VTK_PRINT_SELF_CHECK_TCL} ${KWWidgets_SOURCE_DIR}) endif(VTK_PRINT_SELF_CHECK_TCL AND TCL_TCLSH) if(VTK_FIND_STRING_TCL AND TCL_TCLSH) add_test(KWWidgets-SetObjectMacro ${TCL_TCLSH} ${VTK_FIND_STRING_TCL} "${KWWidgets_SOURCE_DIR}/vtk\\\\*.h" "vtkSetObjectMacro") endif(VTK_FIND_STRING_TCL AND TCL_TCLSH) kwwidgets-1.0.0~cvs20100930/vtkKWParameterValueHermiteFunctionEditor.h0000644000175000017500000003322111001227411025317 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWParameterValueHermiteFunctionEditor.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWParameterValueHermiteFunctionEditor - a hermite function editor // .SECTION Description // This widget implements and defines the interface needed to edit // an hermitian curve. On top of the superclass API that already // describes each control point of the curve, several pure virtual functions // are provided for subclasses to specify the midpoint and sharpness at each // control point. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. #ifndef __vtkKWParameterValueHermiteFunctionEditor_h #define __vtkKWParameterValueHermiteFunctionEditor_h #include "vtkKWParameterValueFunctionEditor.h" class vtkKWScaleWithEntry; class KWWidgets_EXPORT vtkKWParameterValueHermiteFunctionEditor : public vtkKWParameterValueFunctionEditor { public: vtkTypeRevisionMacro(vtkKWParameterValueHermiteFunctionEditor,vtkKWParameterValueFunctionEditor); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the midpoint entry UI visibility. // Not shown if superclass PointEntriesVisibility is set to Off // Note: set this parameter to the proper value before calling Create() in // order to minimize the footprint of the object. vtkBooleanMacro(MidPointEntryVisibility, int); virtual void SetMidPointEntryVisibility(int); vtkGetMacro(MidPointEntryVisibility, int); // Description: // Access the parameter entry. virtual vtkKWScaleWithEntry* GetMidPointEntry(); // Description: // Set/Get if the midpoint value should be displayed in the parameter // domain instead of the normalized [0.0, 1.0] domain. vtkBooleanMacro(DisplayMidPointValueInParameterDomain, int); virtual void SetDisplayMidPointValueInParameterDomain(int); vtkGetMacro(DisplayMidPointValueInParameterDomain, int); // Description: // Set/Get the sharpness entry UI visibility. // Not shown if superclass PointEntriesVisibility is set to Off // Note: set this parameter to the proper value before calling Create() in // order to minimize the footprint of the object. vtkBooleanMacro(SharpnessEntryVisibility, int); virtual void SetSharpnessEntryVisibility(int); vtkGetMacro(SharpnessEntryVisibility, int); // Description: // Access the parameter entry. virtual vtkKWScaleWithEntry* GetSharpnessEntry(); // Description: // Set/Get the midpoint visibility in the canvas. // The style of the midpoint is a rectangle around the midpoint location. // Its color is controlled using MidPointColor. vtkBooleanMacro(MidPointVisibility, int); virtual void SetMidPointVisibility(int); vtkGetMacro(MidPointVisibility, int); // Description: // Set/Get the midpoints color. vtkGetVector3Macro(MidPointColor, double); virtual void SetMidPointColor(double r, double g, double b); virtual void SetMidPointColor(double rgb[3]) { this->SetMidPointColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the selected midpoint color. vtkGetVector3Macro(SelectedMidPointColor, double); virtual void SetSelectedMidPointColor(double r, double g, double b); virtual void SetSelectedMidPointColor(double rgb[3]) { this->SetSelectedMidPointColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the midpoint guideline visibility in the canvas // (for ex: a vertical line at each midpoint). // The style of the midpoint guidelines is the same as the style of the // superclass point guideline (PointGuidelineStyle) for consistency. vtkBooleanMacro(MidPointGuidelineVisibility, int); virtual void SetMidPointGuidelineVisibility(int); vtkGetMacro(MidPointGuidelineVisibility, int); // Description: // Set/Get the midpoint guideline value visibility in the canvas // (i.e., a value on top of the guideline). // Note that the value is not displayed if MidPointGuidelineVisibility is // set to Off (i.e. if we do not display the guideline itself, why displaying // the value ?). vtkBooleanMacro(MidPointGuidelineValueVisibility, int); virtual void SetMidPointGuidelineValueVisibility(int); vtkGetMacro(MidPointGuidelineValueVisibility, int); // Description: // Set/Get the midpoint guideline value printf format. virtual void SetMidPointGuidelineValueFormat(const char *); vtkGetStringMacro(MidPointGuidelineValueFormat); // Description: // Select/Deselect the midpoint between two adjacent points 'id' and // 'id + 1'. Retrieve the midpoint selection, clear it, etc. // (-1 if none selected) vtkGetMacro(SelectedMidPoint, int); virtual void SelectMidPoint(int id); virtual void ClearMidPointSelection(); virtual int HasMidPointSelection(); // Description: // Select a point. // Override the superclass so that selecting a point will clear // the midpoint selection. virtual void SelectPoint(int id); // Description: // Select next and previous point. // Override the superclass so that the mid-points are also selected (i.e. // it will iterator over point, mid-point, point, mid-point, etc.) virtual void SelectNextPoint(); virtual void SelectPreviousPoint(); // Description: // Specifies selection-related commands to associate with the widget. // 'MidPointSelectionChangedCommand' is called whenever the midpoint // selection was changed or cleared. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetMidPointSelectionChangedCommand( vtkObject *object,const char *method); // Description: // Events. Even though it is highly recommended to use the commands // framework defined above to specify the callback methods you want to be // invoked when specific event occur, you can also use the observer // framework and listen to the corresponding events: //BTX enum { MidPointSelectionChangedEvent = 11000 }; //ETX // Description: // Synchronize single selection between two editors A and B. // Override the superclass to take the midpoint selection into account // Return 1 on success, 0 otherwise. virtual int SynchronizeSingleSelection( vtkKWParameterValueFunctionEditor *b); virtual int DoNotSynchronizeSingleSelection( vtkKWParameterValueFunctionEditor *b); // Description: // Synchronize same selection between two editors A and B. // Override the superclass to take the midpoint selection into account // Return 1 on success, 0 otherwise. virtual int SynchronizeSameSelection( vtkKWParameterValueFunctionEditor *b); virtual int DoNotSynchronizeSameSelection( vtkKWParameterValueFunctionEditor *b); // Description: // Update the whole UI depending on the value of the Ivars virtual void Update(); // Description: // Convenience method that will hide all elements but the histogram. virtual void DisplayHistogramOnly(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Some constants //BTX static const char *MidPointTag; static const char *MidPointGuidelineTag; static const char *MidPointSelectedTag; //ETX // Description: // Callbacks. Internal, do not use. virtual void MidPointEntryChangedCallback(double value); virtual void MidPointEntryChangingCallback(double value); virtual void SharpnessEntryChangedCallback(double value); virtual void SharpnessEntryChangingCallback(double value); virtual void StartInteractionCallback(int x, int y, int shift); virtual void MoveMidPointCallback(int x, int y, int button); virtual void EndMidPointInteractionCallback(int x, int y); protected: vtkKWParameterValueHermiteFunctionEditor(); ~vtkKWParameterValueHermiteFunctionEditor(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Retrieve the midpoint between two adjacent points 'id' and 'id + 1'. // The midpoint is the normalized distance between the two points at which // the interpolated value reaches the median value in the value space. // Return 1 on success (there is a midpoint at normalized position 'pos'), // 0 otherwise. // The default implementation here does not provide any midpoint. virtual int GetFunctionPointMidPoint(int id, double *pos) = 0; // Description: // Set the midpoint between two adjacent points 'id' and 'id + 1'. // Return 1 on success (the midpoint was successfully set at normalized // position 'pos'), 0 otherwise. // The default implementation here does not provide any midpoint. virtual int SetFunctionPointMidPoint(int id, double pos) = 0; // Description: // Return 1 if the 'midpoint' of the point 'id' is locked (can/should // not be changed/edited), 0 otherwise. virtual int FunctionPointMidPointIsLocked(int id); // Description: // Retrieve the sharpness of the transition between two adjacent points // 'id' and 'id + 1'. // Return 1 on success (there is a sharpness defined for this point), // 0 otherwise. virtual int GetFunctionPointSharpness(int id, double *sharpness) = 0; // Description: // Set the sharpness of the transition between two adjacent points // 'id' and 'id + 1'. // Return 1 on success (the sharpness was successfully set), 0 otherwise. virtual int SetFunctionPointSharpness(int id, double sharpness) = 0; // Description: // Return 1 if the 'sharpness' of the point 'id' is locked (can/should // not be changed/edited), 0 otherwise. virtual int FunctionPointSharpnessIsLocked(int id); // Description: // Update mi9dpoint entries virtual void UpdateMidPointEntries(int id); // Description: // Higher-level methods to manipulate the function. virtual int GetMidPointCanvasCoordinates(int id, int *x, int *y, double *p); virtual int FindMidPointAtCanvasCoordinates( int x, int y, int *id, int *c_x, int *c_y); int MidPointEntryVisibility; int DisplayMidPointValueInParameterDomain; int SharpnessEntryVisibility; int MidPointGuidelineVisibility; int MidPointGuidelineValueVisibility; double MidPointColor[3]; double SelectedMidPointColor[3]; int SelectedMidPoint; int LastMidPointSelectionCanvasCoordinateX; int LastMidPointSelectionCanvasCoordinateY; double LastMidPointSelectionSharpness; char* MidPointGuidelineValueFormat; // Commands char *MidPointSelectionChangedCommand; virtual void InvokeMidPointSelectionChangedCommand(); // GUI vtkKWScaleWithEntry *MidPointEntry; vtkKWScaleWithEntry *SharpnessEntry; // Description: // Create some objects on the fly (lazy creation, to allow for a smaller // footprint) virtual void CreateMidPointEntry(); virtual void CreateSharpnessEntry(); virtual int IsPointEntriesFrameUsed(); virtual int IsGuidelineValueCanvasUsed(); // Description: // Update the midpoint entry according to the midpoint of a point virtual void UpdateMidPointEntry(int id); // Description: // Update the sharpness entry according to the sharpness of a point virtual void UpdateSharpnessEntry(int id); // Description: // Merge the point 'editor_id' from another function editor 'editor' into // our instance. Override the super to pass the midpoint and sharpness too virtual int MergePointFromEditor( vtkKWParameterValueFunctionEditor *editor, int editor_id, int *new_id); // Description: // Copy the point 'id' parameter and values from another function editor // 'editor' into the point 'id' in the instance. // Override the super to pass the midpoint and sharpness too virtual int CopyPointFromEditor( vtkKWParameterValueFunctionEditor *editor, int id); // Description: // Redraw the whole function or a specific point, or // the line between two points. Overriden to take midpoints into account //BTX virtual void RedrawFunction(); virtual void RedrawFunctionDependentElements(); virtual void RedrawSinglePointDependentElements(int id); virtual void RedrawLine(int id1, int id2, vtksys_ios::ostream *tk_cmd = 0); //ETX // Description: // Pack the widget virtual void PackPointEntries(); // Description: // Bind/Unbind all widgets. virtual void Bind(); virtual void UnBind(); // Synchronization callbacks virtual void ProcessSynchronizationEvents( vtkObject *caller, unsigned long event, void *calldata); virtual void ProcessSynchronizationEvents2( vtkObject *caller, unsigned long event, void *calldata); private: int MidPointVisibility; vtkKWParameterValueHermiteFunctionEditor(const vtkKWParameterValueHermiteFunctionEditor&); // Not implemented void operator=(const vtkKWParameterValueHermiteFunctionEditor&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWMatrixWidget.cxx0000644000175000017500000003047210540353637021220 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWMatrixWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWMatrixWidget.h" #include "vtkKWEntrySet.h" #include "vtkKWEntry.h" #include "vtkObjectFactory.h" #include #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWMatrixWidget ); vtkCxxRevisionMacro(vtkKWMatrixWidget, "$Revision: 1.6 $"); //---------------------------------------------------------------------------- vtkKWMatrixWidget::vtkKWMatrixWidget() { this->NumberOfColumns = 1; this->NumberOfRows = 1; this->EntrySet = vtkKWEntrySet::New(); this->ElementWidth = 5; this->ReadOnly = 0; this->RestrictElementValue = vtkKWMatrixWidget::RestrictDouble; this->ElementChangedCommand = NULL; this->ElementChangedCommandTrigger = (vtkKWMatrixWidget::TriggerOnFocusOut | vtkKWMatrixWidget::TriggerOnReturnKey); } //---------------------------------------------------------------------------- vtkKWMatrixWidget::~vtkKWMatrixWidget() { if (this->EntrySet) { this->EntrySet->SetParent(NULL); this->EntrySet->Delete(); } if (this->ElementChangedCommand) { delete [] this->ElementChangedCommand; this->ElementChangedCommand = NULL; } } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); this->EntrySet->SetParent(this); this->EntrySet->Create(); this->EntrySet->PackHorizontallyOn(); this->EntrySet->SetWidgetsPadX(1); this->EntrySet->SetWidgetsPadY(1); this->EntrySet->ExpandWidgetsOff(); this->Script("pack %s -fill both", this->EntrySet->GetWidgetName()); this->UpdateWidget(); } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetNumberOfColumns(int arg) { if (this->NumberOfColumns == arg || arg < 0) { return; } this->NumberOfColumns = arg; this->Modified(); this->UpdateWidget(); } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetNumberOfRows(int arg) { if (this->NumberOfRows == arg || arg < 0) { return; } this->NumberOfRows = arg; this->Modified(); this->UpdateWidget(); } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetElementValue(int row, int col, const char *val) { if (this->EntrySet && this->EntrySet->IsCreated() && row >= 0 && row < this->NumberOfRows && col >= 0 && col < this->NumberOfColumns) { int id = col + row * this->NumberOfColumns; this->EntrySet->GetWidget(id)->SetValue(val); } } //---------------------------------------------------------------------------- const char* vtkKWMatrixWidget::GetElementValue(int row, int col) { if (this->EntrySet && this->EntrySet->IsCreated() && row >= 0 && row < this->NumberOfRows && col >= 0 && col < this->NumberOfColumns) { int id = col + row * this->NumberOfColumns; return this->EntrySet->GetWidget(id)->GetValue(); } return NULL; } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetElementValueAsInt(int row, int col, int val) { if (this->EntrySet && this->EntrySet->IsCreated() && row >= 0 && row < this->NumberOfRows && col >= 0 && col < this->NumberOfColumns) { int id = col + row * this->NumberOfColumns; this->EntrySet->GetWidget(id)->SetValueAsInt(val); } } //---------------------------------------------------------------------------- int vtkKWMatrixWidget::GetElementValueAsInt(int row, int col) { if (this->EntrySet && this->EntrySet->IsCreated() && row >= 0 && row < this->NumberOfRows && col >= 0 && col < this->NumberOfColumns) { int id = col + row * this->NumberOfColumns; return this->EntrySet->GetWidget(id)->GetValueAsInt(); } return 0; } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetElementValueAsDouble(int row, int col, double val) { if (this->EntrySet && this->EntrySet->IsCreated() && row >= 0 && row < this->NumberOfRows && col >= 0 && col < this->NumberOfColumns) { int id = col + row * this->NumberOfColumns; this->EntrySet->GetWidget(id)->SetValueAsDouble(val); } } //---------------------------------------------------------------------------- double vtkKWMatrixWidget::GetElementValueAsDouble(int row, int col) { if (this->EntrySet && this->EntrySet->IsCreated() && row >= 0 && row < this->NumberOfRows && col >= 0 && col < this->NumberOfColumns) { int id = col + row * this->NumberOfColumns; return this->EntrySet->GetWidget(id)->GetValueAsDouble(); } return 0; } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::UpdateWidget() { if (!this->EntrySet->IsCreated()) { return; } int i; this->EntrySet->SetMaximumNumberOfWidgetsInPackingDirection( this->NumberOfColumns); int entry_trigger = 0; if (this->ElementChangedCommandTrigger & vtkKWMatrixWidget::TriggerOnFocusOut) { entry_trigger |= vtkKWEntry::TriggerOnFocusOut; } if (this->ElementChangedCommandTrigger & vtkKWMatrixWidget::TriggerOnReturnKey) { entry_trigger |= vtkKWEntry::TriggerOnReturnKey; } if (this->ElementChangedCommandTrigger & vtkKWMatrixWidget::TriggerOnAnyChange) { entry_trigger |= vtkKWEntry::TriggerOnAnyChange; } char command[256]; int nb_requested_entries = this->NumberOfColumns * this->NumberOfRows; int nb_entries = this->EntrySet->GetNumberOfWidgets(); while (nb_entries < nb_requested_entries) { int id = nb_entries++; vtkKWEntry *entry = this->EntrySet->AddWidget(id); if (entry) { entry->SetWidth(this->ElementWidth); entry->SetReadOnly(this->ReadOnly); entry->SetRestrictValue(this->RestrictElementValue); sprintf(command, "ElementChangedCallback %d", id); entry->SetCommand(this, command); entry->SetCommandTrigger(entry_trigger); } } for (i = 0; i < nb_requested_entries; i++) { this->EntrySet->SetWidgetVisibility(i, 1); } for (i = nb_requested_entries; i < nb_entries; i++) { this->EntrySet->SetWidgetVisibility(i, 0); } } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetRestrictElementValue(int arg) { if (this->RestrictElementValue == arg) { return; } this->RestrictElementValue = arg; this->Modified(); if (this->EntrySet->IsCreated()) { for (int i = 0; i < this->EntrySet->GetNumberOfWidgets(); i++) { vtkKWEntry *entry = this->EntrySet->GetWidget(i); if (entry) { entry->SetRestrictValue(this->RestrictElementValue); } } } } void vtkKWMatrixWidget::SetRestrictElementValueToInteger() { this->SetRestrictElementValue(vtkKWMatrixWidget::RestrictInteger); } void vtkKWMatrixWidget::SetRestrictElementValueToDouble() { this->SetRestrictElementValue(vtkKWMatrixWidget::RestrictDouble); } void vtkKWMatrixWidget::SetRestrictElementValueToNone() { this->SetRestrictElementValue(vtkKWMatrixWidget::RestrictNone); } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetElementWidth(int width) { if (this->ElementWidth == width) { return; } this->ElementWidth = width; this->Modified(); if (this->EntrySet->IsCreated()) { for (int i = 0; i < this->EntrySet->GetNumberOfWidgets(); i++) { vtkKWEntry *entry = this->EntrySet->GetWidget(i); if (entry) { entry->SetWidth(this->ElementWidth); } } } } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetReadOnly(int arg) { if (this->ReadOnly == arg) { return; } this->ReadOnly = arg; this->Modified(); if (this->EntrySet->IsCreated()) { for (int i = 0; i < this->EntrySet->GetNumberOfWidgets(); i++) { vtkKWEntry *entry = this->EntrySet->GetWidget(i); if (entry) { entry->SetReadOnly(this->ReadOnly); } } } } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetElementChangedCommandTrigger(int arg) { if (this->ElementChangedCommandTrigger == arg) { return; } this->ElementChangedCommandTrigger = arg; this->Modified(); int entry_trigger = 0; if (this->ElementChangedCommandTrigger & vtkKWMatrixWidget::TriggerOnFocusOut) { entry_trigger |= vtkKWEntry::TriggerOnFocusOut; } if (this->ElementChangedCommandTrigger & vtkKWMatrixWidget::TriggerOnReturnKey) { entry_trigger |= vtkKWEntry::TriggerOnReturnKey; } if (this->ElementChangedCommandTrigger & vtkKWMatrixWidget::TriggerOnAnyChange) { entry_trigger |= vtkKWEntry::TriggerOnAnyChange; } if (this->EntrySet->IsCreated()) { for (int i = 0; i < this->EntrySet->GetNumberOfWidgets(); i++) { vtkKWEntry *entry = this->EntrySet->GetWidget(i); if (entry) { entry->SetCommandTrigger(entry_trigger); } } } } void vtkKWMatrixWidget::SetElementChangedCommandTriggerToReturnKeyAndFocusOut() { this->SetElementChangedCommandTrigger( vtkKWMatrixWidget::TriggerOnFocusOut | vtkKWMatrixWidget::TriggerOnReturnKey); } void vtkKWMatrixWidget::SetElementChangedCommandTriggerToAnyChange() { this->SetElementChangedCommandTrigger(vtkKWMatrixWidget::TriggerOnAnyChange); } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::ElementChangedCallback(int id, const char *value) { int rank = this->EntrySet->GetWidgetPosition(id); if (this->NumberOfColumns && this->NumberOfRows) { int row = rank / this->NumberOfColumns; int col = rank % this->NumberOfColumns; this->InvokeElementChangedCommand(row, col, value); } } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::SetElementChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->ElementChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::InvokeElementChangedCommand( int row, int col, const char *value) { if (this->ElementChangedCommand && *this->ElementChangedCommand && this->IsCreated()) { const char *val = this->ConvertInternalStringToTclString( value, vtkKWCoreWidget::ConvertStringEscapeInterpretable); this->Script("%s %d %d \"%s\"", this->ElementChangedCommand, row, col, val ? val : ""); } void *data[3]; data[0] = &row; data[1] = &col; data[2] = &value; this->InvokeEvent(vtkKWMatrixWidget::ElementChangedEvent, data); } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::UpdateEnableState() { this->Superclass::UpdateEnableState(); if (this->EntrySet) { this->EntrySet->SetEnabled(this->GetEnabled()); } } //---------------------------------------------------------------------------- void vtkKWMatrixWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Width: " << this->GetWidth() << endl; os << indent << "Readonly: " << (this->ReadOnly ? "On" : "Off") << endl; os << indent << "RestrictElementValue: " << this->RestrictElementValue << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWWidgets.h0000644000175000017500000000172210410610277017627 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWidgets.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #ifndef __vtkKWWidgets_h #define __vtkKWWidgets_h #include "vtkKWWidgetsConfigure.h" #if defined(_WIN32) && defined(KWWidgets_BUILD_SHARED_LIBS) # if defined(KWWidgets_EXPORTS) # define KWWidgets_EXPORT __declspec( dllexport ) # else # define KWWidgets_EXPORT __declspec( dllimport ) # endif #else # define KWWidgets_EXPORT #endif #ifdef __cplusplus #define KWWidgets_EXTERN extern "C" #else #define KWWidgets_EXTERN extern #endif #endif kwwidgets-1.0.0~cvs20100930/vtkKWRadioButtonSet.h0000644000175000017500000000504410345573407021142 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWRadioButtonSet.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWRadioButtonSet - a concrete set of vtkKWRadioButton // .SECTION Description // A composite widget to conveniently store, allocate, create and pack a // set of vtkKWRadioButton. // Each vtkKWRadioButton is created, removed or queried based // on a unique ID provided by the user (ids are *not* handled by the class // since it is likely that they will be defined as enum's or #define by // the user for easier retrieval). // As a subclass of vtkKWWidgetSet, it inherits methods to set the widgets // visibility individually, set the layout parameters, and query each widget. // Widgets are packed (gridded) in the order they were added. // .SECTION See Also // vtkKWWidgetSet #ifndef __vtkKWRadioButtonSet_h #define __vtkKWRadioButtonSet_h #include "vtkKWWidgetSet.h" class vtkKWRadioButton; class KWWidgets_EXPORT vtkKWRadioButtonSet : public vtkKWWidgetSet { public: static vtkKWRadioButtonSet* New(); vtkTypeRevisionMacro(vtkKWRadioButtonSet,vtkKWWidgetSet); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Add a vtkKWRadioButton to the set. // The id has to be unique among the set. // Return a pointer to the vtkKWRadioButton, or NULL on error. virtual vtkKWRadioButton* AddWidget(int id); // Description: // Insert a vtkKWRadioButton at a specific position in the set. // The id has to be unique among the set. // Return a pointer to the vtkKWRadioButton, or NULL on error. virtual vtkKWRadioButton* InsertWidget(int id, int pos); // Description: // Get a vtkKWRadioButton from the set, given its unique id. // Return a pointer to the vtkKWRadioButton, or NULL on error. virtual vtkKWRadioButton* GetWidget(int id); protected: vtkKWRadioButtonSet() {}; ~vtkKWRadioButtonSet() {}; // Helper methods virtual vtkKWWidget* AllocateAndCreateWidget(); virtual vtkKWWidget* InsertWidgetInternal(int id, int pos); private: vtkKWRadioButtonSet(const vtkKWRadioButtonSet&); // Not implemented void operator=(const vtkKWRadioButtonSet&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWPushButton.h0000644000175000017500000002636510546555550020362 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWPushButton.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWPushButton - push button widget // .SECTION Description // A simple widget that represents a push button. #ifndef __vtkKWPushButton_h #define __vtkKWPushButton_h #include "vtkKWCoreWidget.h" class vtkKWIcon; class KWWidgets_EXPORT vtkKWPushButton : public vtkKWCoreWidget { public: static vtkKWPushButton* New(); vtkTypeRevisionMacro(vtkKWPushButton,vtkKWCoreWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set the contents label. virtual void SetText(const char *label); virtual char *GetText(); // Description: // Set/Get the text width (in chars if the button has a text contents, or // pixels if it has an image contents). virtual void SetWidth(int width); virtual int GetWidth(); // Description: // Set/Get the text height (in chars if the button has a text contents, or // pixels if it has an image contents). virtual void SetHeight(int height); virtual int GetHeight(); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when button is pressed. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetCommand(vtkObject *object, const char *method); // Description: // Events. The InvokedEvent is triggered when the button is pressed. //BTX enum { InvokedEvent = 10000 }; //ETX // Description: // Set/Get the background color of the widget virtual void GetBackgroundColor(double *r, double *g, double *b); virtual double* GetBackgroundColor(); virtual void SetBackgroundColor(double r, double g, double b); virtual void SetBackgroundColor(double rgb[3]) { this->SetBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget virtual void GetForegroundColor(double *r, double *g, double *b); virtual double* GetForegroundColor(); virtual void SetForegroundColor(double r, double g, double b); virtual void SetForegroundColor(double rgb[3]) { this->SetForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the highlight thickness, a non-negative value indicating the // width of the highlight rectangle to draw around the outside of the // widget when it has the input focus. virtual void SetHighlightThickness(int); virtual int GetHighlightThickness(); // Description: // Set/Get the active background color of // the widget. An element (a widget or portion of a widget) is active // if the mouse cursor is positioned over the element and pressing a mouse // button will cause some action to occur. virtual void GetActiveBackgroundColor(double *r, double *g, double *b); virtual double* GetActiveBackgroundColor(); virtual void SetActiveBackgroundColor(double r, double g, double b); virtual void SetActiveBackgroundColor(double rgb[3]) { this->SetActiveBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the active foreground color of the widget. An element // (a widget or portion of a widget) is active if the mouse cursor is // positioned over the element and pressing a mouse button will cause some // action to occur. virtual void GetActiveForegroundColor(double *r, double *g, double *b); virtual double* GetActiveForegroundColor(); virtual void SetActiveForegroundColor(double r, double g, double b); virtual void SetActiveForegroundColor(double rgb[3]) { this->SetActiveForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget when it is disabled. virtual void GetDisabledForegroundColor(double *r, double *g, double *b); virtual double* GetDisabledForegroundColor(); virtual void SetDisabledForegroundColor(double r, double g, double b); virtual void SetDisabledForegroundColor(double rgb[3]) { this->SetDisabledForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the border width, a non-negative value indicating the width of // the 3-D border to draw around the outside of the widget (if such a border // is being drawn; the Relief option typically determines this). virtual void SetBorderWidth(int); virtual int GetBorderWidth(); // Description: // Set/Get the 3-D effect desired for the widget. // The value indicates how the interior of the widget should appear // relative to its exterior. // Valid constants can be found in vtkKWOptions::ReliefType. virtual void SetRelief(int); virtual int GetRelief(); virtual void SetReliefToRaised(); virtual void SetReliefToSunken(); virtual void SetReliefToFlat(); virtual void SetReliefToRidge(); virtual void SetReliefToSolid(); virtual void SetReliefToGroove(); // Description: // Set/Get the padding that will be applied around each widget (in pixels). // Specifies a non-negative value indicating how much extra space to request // for the widget in the X and Y-direction. When computing how large a // window it needs, the widget will add this amount to the width it would // normally need (as determined by the width of the things displayed // in the widget); if the geometry manager can satisfy this request, the // widget will end up with extra internal space around what it displays // inside. virtual void SetPadX(int); virtual int GetPadX(); virtual void SetPadY(int); virtual int GetPadY(); // Description: // Set/Get the anchoring. // Specifies how the information in a widget (e.g. text or a bitmap) is to // be displayed in the widget. // Valid constants can be found in vtkKWOptions::AnchorType. virtual void SetAnchor(int); virtual int GetAnchor(); virtual void SetAnchorToNorth(); virtual void SetAnchorToNorthEast(); virtual void SetAnchorToEast(); virtual void SetAnchorToSouthEast(); virtual void SetAnchorToSouth(); virtual void SetAnchorToSouthWest(); virtual void SetAnchorToWest(); virtual void SetAnchorToNorthWest(); virtual void SetAnchorToCenter(); // Description: // Set/Get the 3-D effect desired for the widget. // Specifies an alternative relief for the button, to be used when the mouse // cursor is over the widget. This option can be used to make toolbar // buttons, by configuring SetRelief to Flat and OverRelief to Raised. // Valid constants can be found in vtkKWOptions::ReliefType. // If the value of this option is None, then no alternative relief is used // when the mouse cursor is over the checkbutton. virtual void SetOverRelief(int); virtual int GetOverRelief(); virtual void SetOverReliefToRaised(); virtual void SetOverReliefToSunken(); virtual void SetOverReliefToFlat(); virtual void SetOverReliefToRidge(); virtual void SetOverReliefToSolid(); virtual void SetOverReliefToGroove(); virtual void SetOverReliefToNone(); // Description: // Specifies the font to use when drawing text inside the widget. // You can use predefined font names (e.g. 'system'), or you can specify // a set of font attributes with a platform-independent name, for example, // 'times 12 bold'. In this example, the font is specified with a three // element list: the first element is the font family, the second is the // size, the third is a list of style parameters (normal, bold, roman, // italic, underline, overstrike). Example: 'times 12 {bold italic}'. // The Times, Courier and Helvetica font families are guaranteed to exist // and will be matched to the corresponding (closest) font on your system. // If you are familiar with the X font names specification, you can also // describe the font that way (say, '*times-medium-r-*-*-12*'). virtual void SetFont(const char *font); virtual const char* GetFont(); // Description: // Specifies an image to display in the widget. Typically, if the image // is specified then it overrides other options that specify a bitmap or // textual value to display in the widget. Invoke vtkKWWidget's // SetConfigurationOption("-image", imagename) to use a specific // pre-existing Tk image, or call one of the following functions: // The SetImageToPredefinedIcon method accepts an index to one of the // predefined icon listed in vtkKWIcon. // The SetImageToPixels method sets the image using pixel data. It expects // a pointer to the pixels and the structure of the image, i.e. its width, // height and the pixel_size (how many bytes per pixel, say 3 for RGB, or // 1 for grayscale). If buffer_length = 0, it is computed automatically // from the previous parameters. If it is not, it will most likely indicate // that the buffer has been encoded using base64 and/or zlib. // If pixel_size > 3 (i.e. RGBA), the image is blend the with background // color of the widget. // Check the SetCompoundMode method if you want to display both the // image and the label at the same time. virtual void SetImageToIcon(vtkKWIcon *icon); virtual void SetImageToPredefinedIcon(int icon_index); virtual void SetImageToPixels( const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length = 0); // Description: // Specifies if the widget should display text and bitmaps/images at the // same time, and if so, where the bitmap/image should be placed relative // to the text. // Valid constants can be found in vtkKWOptions::CompoundModeType. // The (default) value CompoundModeNone specifies that the bitmap or image // should (if defined) be displayed instead of the text. virtual void SetCompoundMode(int); virtual int GetCompoundMode(); virtual void SetCompoundModeToNone(); virtual void SetCompoundModeToLeft(); virtual void SetCompoundModeToCenter(); virtual void SetCompoundModeToRight(); virtual void SetCompoundModeToTop(); virtual void SetCompoundModeToBottom(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void CommandCallback(); protected: vtkKWPushButton(); ~vtkKWPushButton(); // Description: // Create the widget. virtual void CreateWidget(); vtkSetStringMacro(ButtonText); char* ButtonText; char *Command; virtual void InvokeCommand(); private: vtkKWPushButton(const vtkKWPushButton&); // Not implemented void operator=(const vtkKWPushButton&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWWindow.cxx0000644000175000017500000013004611075753465020064 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWindow.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWWindow.h" #include "vtkKWOptions.h" #include "vtkKWApplication.h" #include "vtkKWApplicationSettingsInterface.h" #include "vtkKWFrame.h" #include "vtkKWFrameWithLabel.h" #include "vtkKWInternationalization.h" #include "vtkKWIcon.h" #include "vtkKWLabel.h" #include "vtkKWMenu.h" #include "vtkKWMessageDialog.h" #include "vtkKWNotebook.h" #include "vtkKWRegistryHelper.h" #include "vtkKWSeparator.h" #include "vtkKWSplitFrame.h" #include "vtkKWToolbar.h" #include "vtkKWToolbarSet.h" #include "vtkKWUserInterfaceManagerDialog.h" #include "vtkKWUserInterfaceManagerNotebook.h" #include "vtkObjectFactory.h" #include #include vtkCxxRevisionMacro(vtkKWWindow, "$Revision: 1.297 $"); //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWWindow ); //---------------------------------------------------------------------------- vtkKWWindow::vtkKWWindow() { this->MainSplitFrame = vtkKWSplitFrame::New(); this->MainSplitFrame->SetFrame1MinimumSize(250); this->SecondarySplitFrame = vtkKWSplitFrame::New(); this->PanelLayout = vtkKWWindow::PanelLayoutSecondaryBelowView; // Main Panel this->MainNotebook = NULL; this->MainUserInterfaceManager = NULL; // Secondary panel this->SecondaryNotebook = NULL; this->SecondaryUserInterfaceManager = NULL; // View panel this->ViewNotebook = NULL; this->ViewUserInterfaceManager = NULL; // Toolbar set this->SecondaryToolbarSet = NULL; // Application Settings this->ApplicationSettingsInterface = NULL; this->ApplicationSettingsUserInterfaceManager = NULL; this->StatusFramePosition = vtkKWWindow::StatusFramePositionWindow; // Some constants this->HideMainPanelMenuLabel = vtksys::SystemTools::DuplicateString( ks_("Menu|Window|Hide &Main Panel")); this->ShowMainPanelMenuLabel = vtksys::SystemTools::DuplicateString( ks_("Menu|Window|Show &Main Panel")); this->HideSecondaryPanelMenuLabel = vtksys::SystemTools::DuplicateString( ks_("Menu|Window|Hide &Bottom Panel")); this->ShowSecondaryPanelMenuLabel = vtksys::SystemTools::DuplicateString( ks_("Menu|Window|Show &Bottom Panel")); this->TclInteractorMenuLabel = vtksys::SystemTools::DuplicateString( ks_("Menu|Window|&Tcl Interactor")); this->LogDialogMenuLabel = vtksys::SystemTools::DuplicateString( ks_("Menu|Window|&Error Log")); this->DefaultViewPanelName = vtksys::SystemTools::DuplicateString("View"); this->MainPanelSizeRegKey = vtksys::SystemTools::DuplicateString("MainPanelSize"); this->MainPanelVisibilityRegKey = vtksys::SystemTools::DuplicateString("MainPanelVisibility"); this->MainPanelVisibilityKeyAccelerator = vtksys::SystemTools::DuplicateString("F5"); this->SecondaryPanelSizeRegKey = vtksys::SystemTools::DuplicateString("SecondaryPanelSize"); this->SecondaryPanelVisibilityRegKey = vtksys::SystemTools::DuplicateString("SecondaryPanelVisibility"); this->SecondaryPanelVisibilityKeyAccelerator = vtksys::SystemTools::DuplicateString("F6"); this->ViewPanelPositionRegKey = vtksys::SystemTools::DuplicateString("ViewPanelPosition"); } //---------------------------------------------------------------------------- vtkKWWindow::~vtkKWWindow() { this->PrepareForDelete(); if (this->MainSplitFrame) { this->MainSplitFrame->Delete(); this->MainSplitFrame = NULL; } if (this->MainNotebook) { this->MainNotebook->Delete(); this->MainNotebook = NULL; } if (this->MainUserInterfaceManager) { this->MainUserInterfaceManager->Delete(); this->MainUserInterfaceManager = NULL; } if (this->SecondarySplitFrame) { this->SecondarySplitFrame->Delete(); this->SecondarySplitFrame = NULL; } if (this->SecondaryNotebook) { this->SecondaryNotebook->Delete(); this->SecondaryNotebook = NULL; } if (this->SecondaryUserInterfaceManager) { this->SecondaryUserInterfaceManager->Delete(); this->SecondaryUserInterfaceManager = NULL; } if (this->ViewNotebook) { this->ViewNotebook->Delete(); this->ViewNotebook = NULL; } if (this->ViewUserInterfaceManager) { this->ViewUserInterfaceManager->Delete(); this->ViewUserInterfaceManager = NULL; } if (this->SecondaryToolbarSet) { this->SecondaryToolbarSet->Delete(); this->SecondaryToolbarSet = NULL; } if (this->ApplicationSettingsUserInterfaceManager) { this->ApplicationSettingsUserInterfaceManager->Delete(); this->ApplicationSettingsUserInterfaceManager = NULL; } if (this->ApplicationSettingsInterface) { this->ApplicationSettingsInterface->Delete(); this->ApplicationSettingsInterface = NULL; } this->SetMainPanelSizeRegKey(NULL); this->SetMainPanelVisibilityRegKey(NULL); this->SetMainPanelVisibilityKeyAccelerator(NULL); this->SetHideMainPanelMenuLabel(NULL); this->SetShowMainPanelMenuLabel(NULL); this->SetSecondaryPanelSizeRegKey(NULL); this->SetSecondaryPanelVisibilityRegKey(NULL); this->SetSecondaryPanelVisibilityKeyAccelerator(NULL); this->SetHideSecondaryPanelMenuLabel(NULL); this->SetShowSecondaryPanelMenuLabel(NULL); this->SetDefaultViewPanelName(NULL); this->SetTclInteractorMenuLabel(NULL); this->SetViewPanelPositionRegKey(NULL); this->SetLogDialogMenuLabel(NULL); } //---------------------------------------------------------------------------- void vtkKWWindow::PrepareForDelete() { if (this->MainUserInterfaceManager) { this->MainUserInterfaceManager->RemoveAllPanels(); } if (this->SecondaryUserInterfaceManager) { this->SecondaryUserInterfaceManager->RemoveAllPanels(); } if (this->ViewUserInterfaceManager) { this->ViewUserInterfaceManager->RemoveAllPanels(); } if (this->ApplicationSettingsUserInterfaceManager) { this->ApplicationSettingsUserInterfaceManager->RemoveAllPanels(); } if (this->SecondaryToolbarSet) { this->SecondaryToolbarSet->SetToolbarVisibilityChangedCommand( NULL, NULL); this->SecondaryToolbarSet->SetNumberOfToolbarsChangedCommand( NULL, NULL); this->SecondaryToolbarSet->RemoveAllToolbars(); } } //---------------------------------------------------------------------------- void vtkKWWindow::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro("class already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Main and Secondary split frames this->SecondarySplitFrame->SetSeparatorSize( this->MainSplitFrame->GetSeparatorSize()); this->SecondarySplitFrame->SetOrientationToVertical(); this->MainSplitFrame->SetExpandableFrameToFrame2(); if (this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowView) { this->MainSplitFrame->SetParent(this->Superclass::GetViewFrame()); this->MainSplitFrame->Create(); this->SecondarySplitFrame->SetParent(this->MainSplitFrame->GetFrame2()); this->SecondarySplitFrame->Create(); } else if (this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowMain) { this->MainSplitFrame->SetParent(this->Superclass::GetViewFrame()); this->MainSplitFrame->Create(); this->SecondarySplitFrame->SetParent(this->MainSplitFrame->GetFrame1()); this->SecondarySplitFrame->Create(); } else { this->SecondarySplitFrame->SetParent(this->Superclass::GetViewFrame()); this->SecondarySplitFrame->Create(); this->MainSplitFrame->SetParent(this->SecondarySplitFrame->GetFrame2()); this->MainSplitFrame->Create(); } this->Script("pack %s -side top -fill both -expand t", this->MainSplitFrame->GetWidgetName()); this->Script("pack %s -side top -fill both -expand t", this->SecondarySplitFrame->GetWidgetName()); this->AddCallbackCommandObservers(); } //---------------------------------------------------------------------------- void vtkKWWindow::PopulateWindowMenu() { this->Superclass::PopulateWindowMenu(); int tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); int show_icons = (tcl_major > 8 || (tcl_major == 8 && tcl_minor >= 5)); int idx; vtkKWMenu *menu = this->GetWindowMenu(); vtksys_stl::string cmd; idx = menu->AddCommand(this->GetHideMainPanelMenuLabel(), this, "MainPanelVisibilityCallback"); menu->SetItemAccelerator( idx, this->GetMainPanelVisibilityKeyAccelerator()); menu->SetBindingForItemAccelerator(idx, menu->GetParentTopLevel()); if (show_icons) { menu->SetItemImageToPredefinedIcon( idx, vtkKWIcon::IconNuvola16x16ActionsViewRight); menu->SetItemCompoundModeToLeft(idx); } idx = menu->AddCommand(this->GetHideSecondaryPanelMenuLabel(), this, "SecondaryPanelVisibilityCallback"); menu->SetItemAccelerator( idx, this->GetSecondaryPanelVisibilityKeyAccelerator()); menu->SetBindingForItemAccelerator(idx, menu->GetParentTopLevel()); if (show_icons) { menu->SetItemImageToPredefinedIcon( idx, vtkKWIcon::IconNuvola16x16ActionsViewBottom); menu->SetItemCompoundModeToLeft(idx); } menu->AddSeparator(); cmd = "DisplayLogDialog {"; cmd += this->GetTclName(); cmd += "}"; idx = menu->AddCommand( this->GetLogDialogMenuLabel(), this->GetApplication(), cmd.c_str()); menu->SetItemHelpString( idx, k_("Display the log window")); menu->SetItemAccelerator(idx, "Ctrl+Alt+E"); menu->SetBindingForItemAccelerator(idx, menu->GetParentTopLevel()); if (show_icons) { menu->SetItemImageToPredefinedIcon( idx, vtkKWIcon::IconNuvola16x16ActionsNo); menu->SetItemCompoundModeToLeft(idx); } if (!this->GetApplication()->GetReleaseMode()) { menu->AddSeparator(); idx = menu->AddCommand( this->GetTclInteractorMenuLabel(), this, "DisplayTclInteractor"); menu->SetItemHelpString( idx, k_("Display a prompt to interact with the Tcl engine")); menu->SetItemAccelerator(idx, "Ctrl+T"); menu->SetBindingForItemAccelerator(idx, menu->GetParentTopLevel()); if (show_icons) { menu->SetItemImageToPredefinedIcon( idx, vtkKWIcon::IconNuvola16x16AppsBug); menu->SetItemCompoundModeToLeft(idx); } } } //---------------------------------------------------------------------------- void vtkKWWindow::PopulateViewMenu() { this->Superclass::PopulateViewMenu(); int tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); int show_icons = (tcl_major > 8 || (tcl_major == 8 && tcl_minor >= 5)); int idx; vtkKWMenu *menu = this->GetViewMenu(); vtksys_stl::string cmd; // Menu : View : Application Settings idx = this->GetViewMenuInsertPosition(); cmd = "ShowApplicationSettingsUserInterface {"; cmd += this->GetApplicationSettingsInterface()->GetName(); cmd += "}"; idx = menu->InsertCommand( idx, this->GetApplicationSettingsInterface()->GetName(), this, cmd.c_str()); menu->SetItemAccelerator(idx, "F2"); menu->SetBindingForItemAccelerator(idx, menu->GetParentTopLevel()); if (show_icons) { menu->SetItemImageToPredefinedIcon( idx, vtkKWIcon::IconNuvola16x16ActionsConfigure); menu->SetItemCompoundModeToLeft(idx); } } //---------------------------------------------------------------------------- void vtkKWWindow::Pack() { if (!this->IsCreated()) { return; } this->Superclass::Pack(); // Status frame and status frame separator // Override the parent if (this->StatusFrame && this->StatusFrame->IsCreated()) { vtkKWWidget *in = this; switch (this->StatusFramePosition) { case vtkKWWindow::StatusFramePositionMainPanel: in = this->GetMainPanelFrame(); break; case vtkKWWindow::StatusFramePositionSecondaryPanel: in = this->GetSecondaryPanelFrame(); break; case vtkKWWindow::StatusFramePositionViewPanel: in = this->GetViewPanelFrame(); break; case vtkKWWindow::StatusFramePositionLeftOfDivider: if (this->MainSplitFrame) { in = this->MainSplitFrame->GetFrame1(); } break; case vtkKWWindow::StatusFramePositionRightOfDivider: if (this->MainSplitFrame) { in = this->MainSplitFrame->GetFrame2(); } break; case vtkKWWindow::StatusFramePositionWindow: default: break; } if (this->StatusFrameVisibility && in && in->IsCreated()) { this->Script("pack %s -side bottom -fill x -pady 0 -in %s", this->StatusFrame->GetWidgetName(), in->GetWidgetName()); if (this->StatusFrameSeparator && this->StatusFrameSeparator->IsCreated()) { this->Script("pack %s -side bottom -fill x -pady 2 -in %s", this->StatusFrameSeparator->GetWidgetName(), in->GetWidgetName()); } } } } //---------------------------------------------------------------------------- vtkKWToolbarSet* vtkKWWindow::GetSecondaryToolbarSet() { if (!this->SecondaryToolbarSet) { this->SecondaryToolbarSet = vtkKWToolbarSet::New(); } if (!this->SecondaryToolbarSet->IsCreated() && this->IsCreated()) { this->SecondaryToolbarSet->SetParent(this->MainSplitFrame->GetFrame2()); this->SecondaryToolbarSet->Create(); this->SecondaryToolbarSet->TopSeparatorVisibilityOn(); this->SecondaryToolbarSet->BottomSeparatorVisibilityOff(); this->SecondaryToolbarSet->SynchronizeToolbarsVisibilityWithRegistryOn(); this->SecondaryToolbarSet->SetToolbarVisibilityChangedCommand( this, "ToolbarVisibilityChangedCallback"); this->SecondaryToolbarSet->SetNumberOfToolbarsChangedCommand( this, "NumberOfToolbarsChangedCallback"); vtksys_stl::string after; if (this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowView) { after = "-after "; after += this->SecondarySplitFrame->GetWidgetName(); } else if (this->ViewNotebook) { after = "-after "; after += this->ViewNotebook->GetWidgetName(); } this->Script( "pack %s -padx 0 -pady 0 -side bottom -fill x -expand no %s", this->SecondaryToolbarSet->GetWidgetName(), after.c_str()); } return this->SecondaryToolbarSet; } //---------------------------------------------------------------------------- void vtkKWWindow::SetViewPanelPosition(int val) { if (val < vtkKWWindow::ViewPanelPositionLeft) { val = vtkKWWindow::ViewPanelPositionLeft; } if (val > vtkKWWindow::ViewPanelPositionRight) { val = vtkKWWindow::ViewPanelPositionRight; } if (this->GetViewPanelPosition() == val) { return; } if (this->MainSplitFrame) { if (val == vtkKWWindow::ViewPanelPositionRight) { this->MainSplitFrame->SetFrameLayoutToDefault(); } else { this->MainSplitFrame->SetFrameLayoutToSwapped(); } } // Update the UI (the app settings reflect this change) this->Update(); } //---------------------------------------------------------------------------- int vtkKWWindow::GetViewPanelPosition() { if (this->MainSplitFrame) { if (this->MainSplitFrame->GetFrameLayout() == vtkKWSplitFrame::FrameLayoutDefault) { return vtkKWWindow::ViewPanelPositionRight; } else { return vtkKWWindow::ViewPanelPositionLeft; } } return vtkKWWindow::ViewPanelPositionRight; } //---------------------------------------------------------------------------- vtkKWApplicationSettingsInterface* vtkKWWindow::GetApplicationSettingsInterface() { // If not created, create the application settings interface, connect it // to the current window, and manage it with the app settings // interface manager. // Subclasses that will add more settings will likely to create a subclass // of vtkKWApplicationSettingsInterface and override this function so that // it instantiates that subclass instead vtkKWApplicationSettingsInterface. if (!this->ApplicationSettingsInterface) { this->ApplicationSettingsInterface = vtkKWApplicationSettingsInterface::New(); this->ApplicationSettingsInterface->SetWindow(this); this->ApplicationSettingsInterface->SetUserInterfaceManager( this->GetApplicationSettingsUserInterfaceManager()); } return this->ApplicationSettingsInterface; } //---------------------------------------------------------------------------- vtkKWUserInterfaceManager* vtkKWWindow::GetApplicationSettingsUserInterfaceManager() { if (!this->ApplicationSettingsUserInterfaceManager) { this->ApplicationSettingsUserInterfaceManager = vtkKWUserInterfaceManagerDialog::New(); vtkKWTopLevel *toplevel = this->ApplicationSettingsUserInterfaceManager->GetTopLevel(); toplevel->SetMasterWindow(this); toplevel->SetTitle( ks_("Application Settings|Title|Application Settings")); this->ApplicationSettingsUserInterfaceManager->PageNodeVisibilityOff(); } if (this->IsCreated() && !this->ApplicationSettingsUserInterfaceManager->IsCreated()) { this->ApplicationSettingsUserInterfaceManager->Create(); } return this->ApplicationSettingsUserInterfaceManager; } //---------------------------------------------------------------------------- void vtkKWWindow::ShowApplicationSettingsUserInterface(const char *name) { if (this->GetApplicationSettingsUserInterfaceManager()) { this->ShowApplicationSettingsUserInterface( this->GetApplicationSettingsUserInterfaceManager()->GetPanel(name)); } } //---------------------------------------------------------------------------- void vtkKWWindow::ShowApplicationSettingsUserInterface( vtkKWUserInterfacePanel *panel) { if (!panel) { return; } vtkKWUserInterfaceManager *uim = this->GetApplicationSettingsUserInterfaceManager(); if (!uim || !uim->HasPanel(panel)) { vtkErrorMacro( "Sorry, the user interface panel you are trying to display (" << panel->GetName() << ") is not managed by the Application Settings " "User Interface Manager"); return; } panel->Raise(); } //---------------------------------------------------------------------------- vtkKWNotebook* vtkKWWindow::GetMainNotebook() { if (!this->MainNotebook) { this->MainNotebook = vtkKWNotebook::New(); this->MainNotebook->PagesCanBePinnedOn(); this->MainNotebook->EnablePageTabContextMenuOn(); this->MainNotebook->AlwaysShowTabsOn(); } if (!this->MainNotebook->IsCreated() && this->IsCreated()) { this->MainNotebook->SetParent(this->GetMainPanelFrame()); this->MainNotebook->Create(); this->Script("pack %s -pady 0 -padx 0 -fill both -expand yes -anchor n", this->MainNotebook->GetWidgetName()); } return this->MainNotebook; } //---------------------------------------------------------------------------- int vtkKWWindow::HasMainUserInterfaceManager() { return this->MainUserInterfaceManager ? 1 : 0; } //---------------------------------------------------------------------------- vtkKWUserInterfaceManager* vtkKWWindow::GetMainUserInterfaceManager() { if (!this->MainUserInterfaceManager) { this->MainUserInterfaceManager = vtkKWUserInterfaceManagerNotebook::New(); this->MainUserInterfaceManager->SetNotebook(this->GetMainNotebook()); this->MainUserInterfaceManager->EnableDragAndDropOn(); this->GetMainNotebook()->ShowIconsOn(); } if (!this->MainUserInterfaceManager->IsCreated() && this->IsCreated()) { this->MainUserInterfaceManager->Create(); } return this->MainUserInterfaceManager; } //---------------------------------------------------------------------------- void vtkKWWindow::ShowMainUserInterface(const char *name) { if (this->GetMainUserInterfaceManager()) { this->ShowMainUserInterface( this->GetMainUserInterfaceManager()->GetPanel(name)); } } //---------------------------------------------------------------------------- void vtkKWWindow::ShowMainUserInterface(vtkKWUserInterfacePanel *panel) { if (!panel) { return; } vtkKWUserInterfaceManager *uim = this->GetMainUserInterfaceManager(); if (!uim || !uim->HasPanel(panel)) { vtkErrorMacro( "Sorry, the user interface panel you are trying to display (" << panel->GetName() << ") is not managed by the Main " "User Interface Manager"); return; } this->SetMainPanelVisibility(1); if (!panel->Raise()) { vtksys_ios::ostringstream msg; msg << "The panel you are trying to access could not be displayed " << "properly. Please make sure there is enough room in the notebook " << "to bring up this part of the interface."; if (this->MainNotebook && this->MainNotebook->GetShowOnlyMostRecentPages() && this->MainNotebook->GetPagesCanBePinned()) { msg << " This may happen if you displayed " << this->MainNotebook->GetNumberOfMostRecentPages() << " notebook pages " << "at the same time and pinned/locked all of them. In that case, " << "try to hide or unlock a notebook page first."; } vtkKWMessageDialog::PopupMessage( this->GetApplication(), this, "User Interface Warning", msg.str().c_str(), vtkKWMessageDialog::WarningIcon); } } //---------------------------------------------------------------------------- vtkKWFrame* vtkKWWindow::GetMainPanelFrame() { if (this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowView || this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowMainAndView) { if (this->MainSplitFrame) { return this->MainSplitFrame->GetFrame1(); } } else if (this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowMain) { if (this->SecondarySplitFrame) { return this->SecondarySplitFrame->GetFrame2(); } } return NULL; } //---------------------------------------------------------------------------- int vtkKWWindow::GetMainPanelVisibility() { if (this->MainSplitFrame) { return this->MainSplitFrame->GetFrame1Visibility(); } return 0; } //---------------------------------------------------------------------------- void vtkKWWindow::SetMainPanelVisibility(int arg) { if (arg == this->GetMainPanelVisibility()) { return; } if (this->MainSplitFrame) { this->MainSplitFrame->SetFrame1Visibility(arg); } this->UpdateMenuState(); } //---------------------------------------------------------------------------- void vtkKWWindow::MainPanelVisibilityCallback() { this->SetMainPanelVisibility(!this->GetMainPanelVisibility()); this->UpdateMenuState(); } //---------------------------------------------------------------------------- vtkKWNotebook* vtkKWWindow::GetSecondaryNotebook() { if (!this->SecondaryNotebook) { this->SecondaryNotebook = vtkKWNotebook::New(); this->SecondaryNotebook->PagesCanBePinnedOn(); this->SecondaryNotebook->EnablePageTabContextMenuOn(); this->SecondaryNotebook->AlwaysShowTabsOn(); } if (!this->SecondaryNotebook->IsCreated() && this->IsCreated()) { this->SecondaryNotebook->SetParent(this->GetSecondaryPanelFrame()); this->SecondaryNotebook->Create(); this->Script("pack %s -pady 0 -padx 0 -fill both -expand yes -anchor n", this->SecondaryNotebook->GetWidgetName()); } return this->SecondaryNotebook; } //---------------------------------------------------------------------------- int vtkKWWindow::HasSecondaryUserInterfaceManager() { return this->SecondaryUserInterfaceManager ? 1 : 0; } //---------------------------------------------------------------------------- vtkKWUserInterfaceManager* vtkKWWindow::GetSecondaryUserInterfaceManager() { if (!this->SecondaryUserInterfaceManager) { this->SecondaryUserInterfaceManager = vtkKWUserInterfaceManagerNotebook::New(); this->SecondaryUserInterfaceManager->SetNotebook( this->GetSecondaryNotebook()); this->SecondaryUserInterfaceManager->EnableDragAndDropOn(); } if (!this->SecondaryUserInterfaceManager->IsCreated() && this->IsCreated()) { this->SecondaryUserInterfaceManager->Create(); } return this->SecondaryUserInterfaceManager; } //---------------------------------------------------------------------------- void vtkKWWindow::ShowSecondaryUserInterface(const char *name) { if (this->HasSecondaryUserInterfaceManager()) { this->ShowSecondaryUserInterface( this->GetSecondaryUserInterfaceManager()->GetPanel(name)); } } //---------------------------------------------------------------------------- void vtkKWWindow::ShowSecondaryUserInterface(vtkKWUserInterfacePanel *panel) { if (!panel) { return; } vtkKWUserInterfaceManager *uim = this->GetSecondaryUserInterfaceManager(); if (!uim || !uim->HasPanel(panel)) { vtkErrorMacro( "Sorry, the user interface panel you are trying to display (" << panel->GetName() << ") is not managed by the Secondary " "User Interface Manager"); return; } this->SetSecondaryPanelVisibility(1); if (!panel->Raise()) { vtksys_stl::string msg; msg = "The panel you are trying to access could not be displayed " "properly. Please make sure there is enough room in the notebook " "to bring up this part of the interface."; if (this->SecondaryNotebook && this->SecondaryNotebook->GetShowOnlyMostRecentPages() && this->SecondaryNotebook->GetPagesCanBePinned()) { msg += " This may happen if you displayed "; msg += this->SecondaryNotebook->GetNumberOfMostRecentPages(); msg += " notebook pages " "at the same time and pinned/locked all of them. In that case, " "try to hide or unlock a notebook page first."; } vtkKWMessageDialog::PopupMessage( this->GetApplication(), this, "User Interface Warning", msg.c_str(), vtkKWMessageDialog::WarningIcon); } } //--------------------------------------------------------------------------- vtkKWFrame* vtkKWWindow::GetSecondaryPanelFrame() { return this->SecondarySplitFrame ? this->SecondarySplitFrame->GetFrame1() : NULL; } //---------------------------------------------------------------------------- int vtkKWWindow::GetSecondaryPanelVisibility() { return (this->SecondarySplitFrame && this->SecondarySplitFrame->GetFrame1Visibility() ? 1 : 0); } //---------------------------------------------------------------------------- void vtkKWWindow::SetSecondaryPanelVisibility(int arg) { if (arg == this->GetSecondaryPanelVisibility()) { return; } if (this->SecondarySplitFrame) { this->SecondarySplitFrame->SetFrame1Visibility(arg); } this->UpdateMenuState(); } //---------------------------------------------------------------------------- void vtkKWWindow::SecondaryPanelVisibilityCallback() { this->SetSecondaryPanelVisibility(!this->GetSecondaryPanelVisibility()); } //---------------------------------------------------------------------------- vtkKWFrame* vtkKWWindow::GetViewFrame() { vtkKWUserInterfaceManager *uim = this->GetViewUserInterfaceManager(); if (uim) { vtkKWUserInterfacePanel *panel = uim->GetPanel(this->GetDefaultViewPanelName()); if (panel) { return vtkKWFrame::SafeDownCast(panel->GetPageWidget(panel->GetName())); } } return NULL; } //---------------------------------------------------------------------------- vtkKWFrame* vtkKWWindow::GetViewPanelFrame() { if (this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowView) { return this->SecondarySplitFrame->GetFrame2(); } else { if (this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowMain || this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowMainAndView) { return this->MainSplitFrame->GetFrame2(); } } return NULL; } //---------------------------------------------------------------------------- vtkKWNotebook* vtkKWWindow::GetViewNotebook() { if (!this->ViewNotebook) { this->ViewNotebook = vtkKWNotebook::New(); this->ViewNotebook->PagesCanBePinnedOn(); this->ViewNotebook->EnablePageTabContextMenuOn(); this->ViewNotebook->AlwaysShowTabsOff(); } if (!this->ViewNotebook->IsCreated() && this->IsCreated()) { this->ViewNotebook->SetParent(this->GetViewPanelFrame()); this->ViewNotebook->Create(); this->Script("pack %s -pady 0 -padx 0 -fill both -expand yes -anchor n", this->ViewNotebook->GetWidgetName()); } return this->ViewNotebook; } //---------------------------------------------------------------------------- int vtkKWWindow::HasViewUserInterfaceManager() { return this->ViewUserInterfaceManager ? 1 : 0; } //---------------------------------------------------------------------------- vtkKWUserInterfaceManager* vtkKWWindow::GetViewUserInterfaceManager() { if (!this->ViewUserInterfaceManager) { this->ViewUserInterfaceManager = vtkKWUserInterfaceManagerNotebook::New(); this->ViewUserInterfaceManager->SetNotebook( this->GetViewNotebook()); this->ViewUserInterfaceManager->EnableDragAndDropOn(); } if (!this->ViewUserInterfaceManager->IsCreated() && this->IsCreated()) { this->ViewUserInterfaceManager->Create(); // Also create a default page for the view vtkKWUserInterfacePanel *panel = vtkKWUserInterfacePanel::New(); panel->SetName(this->GetDefaultViewPanelName()); panel->SetUserInterfaceManager(this->ViewUserInterfaceManager); panel->Create(); panel->Delete(); panel->AddPage(panel->GetName(), NULL); } return this->ViewUserInterfaceManager; } //---------------------------------------------------------------------------- void vtkKWWindow::ShowViewUserInterface(const char *name) { if (this->GetViewUserInterfaceManager()) { this->ShowViewUserInterface( this->GetViewUserInterfaceManager()->GetPanel(name)); } } //---------------------------------------------------------------------------- void vtkKWWindow::ShowViewUserInterface(vtkKWUserInterfacePanel *panel) { if (!panel) { return; } vtkKWUserInterfaceManager *uim = this->GetViewUserInterfaceManager(); if (!uim || !uim->HasPanel(panel)) { vtkErrorMacro( "Sorry, the user interface panel you are trying to display (" << panel->GetName() << ") is not managed by the View " "User Interface Manager"); return; } this->SetSecondaryPanelVisibility(1); if (!panel->Raise()) { vtksys_stl::string msg; msg = "The panel you are trying to access could not be displayed " "properly. Please make sure there is enough room in the notebook " "to bring up this part of the interface."; if (this->ViewNotebook && this->ViewNotebook->GetShowOnlyMostRecentPages() && this->ViewNotebook->GetPagesCanBePinned()) { msg += " This may happen if you displayed "; msg += this->ViewNotebook->GetNumberOfMostRecentPages(); msg += " notebook pages " "at the same time and pinned/locked all of them. In that case, " "try to hide or unlock a notebook page first."; } vtkKWMessageDialog::PopupMessage( this->GetApplication(), this, "User Interface Warning", msg.c_str(), vtkKWMessageDialog::WarningIcon); } } //---------------------------------------------------------------------------- void vtkKWWindow::SetStatusFramePosition(int s) { if (s < vtkKWWindow::StatusFramePositionWindow) { s = vtkKWWindow::StatusFramePositionWindow; } else if (s > vtkKWWindow::StatusFramePositionRightOfDivider) { s = vtkKWWindow::StatusFramePositionRightOfDivider; } if (s == this->StatusFramePosition) { return; } this->StatusFramePosition = s; this->Modified(); this->Pack(); } //----------------------------------------------------------------------------- void vtkKWWindow::PrintSettingsCallback() { vtkKWApplicationSettingsInterface *app_settings = this->GetApplicationSettingsInterface(); vtkKWUserInterfaceManagerDialog *app_settings_uim = vtkKWUserInterfaceManagerDialog::SafeDownCast( this->GetApplicationSettingsUserInterfaceManager()); // If the UIM is a dialog one, try to reach the Print Settings section // directly, otherwise just use the regular UIM API to show the panel if (app_settings && app_settings_uim) { app_settings_uim->RaiseSection( app_settings, NULL, ks_("Application Settings|Print Settings")); } else { this->ShowApplicationSettingsUserInterface(app_settings); } } //---------------------------------------------------------------------------- void vtkKWWindow::SaveWindowGeometryToRegistry() { this->Superclass::SaveWindowGeometryToRegistry(); if (!this->IsCreated()) { return; } // Main panel this->GetApplication()->SetRegistryValue( 2, "Geometry", this->GetMainPanelSizeRegKey(), "%d", this->MainSplitFrame->GetFrame1Size()); this->GetApplication()->SetRegistryValue( 2, "Geometry", this->GetMainPanelVisibilityRegKey(), "%d", this->GetMainPanelVisibility()); // Secondary panel this->GetApplication()->SetRegistryValue( 2, "Geometry", this->GetSecondaryPanelSizeRegKey(), "%d", this->SecondarySplitFrame->GetFrame1Size()); this->GetApplication()->SetRegistryValue( 2, "Geometry", this->GetSecondaryPanelVisibilityRegKey(), "%d", this->GetSecondaryPanelVisibility()); // View panel const char *pos = NULL; if (this->GetViewPanelPosition() == vtkKWWindow::ViewPanelPositionLeft) { pos = "Left"; } else if (this->GetViewPanelPosition() == vtkKWWindow::ViewPanelPositionRight) { pos = "Right"; } if (pos) { this->GetApplication()->SetRegistryValue( 2, "Geometry", this->GetViewPanelPositionRegKey(), "%s", pos); } } //---------------------------------------------------------------------------- void vtkKWWindow::RestoreWindowGeometryFromRegistry() { this->Superclass::RestoreWindowGeometryFromRegistry(); if (!this->IsCreated()) { return; } // Main panel if (this->GetApplication()->HasRegistryValue( 2, "Geometry", this->GetMainPanelSizeRegKey())) { int reg_size = this->GetApplication()->GetIntRegistryValue( 2, "Geometry", this->GetMainPanelSizeRegKey()); if (reg_size >= this->MainSplitFrame->GetFrame1MinimumSize()) { this->MainSplitFrame->SetFrame1Size(reg_size); } } if (this->GetApplication()->HasRegistryValue( 2, "Geometry", this->GetMainPanelVisibilityRegKey())) { this->SetMainPanelVisibility( this->GetApplication()->GetIntRegistryValue( 2, "Geometry", this->GetMainPanelVisibilityRegKey())); } // Secondary panel if (this->GetApplication()->HasRegistryValue( 2, "Geometry", this->GetSecondaryPanelSizeRegKey())) { int reg_size = this->GetApplication()->GetIntRegistryValue( 2, "Geometry", this->GetSecondaryPanelSizeRegKey()); if (reg_size >= this->SecondarySplitFrame->GetFrame1MinimumSize()) { this->SecondarySplitFrame->SetFrame1Size(reg_size); } } if (this->GetApplication()->HasRegistryValue( 2, "Geometry", this->GetSecondaryPanelVisibilityRegKey())) { this->SetSecondaryPanelVisibility( this->GetApplication()->GetIntRegistryValue( 2, "Geometry", this->GetSecondaryPanelVisibilityRegKey())); } // View panel char pos[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; if (this->GetApplication()->GetRegistryValue( 2, "Geometry", this->GetViewPanelPositionRegKey(), pos)) { if (!strcmp(pos, "Left")) { this->SetViewPanelPositionToLeft(); } else if (!strcmp(pos, "Right")) { this->SetViewPanelPositionToRight(); } } } //---------------------------------------------------------------------------- void vtkKWWindow::Render() { } //----------------------------------------------------------------------------- void vtkKWWindow::NumberOfToolbarsChangedCallback() { this->Superclass::NumberOfToolbarsChangedCallback(); if (this->SecondaryToolbarSet) { this->SecondaryToolbarSet->PopulateToolbarsVisibilityMenu( this->GetToolbarsVisibilityMenu()); } } //---------------------------------------------------------------------------- void vtkKWWindow::ToolbarVisibilityChangedCallback(vtkKWToolbar *toolbar) { this->Superclass::ToolbarVisibilityChangedCallback(toolbar); if (this->SecondaryToolbarSet) { this->SecondaryToolbarSet->UpdateToolbarsVisibilityMenu( this->GetToolbarsVisibilityMenu()); } } //---------------------------------------------------------------------------- void vtkKWWindow::Update() { this->Superclass::Update(); // Update the whole interface if (this->HasMainUserInterfaceManager()) { // Redundant Update() here, since we call UpdateEnableState(), which as // a side effect will update each panel (see UpdateEnableState()) // this->GetMainUserInterfaceManager()->Update(); } } //----------------------------------------------------------------------------- void vtkKWWindow::UpdateToolbarState() { this->Superclass::UpdateToolbarState(); if (this->SecondaryToolbarSet) { this->SecondaryToolbarSet->SetToolbarsAspect( vtkKWToolbar::GetGlobalToolbarAspect()); this->SecondaryToolbarSet->SetToolbarsWidgetsAspect( vtkKWToolbar::GetGlobalWidgetsAspect()); this->PropagateEnableState(this->SecondaryToolbarSet); } } //---------------------------------------------------------------------------- void vtkKWWindow::UpdateEnableState() { this->Superclass::UpdateEnableState(); // Update the notebook this->PropagateEnableState(this->MainNotebook); this->PropagateEnableState(this->SecondaryNotebook); this->PropagateEnableState(this->ViewNotebook); // Update all the user interface panels if (this->HasMainUserInterfaceManager()) { this->GetMainUserInterfaceManager()->SetEnabled(this->GetEnabled()); // As a side effect, SetEnabled() call an Update() on the panel, // which will call an UpdateEnableState() too, // this->GetMainUserInterfaceManager()->UpdateEnableState(); // this->GetMainUserInterfaceManager()->Update(); } if (this->HasSecondaryUserInterfaceManager()) { this->GetSecondaryUserInterfaceManager()->SetEnabled(this->GetEnabled()); // As a side effect, SetEnabled() call an Update() on the panel, // which will call an UpdateEnableState() too, // this->GetSecondaryUserInterfaceManager()->UpdateEnableState(); // this->GetSecondaryUserInterfaceManager()->Update(); } if (this->HasViewUserInterfaceManager()) { this->GetViewUserInterfaceManager()->SetEnabled(this->GetEnabled()); // As a side effect, SetEnabled() call an Update() on the panel, // which will call an UpdateEnableState() too, // this->GetViewUserInterfaceManager()->UpdateEnableState(); // this->GetViewUserInterfaceManager()->Update(); } if (this->GetApplicationSettingsUserInterfaceManager()) { this->GetApplicationSettingsUserInterfaceManager()->SetEnabled( this->GetEnabled()); // As a side effect, SetEnabled() call an Update() on the panel, // which will call an UpdateEnableState() too, // this->GetApplicationSettingsUserInterfaceManager()->UpdateEnableState(); // this->GetApplicationSettingsUserInterfaceManager()->Update(); } // Update the window element this->PropagateEnableState(this->MainSplitFrame); this->PropagateEnableState(this->SecondarySplitFrame); } //---------------------------------------------------------------------------- void vtkKWWindow::UpdateMenuState() { this->Superclass::UpdateMenuState(); // Update the main panel visibility label if (this->WindowMenu) { int idx = -1; if (this->WindowMenu->HasItem(this->GetHideMainPanelMenuLabel())) { idx = this->WindowMenu->GetIndexOfItem( this->GetHideMainPanelMenuLabel()); } else if (this->WindowMenu->HasItem(this->GetShowMainPanelMenuLabel())) { idx = this->WindowMenu->GetIndexOfItem( this->GetShowMainPanelMenuLabel()); } if (idx >= 0) { vtksys_stl::string label; label += this->GetMainPanelVisibility() ? this->GetHideMainPanelMenuLabel() : this->GetShowMainPanelMenuLabel(); this->WindowMenu->SetItemLabel(idx, label.c_str()); } } // Update the secondary panel visibility label if (this->WindowMenu) { int idx = -1; if (this->WindowMenu->HasItem(this->GetHideSecondaryPanelMenuLabel())) { idx = this->WindowMenu->GetIndexOfItem( this->GetHideSecondaryPanelMenuLabel()); } else if (this->WindowMenu->HasItem( this->GetShowSecondaryPanelMenuLabel())) { idx = this->WindowMenu->GetIndexOfItem( this->GetShowSecondaryPanelMenuLabel()); } if (idx >= 0) { vtksys_stl::string label; label += this->GetSecondaryPanelVisibility() ? this->GetHideSecondaryPanelMenuLabel() : this->GetShowSecondaryPanelMenuLabel(); this->WindowMenu->SetItemLabel(idx, label.c_str()); this->WindowMenu->SetItemState( idx, ((this->PanelLayout == vtkKWWindow::PanelLayoutSecondaryBelowMain && !this->GetMainPanelVisibility()) ? vtkKWOptions::StateDisabled : this->WindowMenu->GetEnabled())); } } } //---------------------------------------------------------------------------- void vtkKWWindow::AddCallbackCommandObservers() { this->Superclass::AddCallbackCommandObservers(); this->AddCallbackCommandObserver( this->MainSplitFrame, vtkKWSplitFrame::FrameVisibilityChangedEvent); this->AddCallbackCommandObserver( this->SecondarySplitFrame, vtkKWSplitFrame::FrameVisibilityChangedEvent); } //---------------------------------------------------------------------------- void vtkKWWindow::RemoveCallbackCommandObservers() { this->Superclass::RemoveCallbackCommandObservers(); this->RemoveCallbackCommandObserver( this->MainSplitFrame, vtkKWSplitFrame::FrameVisibilityChangedEvent); this->RemoveCallbackCommandObserver( this->SecondarySplitFrame, vtkKWSplitFrame::FrameVisibilityChangedEvent); } //---------------------------------------------------------------------------- void vtkKWWindow::ProcessCallbackCommandEvents(vtkObject *caller, unsigned long event, void *calldata) { if (caller == this->MainSplitFrame || caller == this->SecondarySplitFrame) { switch (event) { case vtkKWSplitFrame::FrameVisibilityChangedEvent: this->UpdateMenuState(); // to reflect show/hide in the window menu break; } } this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata); } //---------------------------------------------------------------------------- void vtkKWWindow::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "MainNotebook: " << this->GetMainNotebook() << endl; os << indent << "SecondaryNotebook: " << this->GetSecondaryNotebook() << endl; os << indent << "ViewNotebook: " << this->GetViewNotebook() << endl; os << indent << "MainSplitFrame: " << this->MainSplitFrame << endl; os << indent << "SecondarySplitFrame: " << this->SecondarySplitFrame << endl; os << indent << "SecondaryToolbarSet: " << this->SecondaryToolbarSet << endl; os << indent << "PanelLayout: " << this->PanelLayout << endl; os << indent << "StatusFramePosition: " << this->StatusFramePosition << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWStartupPageWidget.h0000644000175000017500000002744011075436557021650 0ustar domibeldomibel/*========================================================================= Module: vtkKWStartupPageWidget.h,v Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWStartupPageWidget - an HSV color selector // Open file // Double click // Drag and drop // Recent files // .SECTION Description // A widget that allows the user choose a HSV color interactively #ifndef __vtkKWStartupPageWidget_h #define __vtkKWStartupPageWidget_h #include "vtkKWCompositeWidget.h" class vtkKWCanvas; class vtkKWLabel; class vtkKWIcon; class vtkKWStartupPageWidgetInternals; class vtkKWMostRecentFilesManager; class KWWidgets_EXPORT vtkKWStartupPageWidget : public vtkKWCompositeWidget { public: static vtkKWStartupPageWidget* New(); vtkTypeRevisionMacro(vtkKWStartupPageWidget,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the gradient colors (in RGB space) vtkGetVector3Macro(GradientColor1, double); virtual void SetGradientColor1(double r, double g, double b); virtual void SetGradientColor1(double rgb[3]) { this->SetGradientColor1(rgb[0], rgb[1], rgb[2]); }; vtkGetVector3Macro(GradientColor2, double); virtual void SetGradientColor2(double r, double g, double b); virtual void SetGradientColor2(double rgb[3]) { this->SetGradientColor2(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the text color (in RGB space) vtkGetVector3Macro(TextColor, double); virtual void SetTextColor(double r, double g, double b); virtual void SetTextColor(double rgb[3]) { this->SetTextColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the text size vtkGetMacro(TextSize, int); virtual void SetTextSize(int); // Description: // Set/Get the text color (in RGB space) when it is selected (hovered on) vtkGetVector3Macro(SelectedTextColor, double); virtual void SetSelectedTextColor(double r, double g, double b); virtual void SetSelectedTextColor(double rgb[3]) { this->SetSelectedTextColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the hint color (in RGB space) vtkGetVector3Macro(HintColor, double); virtual void SetHintColor(double r, double g, double b); virtual void SetHintColor(double rgb[3]) { this->SetHintColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the hint size vtkGetMacro(HintSize, int); virtual void SetHintSize(int); // Description: // Set/Get if the hints should have a shadow. virtual void SetAddShadowToHint(int); vtkGetMacro(AddShadowToHint, int); vtkBooleanMacro(AddShadowToHint, int); // Description: // Set/Get if the Open section is supported/shown. virtual void SetSupportOpen(int); vtkGetMacro(SupportOpen, int); vtkBooleanMacro(SupportOpen, int); // Description: // Set/Get the Open section icon using an icon, or the index to a // predefined icon found in vtkKWIcon. // Note that the Set method does *not* keep a reference to the icon // passed as parameter: it copies the whole icon contents internally. vtkGetObjectMacro(OpenIcon, vtkKWIcon); virtual void SetOpenIcon(vtkKWIcon*); virtual void SetOpenIconToPredefinedIcon(int icon_index); // Description: // Set/Get if the Double Click section is supported/shown. virtual void SetSupportDoubleClick(int); vtkGetMacro(SupportDoubleClick, int); vtkBooleanMacro(SupportDoubleClick, int); // Description: // Set/Get the Double Click section icon using an icon, or the index to a // predefined icon found in vtkKWIcon. // Note that the Set method does *not* keep a reference to the icon // passed as parameter: it copies the whole icon contents internally. vtkGetObjectMacro(DoubleClickIcon, vtkKWIcon); virtual void SetDoubleClickIcon(vtkKWIcon*); virtual void SetDoubleClickIconToPredefinedIcon(int icon_index); // Description: // Set/Get if the Drag & Drop section is supported/shown. virtual void SetSupportDrop(int); vtkGetMacro(SupportDrop, int); vtkBooleanMacro(SupportDrop, int); // Description: // Set/Get the Drag & Drop section icon using an icon, or the index to a // predefined icon found in vtkKWIcon. // Note that the Set method does *not* keep a reference to the icon // passed as parameter: it copies the whole icon contents internally. vtkGetObjectMacro(DropIcon, vtkKWIcon); virtual void SetDropIcon(vtkKWIcon*); virtual void SetDropIconToPredefinedIcon(int icon_index); // Description: // Set/Get if the Most Recent Files section is supported/shown. virtual void SetSupportMostRecentFiles(int); vtkGetMacro(SupportMostRecentFiles, int); vtkBooleanMacro(SupportMostRecentFiles, int); // Description: // Set/Get the Most Recent Files section icon using an icon, or the index to // a predefined icon found in vtkKWIcon. // Note that the Set method does *not* keep a reference to the icon // passed as parameter: it copies the whole icon contents internally. vtkGetObjectMacro(MostRecentFilesIcon, vtkKWIcon); virtual void SetMostRecentFilesIcon(vtkKWIcon*); virtual void SetMostRecentFilesIconToPredefinedIcon(int icon_index); // Description: // Set/Get the Most Recent File icon (i.e. the icon used for a single // most recent file, not the section itself) using an icon, or the index to // a predefined icon found in vtkKWIcon. // Note that the Set method does *not* keep a reference to the icon // passed as parameter: it copies the whole icon contents internally. vtkGetObjectMacro(MostRecentFileIcon, vtkKWIcon); virtual void SetMostRecentFileIcon(vtkKWIcon*); virtual void SetMostRecentFileIconToPredefinedIcon(int icon_index); // Description: // Set/Get the text size of recent file items vtkGetMacro(MostRecentFileSize, int); virtual void SetMostRecentFileSize(int); // Description: // Set/Get the most recent files manager this page should listen to. vtkGetObjectMacro(MostRecentFilesManager, vtkKWMostRecentFilesManager); virtual void SetMostRecentFilesManager(vtkKWMostRecentFilesManager *mgr); // Description: // Set/Get the maximum number of most recent files to display. vtkGetMacro(MaximumNumberOfMostRecentFiles, int); virtual void SetMaximumNumberOfMostRecentFiles(int); // Description: // Specifies commands to associate with the widget. // 'OpenCommand' is invoked when the user click on the Open section. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetOpenCommand( vtkObject *object, const char *method); // Description: // Specifies commands to associate with the widget. // 'DropCommand' is invoked when the user drop a file on the widget. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - filename(s): list of filenames virtual void SetDropCommand( vtkObject *object, const char *method); // Description: // Specifies commands to associate with the widget. // 'DoubleClickCommand' is invoked when the user double-click anywhere // in the page widget. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. virtual void SetDoubleClickCommand( vtkObject *object, const char *method); // Description: // Access to the canvas and internal elements vtkGetObjectMacro(StartupPageCanvas, vtkKWCanvas); // Description: // Update the whole UI depending on the value of the Ivars virtual void Update(); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void ConfigureCallback(); virtual void RedrawCallback(); virtual void HighlightSectionCallback(const char *tag, int flag); virtual void OpenCallback(); virtual void DoubleClickCallback(); // Description: // Add all the default observers needed by that object, or remove // all the observers that were added through AddCallbackCommandObserver. // Subclasses can override these methods to add/remove their own default // observers, but should call the superclass too. virtual void AddCallbackCommandObservers(); virtual void RemoveCallbackCommandObservers(); protected: vtkKWStartupPageWidget(); ~vtkKWStartupPageWidget(); // Description: // Create the widget. virtual void CreateWidget(); double GradientColor1[3]; double GradientColor2[3]; double TextColor[3]; double SelectedTextColor[3]; double HintColor[3]; int TextSize; int HintSize; int MostRecentFileSize; int SupportOpen; int SupportDoubleClick; int SupportDrop; int SupportMostRecentFiles; int MaximumNumberOfMostRecentFiles; int AddShadowToHint; vtkKWIcon *OpenIcon; vtkKWIcon *DoubleClickIcon; vtkKWIcon *DropIcon; vtkKWIcon *MostRecentFilesIcon; vtkKWIcon *MostRecentFileIcon; // Recent files manager vtkKWMostRecentFilesManager *MostRecentFilesManager; // Commands char *OpenCommand; char *DropCommand; char *DoubleClickCommand; // GUI vtkKWCanvas *StartupPageCanvas; // Description: // Bind/Unbind all components. virtual void Bind(); virtual void UnBind(); // Description: // Redraw or update canvas elements virtual void Redraw(); virtual void ScheduleRedraw(); // Description: // Update bindings, fonts, colors, icons virtual void UpdateInternalCanvasBindings(); virtual void UpdateInternalCanvasColors(); virtual void UpdateInternalCanvasFonts(); virtual void UpdateInternalCanvasIcons(); // Description: // Draw section virtual void AddSectionToCanvas( ostream &tk_cmd, int x, int y, vtkKWIcon *icon, const char *text, const char *text_font, const char *hint, const char *hint_font, vtkObject *object, const char *method, const char *tag, const char *extra_tag = NULL); virtual void AddMostRecentFilesSectionToCanvas( ostream &tk_cmd, int x, int y); // Description: // Invoke the commands virtual void InvokeOpenCommand(); virtual void InvokeDoubleClickCommand(); // PIMPL Encapsulation for STL containers //BTX vtkKWStartupPageWidgetInternals *Internals; //ETX // Description: // Processes the events that are passed through CallbackCommand (or others). // Subclasses can oberride this method to process their own events, but // should call the superclass too. virtual void ProcessCallbackCommandEvents( vtkObject *caller, unsigned long event, void *calldata); // Description: // Helpers virtual int GetHorizontalIncrementFromIcon(vtkKWIcon *icon); private: vtkKWStartupPageWidget(const vtkKWStartupPageWidget&); // Not implemented void operator=(const vtkKWStartupPageWidget&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWHSVColorSelector.cxx0000644000175000017500000007606511075261602021752 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWHSVColorSelector.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWHSVColorSelector.h" #include "vtkKWApplication.h" #include "vtkKWCanvas.h" #include "vtkKWFrame.h" #include "vtkKWLabel.h" #include "vtkKWInternationalization.h" #include "vtkKWTkUtilities.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include vtkCxxRevisionMacro(vtkKWHSVColorSelector, "$Revision: 1.24 $"); vtkStandardNewMacro(vtkKWHSVColorSelector); #define VTK_KW_HSV_SEL_POINT_RADIUS_MIN 2 #define VTK_KW_HSV_SEL_HS_WHEEL_RADIUS_MIN 20 #define VTK_KW_HSV_SEL_VALUE_BOX_WIDTH_MIN 10 #define VTK_KW_HSV_SEL_HS_CURSOR_RADIUS_MIN 2 #define VTK_KW_HSV_SEL_V_CURSOR_MARGIN_MIN 0 #define VTK_KW_HSV_SEL_IMAGE_TAG "image" #define VTK_KW_HSV_SEL_SELECTION_TAG "selection" #define VTK_KW_HSV_SEL_DISABLED_OPACITY 0.25 //---------------------------------------------------------------------------- vtkKWHSVColorSelector::vtkKWHSVColorSelector() { this->HueSatWheelRadius = 64; this->ValueBoxWidth = 20; this->HueSatCursorRadius = 4; this->ValueCursorMargin = 2; this->Selected = 0; this->ModificationOnly = 0; this->InvokeCommandsWithRGB = 0; this->HideValue = 0; this->SelectedColor[0] = 0.0; this->SelectedColor[1] = 0.0; this->SelectedColor[2] = 0.5; this->SelectionChangedCommand = NULL; this->SelectionChangingCommand = NULL; this->HueSatWheelCanvas = vtkKWCanvas::New(); this->ValueBoxCanvas = vtkKWCanvas::New(); this->HueSatLabel = vtkKWLabel::New(); this->ValueLabel = vtkKWLabel::New(); } //---------------------------------------------------------------------------- vtkKWHSVColorSelector::~vtkKWHSVColorSelector() { // Commands if (this->SelectionChangedCommand) { delete [] this->SelectionChangedCommand; this->SelectionChangedCommand = NULL; } if (this->SelectionChangingCommand) { delete [] this->SelectionChangingCommand; this->SelectionChangingCommand = NULL; } // GUI if (this->HueSatWheelCanvas) { this->HueSatWheelCanvas->Delete(); this->HueSatWheelCanvas = NULL; } if (this->ValueBoxCanvas) { this->ValueBoxCanvas->Delete(); this->ValueBoxCanvas = NULL; } if (this->HueSatLabel) { this->HueSatLabel->Delete(); this->HueSatLabel = NULL; } if (this->ValueLabel) { this->ValueLabel->Delete(); this->ValueLabel = NULL; } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Create the Hue/Sat canvas this->HueSatWheelCanvas->SetParent(this); this->HueSatWheelCanvas->Create(); this->HueSatWheelCanvas->SetHeight(0); this->HueSatWheelCanvas->SetWidth(0); this->HueSatWheelCanvas->SetReliefToSolid(); this->HueSatWheelCanvas->SetBorderWidth(0); // Create the Value canvas this->ValueBoxCanvas->SetParent(this); this->ValueBoxCanvas->Create(); this->ValueBoxCanvas->SetHeight(0); this->ValueBoxCanvas->SetWidth(0); this->ValueBoxCanvas->SetReliefToSolid(); this->ValueBoxCanvas->SetBorderWidth(0); // Create the Hue/Sat label this->HueSatLabel->SetParent(this); this->HueSatLabel->Create(); this->HueSatLabel->SetBorderWidth(0); this->HueSatLabel->SetText(ks_("Color Space|Hue/Saturation:")); // Create the Value label this->ValueLabel->SetParent(this); this->ValueLabel->Create(); this->ValueLabel->SetBorderWidth(0); this->ValueLabel->SetText(ks_("Color Space|Value:")); // Set the bindings this->Bind(); // Pack the widget this->Pack(); // Update this->Update(); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::Update() { this->UpdateEnableState(); this->Redraw(); // No selection, disable Value box if (!this->HasSelection()) { if (this->ValueBoxCanvas) { this->ValueBoxCanvas->SetEnabled(0); } if (this->ValueLabel) { this->ValueLabel->SetEnabled(0); } } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::Pack() { if (!this->IsCreated()) { return; } // Unpack everything this->HueSatWheelCanvas->UnpackSiblings(); // Repack everything int row = 0; const char *col0 = " -column 1 "; const char *col1 = " -column 0 "; vtksys_ios::ostringstream tk_cmd; // Hue/Sat label tk_cmd << "grid " << this->HueSatLabel->GetWidgetName() << " -sticky ew -row " << row << col0 << endl; // Value label if (!this->HideValue) { tk_cmd << "grid " << this->ValueLabel->GetWidgetName() << " -sticky ew -row " << row << col1 << endl; } row++; // Hue/Sat Box Canvas tk_cmd << "grid " << this->HueSatWheelCanvas->GetWidgetName() << " -sticky ew -row " << row << col0 << endl; // Value Box Canvas if (!this->HideValue) { tk_cmd << "grid " << this->ValueBoxCanvas->GetWidgetName() << " -sticky ew -row " << row << col1 << endl; } this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::Bind() { if (!this->IsCreated()) { return; } // Hue/Sat Box Canvas if (this->HueSatWheelCanvas && this->HueSatWheelCanvas->IsAlive()) { this->HueSatWheelCanvas->SetBinding( "", this, "HueSatPickCallback %x %y"); this->HueSatWheelCanvas->SetBinding( "", this, "HueSatMoveCallback %x %y"); this->HueSatWheelCanvas->SetBinding( "", this, "HueSatReleaseCallback"); } if (this->ValueBoxCanvas && this->ValueBoxCanvas->IsAlive()) { this->ValueBoxCanvas->SetBinding( "", this, "ValuePickCallback %x %y"); this->ValueBoxCanvas->SetBinding( "", this, "ValueMoveCallback %x %y"); this->ValueBoxCanvas->SetBinding( "", this, "ValueReleaseCallback"); } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::UnBind() { if (!this->IsCreated()) { return; } // Hue/Sat Box Canvas if (this->HueSatWheelCanvas && this->HueSatWheelCanvas->IsAlive()) { this->HueSatWheelCanvas->RemoveBinding(""); this->HueSatWheelCanvas->RemoveBinding(""); this->HueSatWheelCanvas->RemoveBinding(""); } if (this->ValueBoxCanvas && this->ValueBoxCanvas->IsAlive()) { this->ValueBoxCanvas->RemoveBinding(""); this->ValueBoxCanvas->RemoveBinding(""); this->ValueBoxCanvas->RemoveBinding(""); } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::SetHueSatWheelRadius(int arg) { if (this->HueSatWheelRadius == arg || arg < VTK_KW_HSV_SEL_HS_WHEEL_RADIUS_MIN) { return; } this->HueSatWheelRadius = arg; this->Modified(); this->Redraw(); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::SetValueBoxWidth(int arg) { if (this->ValueBoxWidth == arg || arg < VTK_KW_HSV_SEL_VALUE_BOX_WIDTH_MIN) { return; } this->ValueBoxWidth = arg; this->Modified(); this->Redraw(); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::SetHueSatCursorRadius(int arg) { if (this->HueSatCursorRadius == arg || arg < VTK_KW_HSV_SEL_HS_CURSOR_RADIUS_MIN) { return; } this->HueSatCursorRadius = arg; this->Modified(); this->Redraw(); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::SetValueCursorMargin(int arg) { if (this->ValueCursorMargin == arg || arg < VTK_KW_HSV_SEL_V_CURSOR_MARGIN_MIN) { return; } this->ValueCursorMargin = arg; this->Modified(); this->Redraw(); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::SetHideValue(int arg) { if (this->HideValue == arg) { return; } this->HideValue = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::SetSelectedColor( double h, double s, double v) { if ((h < 0.0 || h > 1.0 || s < 0.0 || s > 1.0 || v < 0.0 || v > 1.0) || (this->Selected && (h == this->SelectedColor[0] && s == this->SelectedColor[1] && v == this->SelectedColor[2]))) { return; } this->SelectedColor[0] = h; this->SelectedColor[1] = s; this->SelectedColor[2] = v; this->Selected = 1; this->Modified(); this->UpdateValueBoxImage(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::ClearSelection() { if (!this->Selected) { return; } this->Selected = 0; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- int vtkKWHSVColorSelector::HasSelection() { return this->Selected; } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::InvokeCommandWithColor( const char *command, double h, double s, double v) { if (command && *command && this->IsCreated()) { if (this->InvokeCommandsWithRGB) { double r, g, b; vtkMath::HSVToRGB(h, s, v, &r, &g, &b); this->Script("%s %lf %lf %lf", command, r, g, b); } else { this->Script("%s %lf %lf %lf", command, h, s, v); } } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::SetSelectionChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->SelectionChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::InvokeSelectionChangedCommand( double h, double s, double v) { this->InvokeCommandWithColor(this->SelectionChangedCommand, h, s, v); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::SetSelectionChangingCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->SelectionChangingCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::InvokeSelectionChangingCommand( double h, double s, double v) { this->InvokeCommandWithColor(this->SelectionChangingCommand, h, s, v); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->HueSatWheelCanvas); this->PropagateEnableState(this->ValueBoxCanvas); this->PropagateEnableState(this->HueSatLabel); this->PropagateEnableState(this->ValueLabel); if (this->GetEnabled()) { this->Bind(); } else { this->UnBind(); } } // --------------------------------------------------------------------------- void vtkKWHSVColorSelector::SetBalloonHelpString( const char *string) { this->Superclass::SetBalloonHelpString(string); if (this->HueSatWheelCanvas) { this->HueSatWheelCanvas->SetBalloonHelpString(string); } if (this->ValueBoxCanvas) { this->ValueBoxCanvas->SetBalloonHelpString(string); } if (this->HueSatLabel) { this->HueSatLabel->SetBalloonHelpString(string); } if (this->ValueLabel) { this->ValueLabel->SetBalloonHelpString(string); } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::Redraw() { this->RedrawHueSatWheelCanvas(); this->RedrawValueBoxCanvas(); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::RedrawHueSatWheelCanvas() { if (!this->HueSatWheelCanvas || !this->HueSatWheelCanvas->IsAlive()) { return; } vtksys_ios::ostringstream tk_cmd; const char *canv = this->HueSatWheelCanvas->GetWidgetName(); // If the image is not in the canvas, create it and add it to the canvas vtksys_ios::ostringstream img_name; img_name << this->HueSatWheelCanvas->GetWidgetName() << "." << VTK_KW_HSV_SEL_IMAGE_TAG; if (!this->HueSatWheelCanvas->HasTag(VTK_KW_HSV_SEL_IMAGE_TAG)) { vtksys_ios::ostringstream img_name_d; img_name_d << this->HueSatWheelCanvas->GetWidgetName() << "." << VTK_KW_HSV_SEL_IMAGE_TAG << "_disabled"; tk_cmd << "image create photo " << img_name.str().c_str() << " -width 0 -height 0" << endl; tk_cmd << "image create photo " << img_name_d.str().c_str() << " -width 0 -height 0" << endl; tk_cmd << canv << " create image 0 0 -anchor nw " << " -image " << img_name.str().c_str() << " -disabledimage " << img_name_d.str().c_str() << " -tags {" << VTK_KW_HSV_SEL_IMAGE_TAG << "}" << endl; } // Update the image coordinates // Leave some margin for the cursor int height_offset = this->HueSatCursorRadius; int width_offset = height_offset; tk_cmd << canv << " coords " << VTK_KW_HSV_SEL_IMAGE_TAG << " " << width_offset << " " << height_offset << endl; // Resize the canvas given the image size and margins int c_height = 2 * (this->HueSatWheelRadius + height_offset); int c_width = 2 * (this->HueSatWheelRadius + width_offset); this->HueSatWheelCanvas->SetWidth(c_width); this->HueSatWheelCanvas->SetHeight(c_height); char buffer[256]; sprintf(buffer, "0 0 %d %d", c_width, c_height); this->HueSatWheelCanvas->SetConfigurationOption("-scrollregion", buffer); this->Script(tk_cmd.str().c_str()); // Check if the image needs to be redrawn int i_height = 2 * this->HueSatWheelRadius; int i_width = i_height; vtkKWApplication *app = this->GetApplication(); if (vtkKWTkUtilities::GetPhotoWidth(app, img_name.str().c_str()) != i_width || vtkKWTkUtilities::GetPhotoHeight(app, img_name.str().c_str()) != i_height) { this->UpdateHueSatWheelImage(); } // Update the selection this->UpdateHueSatWheelSelection(); } //---------------------------------------------------------------------------- int vtkKWHSVColorSelector::GetHueSatFromCoordinates( int x, int y, double &hue, double &sat) { // x and y are coordinates within the hue/sat wheel image int diameter = 2 * this->HueSatWheelRadius; y = (diameter - 1) - y; double radius = this->HueSatWheelRadius; double dx = (double)x + 0.5 - radius; double dy = (double)y + 0.5 - radius; int inside_wheel; sat = sqrt(dx * dx + dy * dy) / radius; if (sat > 1.0) { sat = 1.0; inside_wheel = 0; } else { inside_wheel = 1; } hue = atan2(dy, dx) / (vtkMath::Pi() * 2.0); if (hue < 0.0) { hue = 1.0 + hue; } return inside_wheel; } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::UpdateHueSatWheelImage() { if (!this->HueSatWheelCanvas || !this->HueSatWheelCanvas->IsAlive()) { return; } // Create the Hue/Sat image and update (as well as the disable image) int diameter = 2 * this->HueSatWheelRadius; unsigned char *buffer = new unsigned char [diameter * diameter * 4]; unsigned char *ptr = buffer; unsigned char *buffer_d = new unsigned char [diameter * diameter * 4]; unsigned char *ptr_d = buffer_d; double hue, sat, r, g, b; for (int y = 0; y < diameter; y++) { for (int x = 0; x < diameter; x++) { if (this->GetHueSatFromCoordinates(x, y, hue, sat)) { vtkMath::HSVToRGB(hue, sat, 1.0, &r, &g, &b); r *= 255.0; g *= 255.0; b *= 255.0; *ptr++ = (unsigned char)r; *ptr++ = (unsigned char)g; *ptr++ = (unsigned char)b; *ptr++ = 255; *ptr_d++ = (unsigned char)r; *ptr_d++ = (unsigned char)g; *ptr_d++ = (unsigned char)b; *ptr_d++ = (unsigned char)(VTK_KW_HSV_SEL_DISABLED_OPACITY * 255.0); } else { *ptr++ = 0; *ptr++ = 0; *ptr++ = 0; *ptr++ = 0; *ptr_d++ = 0; *ptr_d++ = 0; *ptr_d++ = 0; *ptr_d++ = 0; } } } // Update the image vtksys_ios::ostringstream img_name; img_name << this->HueSatWheelCanvas->GetWidgetName() << "." << VTK_KW_HSV_SEL_IMAGE_TAG; vtkKWTkUtilities::UpdatePhoto(this->GetApplication(), img_name.str().c_str(), buffer, diameter, diameter, 4, diameter * diameter * 4); delete [] buffer; // Update the image (disabled state) vtksys_ios::ostringstream img_name_d; img_name_d << this->HueSatWheelCanvas->GetWidgetName() << "." << VTK_KW_HSV_SEL_IMAGE_TAG << "_disabled"; vtkKWTkUtilities::UpdatePhoto(this->GetApplication(), img_name_d.str().c_str(), buffer_d, diameter, diameter, 4, diameter * diameter * 4); delete [] buffer_d; } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::UpdateHueSatWheelSelection() { if (!this->HueSatWheelCanvas || !this->HueSatWheelCanvas->IsAlive()) { return; } vtksys_ios::ostringstream tk_cmd; const char *canv = this->HueSatWheelCanvas->GetWidgetName(); int has_tag = this->HueSatWheelCanvas->HasTag(VTK_KW_HSV_SEL_SELECTION_TAG); // Remove the cursor, or update its coordinates given the selection if (!this->HasSelection()) { if (has_tag) { tk_cmd << canv << " delete " << VTK_KW_HSV_SEL_SELECTION_TAG << endl; } } else { if (!has_tag) { tk_cmd << canv << " create oval 0 0 0 0 -fill #ffffff -tag " << VTK_KW_HSV_SEL_SELECTION_TAG << endl; } double wheel_radius = this->HueSatWheelRadius; int x = (int)(wheel_radius - 0.5 + wheel_radius * this->SelectedColor[1] * cos(this->SelectedColor[0] * vtkMath::Pi() * 2.0)); int y = (int)(wheel_radius - 0.5 - wheel_radius * this->SelectedColor[1] * sin(this->SelectedColor[0] * vtkMath::Pi() * 2.0)); int height_offset = this->HueSatCursorRadius; int width_offset = height_offset; tk_cmd << canv << " coords " << VTK_KW_HSV_SEL_SELECTION_TAG << " " << width_offset + x - this->HueSatCursorRadius << " " << height_offset + y - this->HueSatCursorRadius << " " << width_offset + x + this->HueSatCursorRadius << " " << height_offset + y + this->HueSatCursorRadius << endl; } this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::RedrawValueBoxCanvas() { if (!this->ValueBoxCanvas || !this->ValueBoxCanvas->IsAlive()) { return; } vtksys_ios::ostringstream tk_cmd; const char *canv = this->ValueBoxCanvas->GetWidgetName(); // If the image is not in the canvas, create it and add it to the canvas vtksys_ios::ostringstream img_name; img_name << this->ValueBoxCanvas->GetWidgetName() << "." << VTK_KW_HSV_SEL_IMAGE_TAG; if (!this->ValueBoxCanvas->HasTag(VTK_KW_HSV_SEL_IMAGE_TAG)) { vtksys_ios::ostringstream img_name_d; img_name_d << this->ValueBoxCanvas->GetWidgetName() << "." << VTK_KW_HSV_SEL_IMAGE_TAG << "_disabled"; tk_cmd << "image create photo " << img_name.str().c_str() << " -width 0 -height 0" << endl; tk_cmd << "image create photo " << img_name_d.str().c_str() <<" -width 0 -height 0" << endl; tk_cmd << canv << " create image 0 0 -anchor nw " << " -image " << img_name.str().c_str() << " -disabledimage " << img_name_d.str().c_str() << " -tags {" << VTK_KW_HSV_SEL_IMAGE_TAG << "}" << endl; } // Update the image coordinates // Leave some margin for the cursor int height_offset = this->HueSatCursorRadius; int width_offset = this->ValueCursorMargin; tk_cmd << canv << " coords " << VTK_KW_HSV_SEL_IMAGE_TAG << " " << width_offset << " " << height_offset << endl; // Resize the canvas given the image size and margins int c_height = 2 * (this->HueSatWheelRadius + height_offset); int c_width = this->ValueBoxWidth + 2 * width_offset; this->ValueBoxCanvas->SetWidth(c_width); this->ValueBoxCanvas->SetHeight(c_height); char buffer[256]; sprintf(buffer, "0 0 %d %d", c_width - 1, c_height - 1); this->ValueBoxCanvas->SetConfigurationOption("-scrollregion", buffer); this->Script(tk_cmd.str().c_str()); // Check if the image needs to be redrawn int i_height = 2 * this->HueSatWheelRadius; int i_width = this->ValueBoxWidth; vtkKWApplication *app = this->GetApplication(); if (vtkKWTkUtilities::GetPhotoWidth(app, img_name.str().c_str()) != i_width || vtkKWTkUtilities::GetPhotoHeight(app, img_name.str().c_str()) != i_height) { this->UpdateValueBoxImage(); } // Update the selection this->UpdateValueBoxSelection(); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::GetValueFromCoordinate(int y, double &value) { // y is coordinate within the value box image int height = 2 * this->HueSatWheelRadius; y = (height - 1) - y; value = (double)y / (double)(height - 1); if (value < 0.0) { value = 0.0; } else if (value > 1.0) { value = 1.0; } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::UpdateValueBoxImage() { if (!this->ValueBoxCanvas || !this->ValueBoxCanvas->IsAlive()) { return; } // Create the Value image and update int height = 2 * this->HueSatWheelRadius; int width = this->ValueBoxWidth; unsigned char *buffer = new unsigned char [width * height * 3]; unsigned char *ptr = buffer; unsigned char *buffer_d = new unsigned char [width * height * 4]; unsigned char *ptr_d = buffer_d; double value, r, g, b; for (int y = 0; y < height; y++) { this->GetValueFromCoordinate(y, value); vtkMath::HSVToRGB(this->SelectedColor[0], this->SelectedColor[1], value, &r, &g, &b); r *= 255.0; g *= 255.0; b *= 255.0; for (int x = 0; x < width; x++) { *ptr++ = (unsigned char)r; *ptr++ = (unsigned char)g; *ptr++ = (unsigned char)b; *ptr_d++ = (unsigned char)r; *ptr_d++ = (unsigned char)g; *ptr_d++ = (unsigned char)b; *ptr_d++ = (unsigned char)(VTK_KW_HSV_SEL_DISABLED_OPACITY * 255.0); } } // Update image vtksys_ios::ostringstream img_name; img_name << this->ValueBoxCanvas->GetWidgetName() << "." << VTK_KW_HSV_SEL_IMAGE_TAG; vtkKWTkUtilities::UpdatePhoto(this->GetApplication(), img_name.str().c_str(), buffer, width, height, 3, width * height * 3); delete [] buffer; // Update disabled image vtksys_ios::ostringstream img_name_d; img_name_d << this->ValueBoxCanvas->GetWidgetName() << "." << VTK_KW_HSV_SEL_IMAGE_TAG << "_disabled"; vtkKWTkUtilities::UpdatePhoto(this->GetApplication(), img_name_d.str().c_str(), buffer_d, width, height, 4, width * height * 4); delete [] buffer_d; } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::UpdateValueBoxSelection() { if (!this->ValueBoxCanvas || !this->ValueBoxCanvas->IsAlive()) { return; } vtksys_ios::ostringstream tk_cmd; const char *canv = this->ValueBoxCanvas->GetWidgetName(); int has_tag = this->ValueBoxCanvas->HasTag(VTK_KW_HSV_SEL_SELECTION_TAG); // Delete the cursor or update its coordinates given the selection if (!this->HasSelection()) { if (has_tag) { tk_cmd << canv << " delete " << VTK_KW_HSV_SEL_SELECTION_TAG << endl; } } else { if (!has_tag) { tk_cmd << canv << " create rectangle 0 0 0 0 -fill #ffffff -tag " << VTK_KW_HSV_SEL_SELECTION_TAG << endl; } int height_offset = this->HueSatCursorRadius; int width_offset = this->ValueCursorMargin; int height = this->HueSatWheelRadius * 2; int y = (int)((1.0 - this->SelectedColor[2]) * (height - 1)); tk_cmd << canv << " coords " << VTK_KW_HSV_SEL_SELECTION_TAG << " " << width_offset - this->ValueCursorMargin << " " << height_offset + y - 1 << " " << width_offset + this->ValueBoxWidth - 1 + this->ValueCursorMargin << " " << height_offset + y + 1 << endl; } this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::HueSatPickCallback(int x, int y) { if (this->ModificationOnly && !this->HasSelection()) { return; } this->PreviouslySelectedColor[0] = this->SelectedColor[0]; this->PreviouslySelectedColor[1] = this->SelectedColor[1]; this->PreviouslySelectedColor[2] = this->SelectedColor[2]; int height_offset = this->HueSatCursorRadius; int width_offset = height_offset; y -= height_offset; x -= width_offset; double hue, sat; this->GetHueSatFromCoordinates(x, y, hue, sat); this->SetSelectedColor(hue, sat, this->SelectedColor[2]); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::HueSatMoveCallback(int x, int y) { if (!this->HasSelection()) { return; } int height_offset = this->HueSatCursorRadius; int width_offset = height_offset; y -= height_offset; x -= width_offset; double hue, sat; this->GetHueSatFromCoordinates(x, y, hue, sat); this->SetSelectedColor(hue, sat, this->SelectedColor[2]); if (this->PreviouslySelectedColor[0] != this->SelectedColor[0] || this->PreviouslySelectedColor[1] != this->SelectedColor[1] || this->PreviouslySelectedColor[2] != this->SelectedColor[2]) { this->InvokeSelectionChangingCommand( this->SelectedColor[0], this->SelectedColor[1], this->SelectedColor[2]); } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::HueSatReleaseCallback() { if (!this->HasSelection()) { return; } if (this->PreviouslySelectedColor[0] != this->SelectedColor[0] || this->PreviouslySelectedColor[1] != this->SelectedColor[1] || this->PreviouslySelectedColor[2] != this->SelectedColor[2]) { this->InvokeSelectionChangedCommand( this->SelectedColor[0], this->SelectedColor[1], this->SelectedColor[2]); } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::ValuePickCallback(int vtkNotUsed(x), int y) { if (this->ModificationOnly && !this->HasSelection()) { return; } this->PreviouslySelectedColor[0] = this->SelectedColor[0]; this->PreviouslySelectedColor[1] = this->SelectedColor[1]; this->PreviouslySelectedColor[2] = this->SelectedColor[2]; int height_offset = this->HueSatCursorRadius; y -= height_offset; double value; this->GetValueFromCoordinate(y, value); this->SetSelectedColor( this->SelectedColor[0], this->SelectedColor[1], value); } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::ValueMoveCallback(int vtkNotUsed(x), int y) { if (!this->HasSelection()) { return; } int height_offset = this->HueSatCursorRadius; y -= height_offset; double value; this->GetValueFromCoordinate(y, value); this->SetSelectedColor( this->SelectedColor[0], this->SelectedColor[1], value); if (this->PreviouslySelectedColor[0] != this->SelectedColor[0] || this->PreviouslySelectedColor[1] != this->SelectedColor[1] || this->PreviouslySelectedColor[2] != this->SelectedColor[2]) { this->InvokeSelectionChangingCommand( this->SelectedColor[0], this->SelectedColor[1], this->SelectedColor[2]); } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::ValueReleaseCallback() { if (!this->HasSelection()) { return; } if (this->PreviouslySelectedColor[0] != this->SelectedColor[0] || this->PreviouslySelectedColor[1] != this->SelectedColor[1] || this->PreviouslySelectedColor[2] != this->SelectedColor[2]) { this->InvokeSelectionChangedCommand( this->SelectedColor[0], this->SelectedColor[1], this->SelectedColor[2]); } } //---------------------------------------------------------------------------- void vtkKWHSVColorSelector::PrintSelf( ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "HueSatWheelRadius: "<< this->HueSatWheelRadius << endl; os << indent << "ValueBoxWidth: "<< this->ValueBoxWidth << endl; os << indent << "HueSatCursorRadius: " << this->HueSatCursorRadius << endl; os << indent << "ValueCursorMargin: "<< this->ValueCursorMargin << endl; os << indent << "ModificationOnly: " << (this->ModificationOnly ? "On" : "Off") << endl; os << indent << "InvokeCommandsWithRGB: " << (this->InvokeCommandsWithRGB ? "On" : "Off") << endl; os << indent << "SelectedColor: (" << this->SelectedColor[0] << ", " << this->SelectedColor[1] << ", " << this->SelectedColor[2] << ") " << endl; os << indent << "HideValue: " << (this->HideValue ? "On" : "Off") << endl; os << indent << "HueSatWheelCanvas: "; if (this->HueSatWheelCanvas) { os << endl; this->HueSatWheelCanvas->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "ValueBoxCanvas: "; if (this->ValueBoxCanvas) { os << endl; this->ValueBoxCanvas->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWScale.cxx0000644000175000017500000004005110747375742017643 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWScale.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWScale.h" #include "vtkKWOptions.h" #include "vtkObjectFactory.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWScale ); vtkCxxRevisionMacro(vtkKWScale, "$Revision: 1.120 $"); //---------------------------------------------------------------------------- vtkKWScale::vtkKWScale() { this->Value = 0; this->Range[0] = 0; this->Range[1] = 100; this->Resolution = 1; this->Orientation = vtkKWOptions::OrientationHorizontal; this->Command = NULL; this->StartCommand = NULL; this->EndCommand = NULL; this->ClampValue = 1; this->DisableCommands = 0; this->DisableScaleValueCallback = 1; } //---------------------------------------------------------------------------- vtkKWScale::~vtkKWScale() { if (this->IsAlive()) { this->UnBind(); } if (this->Command) { delete [] this->Command; this->Command = NULL; } if (this->StartCommand) { delete [] this->StartCommand; this->StartCommand = NULL; } if (this->EndCommand) { delete [] this->EndCommand; this->EndCommand = NULL; } } //---------------------------------------------------------------------------- void vtkKWScale::CreateWidget() { // Call the superclass to set the appropriate flags then create manually if (!vtkKWWidget::CreateSpecificTkWidget(this, "scale", "-highlightthickness 0 -bd 2")) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } this->UpdateOrientation(); this->UpdateResolution(); this->UpdateRange(); this->UpdateValue(); this->Bind(); } //---------------------------------------------------------------------------- void vtkKWScale::UpdateOrientation() { if (this->IsCreated()) { this->SetConfigurationOption( "-orient", vtkKWOptions::GetOrientationAsTkOptionValue( this->Orientation)); } } //---------------------------------------------------------------------------- void vtkKWScale::SetOrientation(int orientation) { if (this->Orientation == orientation || (orientation != vtkKWOptions::OrientationHorizontal && orientation != vtkKWOptions::OrientationVertical)) { return; } this->Orientation = orientation; this->Modified(); this->UpdateOrientation(); } void vtkKWScale::SetOrientationToHorizontal() { this->SetOrientation(vtkKWOptions::OrientationHorizontal); }; void vtkKWScale::SetOrientationToVertical() { this->SetOrientation(vtkKWOptions::OrientationVertical); }; //---------------------------------------------------------------------------- void vtkKWScale::GetBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWScale::GetBackgroundColor() { return this->GetConfigurationOptionAsColor("-background"); } //---------------------------------------------------------------------------- void vtkKWScale::SetBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- void vtkKWScale::GetForegroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWScale::GetForegroundColor() { return this->GetConfigurationOptionAsColor("-foreground"); } //---------------------------------------------------------------------------- void vtkKWScale::SetForegroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-foreground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWScale::SetHighlightThickness(int width) { this->SetConfigurationOptionAsInt("-highlightthickness", width); } //---------------------------------------------------------------------------- int vtkKWScale::GetHighlightThickness() { return this->GetConfigurationOptionAsInt("-highlightthickness"); } //---------------------------------------------------------------------------- void vtkKWScale::GetActiveBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWScale::GetActiveBackgroundColor() { return this->GetConfigurationOptionAsColor("-activebackground"); } //---------------------------------------------------------------------------- void vtkKWScale::SetActiveBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-activebackground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWScale::SetBorderWidth(int width) { this->SetConfigurationOptionAsInt("-bd", width); } //---------------------------------------------------------------------------- int vtkKWScale::GetBorderWidth() { return this->GetConfigurationOptionAsInt("-bd"); } //---------------------------------------------------------------------------- void vtkKWScale::SetRelief(int relief) { this->SetConfigurationOption( "-relief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWScale::SetReliefToRaised() { this->SetRelief(vtkKWOptions::ReliefRaised); }; void vtkKWScale::SetReliefToSunken() { this->SetRelief(vtkKWOptions::ReliefSunken); }; void vtkKWScale::SetReliefToFlat() { this->SetRelief(vtkKWOptions::ReliefFlat); }; void vtkKWScale::SetReliefToRidge() { this->SetRelief(vtkKWOptions::ReliefRidge); }; void vtkKWScale::SetReliefToSolid() { this->SetRelief(vtkKWOptions::ReliefSolid); }; void vtkKWScale::SetReliefToGroove() { this->SetRelief(vtkKWOptions::ReliefGroove); }; //---------------------------------------------------------------------------- int vtkKWScale::GetRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-relief")); } //---------------------------------------------------------------------------- void vtkKWScale::SetFont(const char *font) { this->SetConfigurationOption("-font", font); } //---------------------------------------------------------------------------- const char* vtkKWScale::GetFont() { return this->GetConfigurationOption("-font"); } //---------------------------------------------------------------------------- void vtkKWScale::GetTroughColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-troughcolor", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWScale::GetTroughColor() { return this->GetConfigurationOptionAsColor("-troughcolor"); } //---------------------------------------------------------------------------- void vtkKWScale::SetTroughColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-troughcolor", r, g, b); } //---------------------------------------------------------------------------- void vtkKWScale::Bind() { this->SetBinding("", this, "ButtonPressCallback"); this->SetBinding("", this, "ButtonReleaseCallback"); this->AddBinding("", this, "DisableScaleValueCallbackOff"); this->AddBinding("", this, "DisableScaleValueCallbackOn"); char *command = NULL; this->SetObjectMethodCommand(&command, this, "ScaleValueCallback"); this->SetConfigurationOption("-command", command); delete [] command; } //---------------------------------------------------------------------------- void vtkKWScale::UnBind() { this->RemoveBinding(""); this->RemoveBinding(""); this->SetConfigurationOption("-command", NULL); } //---------------------------------------------------------------------------- void vtkKWScale::SetResolution(double r) { if (this->Resolution == r) { return; } this->Resolution = r; this->Modified(); this->UpdateResolution(); } //---------------------------------------------------------------------------- void vtkKWScale::UpdateResolution() { if (this->IsCreated()) { this->SetConfigurationOptionAsDouble("-resolution", this->Resolution); } } //---------------------------------------------------------------------------- void vtkKWScale::SetValue(double num) { if (this->ClampValue) { if (this->Range[1] > this->Range[0]) { if (num > this->Range[1]) { num = this->Range[1]; } else if (num < this->Range[0]) { num = this->Range[0]; } } else { if (num < this->Range[1]) { num = this->Range[1]; } else if (num > this->Range[0]) { num = this->Range[0]; } } } if (this->Value == num) { return; } this->Value = num; this->Modified(); this->UpdateValue(); this->InvokeCommand(this->GetValue()); } //---------------------------------------------------------------------------- void vtkKWScale::UpdateValue() { if (!this->IsCreated()) { return; } int was_disabled = !this->GetEnabled(); if (was_disabled) { this->SetState(vtkKWOptions::StateNormal); this->SetEnabled(1); } this->Script("%s set %g", this->GetWidgetName(), this->Value); if (was_disabled) { this->SetState(vtkKWOptions::StateDisabled); this->SetEnabled(0); } } //---------------------------------------------------------------------------- void vtkKWScale::SetRange(double min, double max) { if (this->Range[0] == min && this->Range[1] == max) { return; } this->Range[0] = min; this->Range[1] = max; this->Modified(); this->UpdateRange(); } //---------------------------------------------------------------------------- void vtkKWScale::UpdateRange() { if (this->IsCreated()) { this->SetConfigurationOptionAsDouble("-from", this->Range[0]); this->SetConfigurationOptionAsDouble("-to", this->Range[1]); } } //---------------------------------------------------------------------------- void vtkKWScale::ScaleValueCallback(double num) { if (this->DisableScaleValueCallback) { return; } this->SetValue(num); } //---------------------------------------------------------------------------- void vtkKWScale::ButtonPressCallback() { this->InvokeStartCommand(this->GetValue()); } //---------------------------------------------------------------------------- void vtkKWScale::ButtonReleaseCallback() { this->InvokeEndCommand(this->GetValue()); } //---------------------------------------------------------------------------- void vtkKWScale::InvokeScaleCommand(const char *command, double value) { if (!this->DisableCommands && command && *command && this->GetApplication()) { // As a convenience, try to detect if we are manipulating integers, and // invoke the callback with the approriate type. if ((double)((long int)this->Resolution) == this->Resolution) { this->Script("%s %ld", command, (long int)value); } else { this->Script("%s %lf", command, value); } } } //---------------------------------------------------------------------------- void vtkKWScale::SetCommand(vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->Command, object, method); } //---------------------------------------------------------------------------- void vtkKWScale::InvokeCommand(double value) { this->InvokeScaleCommand(this->Command, value); this->InvokeEvent(vtkKWScale::ScaleValueChangingEvent, &value); } //---------------------------------------------------------------------------- void vtkKWScale::SetStartCommand(vtkObject *object, const char * method) { this->SetObjectMethodCommand(&this->StartCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWScale::InvokeStartCommand(double value) { this->InvokeScaleCommand(this->StartCommand, value); this->InvokeEvent(vtkKWScale::ScaleValueStartChangingEvent, &value); } //---------------------------------------------------------------------------- void vtkKWScale::SetEndCommand(vtkObject *object, const char * method) { this->SetObjectMethodCommand(&this->EndCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWScale::InvokeEndCommand(double value) { this->InvokeScaleCommand(this->EndCommand, value); this->InvokeEvent(vtkKWScale::ScaleValueChangedEvent, &value); } //---------------------------------------------------------------------------- void vtkKWScale::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->SetState(this->GetEnabled()); } //---------------------------------------------------------------------------- void vtkKWScale::SetWidth(int width) { this->SetConfigurationOptionAsInt("-width", width); } //---------------------------------------------------------------------------- int vtkKWScale::GetWidth() { return this->GetConfigurationOptionAsInt("-width"); } //---------------------------------------------------------------------------- void vtkKWScale::SetLength(int length) { this->SetConfigurationOptionAsInt("-length", length); } //---------------------------------------------------------------------------- int vtkKWScale::GetLength() { return this->GetConfigurationOptionAsInt("-length"); } //---------------------------------------------------------------------------- void vtkKWScale::SetSliderLength(int length) { this->SetConfigurationOptionAsInt("-sliderlength", length); } //---------------------------------------------------------------------------- int vtkKWScale::GetSliderLength() { return this->GetConfigurationOptionAsInt("-sliderlength"); } //---------------------------------------------------------------------------- void vtkKWScale::SetValueVisibility(int val) { this->SetConfigurationOptionAsInt("-showvalue", val); } //---------------------------------------------------------------------------- int vtkKWScale::GetValueVisibility() { return this->GetConfigurationOptionAsInt("-showvalue"); } //---------------------------------------------------------------------------- void vtkKWScale::SetTickInterval(double val) { this->SetConfigurationOptionAsDouble("-tickinterval", val); } //---------------------------------------------------------------------------- double vtkKWScale::GetTickInterval() { return this->GetConfigurationOptionAsDouble("-tickinterval"); } //--------------------------------------------------------------------------- void vtkKWScale::SetLabelText(const char *label) { this->SetTextOption("-label", label); } //--------------------------------------------------------------------------- const char* vtkKWScale::GetLabelText() { return this->GetTextOption("-label"); } //---------------------------------------------------------------------------- void vtkKWScale::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Value: " << this->Value << endl; os << indent << "Resolution: " << this->Resolution << endl; os << indent << "Orientation: " << this->Orientation << endl; os << indent << "Range: " << this->Range[0] << "..." << this->Range[1] << endl; os << indent << "DisableCommands: " << (this->DisableCommands ? "On" : "Off") << endl; os << indent << "ClampValue: " << (this->ClampValue ? "On" : "Off") << endl; os << indent << "DisableScaleValueCallback: " << (this->DisableScaleValueCallback ? "On" : "Off") << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWFrameWithLabel.cxx0000644000175000017500000004333611365164712021441 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWFrameWithLabel.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWFrameWithLabel.h" #include "vtkKWApplication.h" #include "vtkKWDragAndDropTargetSet.h" #include "vtkKWFrame.h" #include "vtkKWInternationalization.h" #include "vtkKWIcon.h" #include "vtkKWLabel.h" #include "vtkKWLabelWithLabel.h" #include "vtkKWTkUtilities.h" #include "vtkObjectFactory.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWFrameWithLabel ); vtkCxxRevisionMacro(vtkKWFrameWithLabel, "$Revision: 1.14 $"); int vtkKWFrameWithLabel::DefaultLabelCase = vtkKWFrameWithLabel::LabelCaseUppercaseFirst; int vtkKWFrameWithLabel::DefaultLabelFontWeight = vtkKWFrameWithLabel::LabelFontWeightBold; int vtkKWFrameWithLabel::DefaultAllowFrameToCollapse = 1; //---------------------------------------------------------------------------- vtkKWFrameWithLabel::vtkKWFrameWithLabel() { this->ExternalMarginFrame = vtkKWFrame::New(); this->CollapsibleFrame = vtkKWFrame::New(); this->InternalMarginFrame = vtkKWFrame::New(); this->Frame = vtkKWFrame::New(); this->LabelFrame = vtkKWFrame::New(); this->Label = vtkKWLabelWithLabel::New(); this->Icon = vtkKWLabel::New(); this->IconData = vtkKWIcon::New(); this->AllowFrameToCollapse = 1; this->LimitedEditionModeIconVisibility = 0; this->ChangePackingOnCollapse = 0; } //---------------------------------------------------------------------------- vtkKWFrameWithLabel::~vtkKWFrameWithLabel() { if (this->Icon) { this->Icon->Delete(); this->Icon = NULL; } if (this->IconData) { this->IconData->Delete(); this->IconData = NULL; } if (this->Label) { this->Label->Delete(); this->Label = NULL; } if (this->Frame) { this->Frame->Delete(); this->Frame = NULL; } if (this->LabelFrame) { this->LabelFrame->Delete(); this->LabelFrame = NULL; } if (this->ExternalMarginFrame) { this->ExternalMarginFrame->Delete(); this->ExternalMarginFrame = NULL; } if (this->InternalMarginFrame) { this->InternalMarginFrame->Delete(); this->InternalMarginFrame = NULL; } if (this->CollapsibleFrame) { this->CollapsibleFrame->Delete(); this->CollapsibleFrame = NULL; } } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); this->ExternalMarginFrame->SetParent(this); this->ExternalMarginFrame->Create(); this->CollapsibleFrame->SetParent(this); this->CollapsibleFrame->Create(); this->CollapsibleFrame->SetReliefToGroove(); this->CollapsibleFrame->SetBorderWidth(2); this->InternalMarginFrame->SetParent(this->CollapsibleFrame); this->InternalMarginFrame->Create(); this->Frame->SetParent(this->CollapsibleFrame); this->Frame->Create(); this->LabelFrame->SetParent(this); this->LabelFrame->Create(); this->Label->SetParent(this->LabelFrame); this->Label->Create(); this->Label->SetBorderWidth(0); this->Label->ExpandWidgetOff(); vtkKWLabel *label = this->GetLabel(); label->SetBorderWidth(1); label->SetPadX(0); label->SetPadY(0); // At this point, although this->Label (a labeled label) has been created, // UpdateEnableState() has been called already and ShowLabelOff() has been // called on the label. Therefore, the label of this->Label was not created // since it is lazy created/allocated on the fly only when needed. // Force label icon to be created now, so that we can set its image option. this->Label->LabelVisibilityOn(); this->GetLabel()->SetBinding("", this, "LabelDoubleClickCallback"); label = this->GetLabelIcon(); label->SetImageToPredefinedIcon(vtkKWIcon::IconNuvola16x16ActionsEncrypted); label->SetBorderWidth(0); label->SetPadX(0); label->SetPadY(0); const char *lem_name = this->GetApplication()->GetLimitedEditionModeName() ? this->GetApplication()->GetLimitedEditionModeName() : "Limited Edition"; char buffer[500]; sprintf(buffer, k_("This feature is not available in '%s'mode."), lem_name); this->GetLabelIcon()->SetBalloonHelpString(buffer); if (vtkKWFrameWithLabel::DefaultLabelFontWeight == vtkKWFrameWithLabel::LabelFontWeightBold) { vtkKWTkUtilities::ChangeFontWeightToBold(this->GetLabel()); } this->IconData->SetImage(vtkKWIcon::IconShrink); this->Icon->SetParent(this); this->Icon->Create(); this->Icon->SetImageToIcon(this->IconData); this->Icon->SetBalloonHelpString( ks_("Frame With Label|Shrink or expand the frame")); this->Script( "pack %s -fill x -expand n -anchor nw -side top", this->ExternalMarginFrame->GetWidgetName()); this->Script( "pack %s -fill both -expand y -anchor nw -side top", this->CollapsibleFrame->GetWidgetName()); this->Script( "pack %s -fill x -expand n -side top", this->InternalMarginFrame->GetWidgetName()); this->Script( "pack %s -padx 2 -pady 2 -fill both -expand yes -side top", this->Frame->GetWidgetName()); this->Script( "pack %s -anchor nw -side left -fill both -expand y -padx 2 -pady 0", this->Label->GetWidgetName()); this->Script("place %s -relx 0 -x 5 -y 0 -anchor nw", this->LabelFrame->GetWidgetName()); this->Label->Raise(); this->Icon->SetBinding("",this,"CollapseButtonCallback"); // If the label frame get resize, reset the margins vtksys_stl::string callback("catch {"); callback += this->GetTclName(); callback += " AdjustMarginCallback}"; this->LabelFrame->SetBinding("", NULL, callback.c_str()); } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::SetWidth(int width) { this->Superclass::SetWidth(width); if (this->CollapsibleFrame) { this->CollapsibleFrame->SetWidth(width); width -= this->CollapsibleFrame->GetBorderWidth() * 2; if (this->InternalMarginFrame) { this->InternalMarginFrame->SetWidth(width); } if (this->Frame) { int padx = 2; // see Create() this->Frame->SetWidth(width - padx * 2); } } } //---------------------------------------------------------------------------- int vtkKWFrameWithLabel::GetWidth() { int width = this->Superclass::GetWidth(); if (this->CollapsibleFrame) { int internal_width = this->CollapsibleFrame->GetWidth(); if (internal_width > width) { width = internal_width; } if (this->Frame) { int padx = 2; // see Create() internal_width = this->Frame->GetWidth() + padx * 2 + this->CollapsibleFrame->GetBorderWidth() * 2; if (internal_width > width) { width = internal_width; } } } return width; } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::SetHeight(int height) { this->Superclass::SetHeight(height); if (this->CollapsibleFrame) { if (this->ExternalMarginFrame) { height -= this->ExternalMarginFrame->GetHeight(); } this->CollapsibleFrame->SetHeight(height); height -= this->CollapsibleFrame->GetBorderWidth() * 2; if (this->InternalMarginFrame) { height -= this->InternalMarginFrame->GetHeight(); } if (this->Frame) { int pady = 2; // see Create() this->Frame->SetHeight(height - pady * 2); } } } //---------------------------------------------------------------------------- int vtkKWFrameWithLabel::GetHeight() { int height = this->Superclass::GetHeight(); if (this->CollapsibleFrame) { int internal_height = this->CollapsibleFrame->GetHeight(); if (this->ExternalMarginFrame) { internal_height += this->ExternalMarginFrame->GetHeight(); } if (internal_height > height) { height = internal_height; } if (this->Frame) { int pady = 2; // see Create() internal_height = this->Frame->GetHeight() + pady * 2 + this->CollapsibleFrame->GetBorderWidth() * 2; if (this->ExternalMarginFrame) { internal_height += this->ExternalMarginFrame->GetHeight(); } if (this->InternalMarginFrame) { internal_height += this->InternalMarginFrame->GetHeight(); } if (internal_height > height) { height = internal_height; } } } return height; } //---------------------------------------------------------------------------- vtkKWLabel* vtkKWFrameWithLabel::GetLabel() { if (this->Label) { return this->Label->GetWidget(); } return NULL; } //---------------------------------------------------------------------------- vtkKWLabel* vtkKWFrameWithLabel::GetLabelIcon() { if (this->Label) { return this->Label->GetLabel(); } return NULL; } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::SetLabelText(const char *text) { if (!text) { return; } if (vtkKWFrameWithLabel::DefaultLabelCase == vtkKWFrameWithLabel::LabelCaseUserSpecified) { this->GetLabel()->SetText(text); } else { vtksys_stl::string res; switch (vtkKWFrameWithLabel::DefaultLabelCase) { case vtkKWFrameWithLabel::LabelCaseUppercaseFirst: res = vtksys::SystemTools::CapitalizedWords(text); break; case vtkKWFrameWithLabel::LabelCaseLowercaseFirst: res = vtksys::SystemTools::UnCapitalizedWords(text); break; } this->GetLabel()->SetText(res.c_str()); } } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::AdjustMarginCallback() { if (this->IsCreated() && this->IconData) { // Get the height of the label frame, and share it between // the two borders (frame). int height = 0, width = 0; vtkKWTkUtilities::GetWidgetRequestedSize( this->LabelFrame, &width, &height); // If the frame has not been packed yet, reqheight will return 1, // so try the hard way by checking what's inside the pack, provided // that it's simple (i.e. packed in a single row or column) if (height <= 1) { vtkKWTkUtilities::GetSlavesBoundingBoxInPack( this->LabelFrame, &width, &height); } // Don't forget the show/hide collapse icon, it might be bigger than // the LabelFrame contents (really ?) if (vtkKWFrameWithLabel::DefaultAllowFrameToCollapse && this->AllowFrameToCollapse && height < this->IconData->GetHeight()) { height = this->IconData->GetHeight(); } int border_h = height / 2; int border2_h = height / 2; #ifdef _WIN32 border_h++; #else border2_h++; #endif this->ExternalMarginFrame->SetHeight(border_h); this->InternalMarginFrame->SetHeight(border2_h); if (vtkKWFrameWithLabel::DefaultAllowFrameToCollapse && this->AllowFrameToCollapse) { this->Script("place %s -relx 1 -x %d -rely 0 -y %d -anchor center", this->Icon->GetWidgetName(), -this->IconData->GetWidth() -1, border_h + 1); this->Icon->Raise(); } // Now check if we need to expand the widget to show the label // This is required if the frame is empty for example, since // the Label is 'placed', it does not claim its own space int min_width = width + this->IconData->GetWidth() + 40; if (this->GetWidth() < min_width) { vtkKWTkUtilities::GetWidgetRequestedSize(this, &width, NULL); if (width < min_width) { this->SetWidth(min_width); } } } } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::ExpandFrame() { if (this->Frame && this->Frame->IsCreated()) { this->Script("pack %s -fill both -expand yes -padx 2 -pady 2", this->Frame->GetWidgetName()); if (this->ChangePackingOnCollapse && this->IsPacked()) { this->Script("pack configure %s -expand y", this->GetWidgetName()); } } if (this->IconData && this->Icon) { this->IconData->SetImage(vtkKWIcon::IconShrink); this->Icon->SetImageToIcon(this->IconData); } } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::CollapseFrame() { if (this->Frame && this->Frame->IsCreated()) { this->Script("pack forget %s", this->Frame->GetWidgetName()); this->SetWidth(this->GetWidth()); this->SetHeight(this->GetHeight()); if (this->ChangePackingOnCollapse && this->IsPacked()) { this->Script("pack configure %s -expand n", this->GetWidgetName()); } } if (this->IconData && this->Icon) { this->IconData->SetImage(vtkKWIcon::IconExpand); this->Icon->SetImageToIcon(this->IconData); } } //---------------------------------------------------------------------------- int vtkKWFrameWithLabel::IsFrameCollapsed() { return (this->Frame && this->Frame->IsCreated() && !this->Frame->IsPacked()); } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::LabelDoubleClickCallback() { this->CollapseButtonCallback(); } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::CollapseButtonCallback() { if (vtkKWFrameWithLabel::DefaultAllowFrameToCollapse && this->AllowFrameToCollapse) { if (this->IsFrameCollapsed()) { this->ExpandFrame(); } else { this->CollapseFrame(); } } } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::SetDefaultAllowFrameToCollapse(int arg) { vtkKWFrameWithLabel::DefaultAllowFrameToCollapse = arg; } //---------------------------------------------------------------------------- int vtkKWFrameWithLabel::GetDefaultAllowFrameToCollapse() { return vtkKWFrameWithLabel::DefaultAllowFrameToCollapse; } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::SetDefaultLabelFontWeight(int arg) { vtkKWFrameWithLabel::DefaultLabelFontWeight = arg; } //---------------------------------------------------------------------------- int vtkKWFrameWithLabel::GetDefaultLabelFontWeight() { return vtkKWFrameWithLabel::DefaultLabelFontWeight; } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::SetDefaultLabelCase(int v) { vtkKWFrameWithLabel::DefaultLabelCase = v; } //---------------------------------------------------------------------------- int vtkKWFrameWithLabel::GetDefaultLabelCase() { return vtkKWFrameWithLabel::DefaultLabelCase; } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::SetLimitedEditionModeIconVisibility(int arg) { if (this->LimitedEditionModeIconVisibility == arg) { return; } this->LimitedEditionModeIconVisibility = arg; this->Modified(); this->UpdateEnableState(); } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::UpdateEnableState() { this->Superclass::UpdateEnableState(); // Disable only the label part of the labeled label // (we want the icon not to look disabled) this->PropagateEnableState(this->GetLabel()); int limited = (this->GetApplication() && this->GetApplication()->GetLimitedEditionMode()); if (limited && this->LimitedEditionModeIconVisibility && !this->GetEnabled()) { this->Label->LabelVisibilityOn(); } else { this->Label->LabelVisibilityOff(); } this->PropagateEnableState(this->Frame); this->PropagateEnableState(this->LabelFrame); this->PropagateEnableState(this->ExternalMarginFrame); this->PropagateEnableState(this->InternalMarginFrame); this->PropagateEnableState(this->CollapsibleFrame); this->PropagateEnableState(this->Icon); } //---------------------------------------------------------------------------- vtkKWDragAndDropTargetSet* vtkKWFrameWithLabel::GetDragAndDropTargetSet() { int exist = this->HasDragAndDropTargetSet(); vtkKWDragAndDropTargetSet *targets = this->Superclass::GetDragAndDropTargetSet(); if (!exist) { targets->SetSourceAnchor(this->GetLabel()); } return targets; } //---------------------------------------------------------------------------- void vtkKWFrameWithLabel::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "AllowFrameToCollapse: " << (this->AllowFrameToCollapse ? "On" : "Off") << endl; os << indent << "ChangePackingOnCollapse: " << (this->ChangePackingOnCollapse ? "On" : "Off") << endl; os << indent << "Frame: " << this->Frame << endl; os << indent << "LabelFrame: " << this->LabelFrame << endl; os << indent << "Groove: " << this->CollapsibleFrame << endl; os << indent << "Label: " << this->Label << endl; os << indent << "LimitedEditionModeIconVisibility: " << (this->LimitedEditionModeIconVisibility ? "On" : "Off") << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWUserInterfaceManagerNotebook.cxx0000644000175000017500000012070211075261666024343 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWUserInterfaceManagerNotebook.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWUserInterfaceManagerNotebook.h" #include "vtkKWDragAndDropTargetSet.h" #include "vtkKWFrameWithLabel.h" #include "vtkKWLabel.h" #include "vtkKWNotebook.h" #include "vtkKWTkUtilities.h" #include "vtkKWUserInterfacePanel.h" #include "vtkObjectFactory.h" #include #include #include //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWUserInterfaceManagerNotebook); vtkCxxRevisionMacro(vtkKWUserInterfaceManagerNotebook, "$Revision: 1.12 $"); //---------------------------------------------------------------------------- class vtkKWUserInterfaceManagerNotebookInternals { public: typedef vtksys_stl::list DragAndDropEntriesContainer; typedef vtksys_stl::list::iterator DragAndDropEntriesContainerIterator; typedef vtksys_stl::list::reverse_iterator DragAndDropEntriesContainerReverseIterator; DragAndDropEntriesContainer DragAndDropEntries; }; //---------------------------------------------------------------------------- vtkKWUserInterfaceManagerNotebook::vtkKWUserInterfaceManagerNotebook() { // The parent class (vtkKWUserInterfaceManager) initializes IdCounter so that // panel IDs starts at 0. In this class, a panel ID will map to a notebook // tag (a tag is an integer associated to each notebook page). The default // tag, if not specified, is 0. By starting at 1 we will avoid mixing managed // and unmanaged pages (unmanaged pages are directly added to the notebook // without going through the manager). this->IdCounter = 1; this->Notebook = NULL; this->EnableDragAndDrop = 0; this->LockDragAndDropEntries = 0; this->Internals = new vtkKWUserInterfaceManagerNotebookInternals; } //---------------------------------------------------------------------------- vtkKWUserInterfaceManagerNotebook::~vtkKWUserInterfaceManagerNotebook() { this->SetNotebook(NULL); // Delete all d&d entries this->DeleteAllDragAndDropEntries(); // Delete the container delete this->Internals; } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::SetNotebook(vtkKWNotebook *_arg) { vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting Notebook to " << _arg); if (this->Notebook == _arg) { return; } if (this->IsCreated() && _arg) { vtkErrorMacro("The notebook cannot be changed once the manager " "has been created."); return; } if (this->Notebook != NULL) { this->Notebook->UnRegister(this); } this->Notebook = _arg; if (this->Notebook != NULL) { this->Notebook->Register(this); } this->Modified(); } //---------------------------------------------------------------------------- vtkKWApplication* vtkKWUserInterfaceManagerNotebook::GetApplication() { if (!this->Superclass::GetApplication() && this->Notebook && this->Notebook->GetApplication()) { this->SetApplication(this->Notebook->GetApplication()); } return this->Superclass::GetApplication(); } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::Create() { if (this->IsCreated()) { vtkErrorMacro("The panel is already created"); return; } // We need a notebook if (!this->Notebook) { vtkErrorMacro("A notebook must be associated to this manager before it " " is created"); return; } // Create the superclass instance (and set the application) this->Superclass::Create(); } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::AddPage( vtkKWUserInterfacePanel *panel, const char *title, const char *balloon, vtkKWIcon *icon) { if (!this->IsCreated()) { vtkErrorMacro("Can not add a page if the manager has not been created."); return -1; } if (!panel) { vtkErrorMacro("Can not add a page to a NULL panel."); return -1; } if (!this->HasPanel(panel)) { vtkErrorMacro("Can not add a page to a panel that is not in the manager."); return -1; } int tag = this->GetPanelId(panel); if (tag < 0) { vtkErrorMacro("Can not access the panel to add a page to."); return -1; } // Use the panel id as a tag in the notebook, so that the pages belonging // to this panel will correspond to notebook pages sharing a same tag. return this->Notebook->AddPage(title, balloon, icon, tag); } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::RemovePage( vtkKWUserInterfacePanel *panel, const char *title) { if (!this->IsCreated()) { vtkErrorMacro( "Can not remove a page if the manager has not been created."); return -1; } if (!panel) { vtkErrorMacro("Can not remove a page from a NULL panel."); return -1; } if (!this->HasPanel(panel)) { vtkErrorMacro( "Can not remove a page from a panel that is not in the manager."); return -1; } int tag = this->GetPanelId(panel); if (tag < 0) { vtkErrorMacro("Can not access the panel to remove a page from."); return -1; } // Use the panel id as a tag in the notebook, so that the pages belonging // to this panel will correspond to notebook pages sharing a same tag. int id = this->Notebook->GetPageId(title, tag); if (id >= 0) { this->Notebook->RemovePage(id); } return id; } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::SetPageTitle( int id, const char *str) { if (!this->IsCreated()) { vtkErrorMacro("Can not set a page's title if the manager has not been created."); return; } this->Notebook->SetPageTitle(id, str); } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::SetPageBalloonHelpString( int id, const char *str) { if (!this->IsCreated()) { vtkErrorMacro("Can not set a page's balloon help string if the manager has not been created."); return; } this->Notebook->SetPageBalloonHelpString(id, str); } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::SetPageIcon( int id, vtkKWIcon *icon) { if (!this->IsCreated()) { vtkErrorMacro("Can not set a page's icon if the manager has not been created."); return; } this->Notebook->SetPageIcon(id, icon); } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::SetPageIconToPredefinedIcon( int id, int icon_index) { if (!this->IsCreated()) { vtkErrorMacro("Can not set a page's icon if the manager has not been created."); return; } this->Notebook->SetPageIconToPredefinedIcon(id, icon_index); } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWUserInterfaceManagerNotebook::GetPageWidget(int id) { if (!this->IsCreated()) { vtkErrorMacro("Can not query a page if the manager has not been created."); return NULL; } // Since each page has a unique id, whatever the panel it belongs to, just // retrieve the frame of the corresponding notebook page. return this->Notebook->GetFrame(id); } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWUserInterfaceManagerNotebook::GetPageWidget( vtkKWUserInterfacePanel *panel, const char *title) { if (!this->IsCreated()) { vtkErrorMacro("Can not query a page if the manager has not been created."); return NULL; } if (!panel) { vtkErrorMacro("Can not query a page from a NULL panel."); return NULL; } if (!this->HasPanel(panel)) { vtkErrorMacro("Can not query a page from a panel that is not " "in the manager."); return NULL; } int tag = this->GetPanelId(panel); if (tag < 0) { vtkErrorMacro("Can not access the panel to query a page."); return NULL; } // Access the notebook page that has this specific title among the notebook // pages that share the same tag (i.e. among the pages that belong to the // same panel). This allow pages from different panels to have the same // title. return this->Notebook->GetFrame(title, tag); } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWUserInterfaceManagerNotebook::GetPagesParentWidget( vtkKWUserInterfacePanel *vtkNotUsed(panel)) { // Here we probably need this->Notebook->Body but it's not a public member return this->Notebook; } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::RaisePage(int id) { if (!this->IsCreated()) { vtkErrorMacro("Can not raise a page if the manager has not been created."); return; } int tag = this->Notebook->GetPageTag(id); vtkKWUserInterfacePanel *panel = this->GetPanel(tag); if (!panel) { vtkErrorMacro("Can not raise a page from a NULL panel."); return; } // Make sure the panel is shown (and created) this->ShowPanel(panel); // Since each page has a unique id, whatever the panel it belongs to, just // raise the corresponding notebook page. this->Notebook->RaisePage(id); } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::RaisePage( vtkKWUserInterfacePanel *panel, const char *title) { if (!this->IsCreated()) { vtkErrorMacro("Can not query a page if the manager has not been created."); return; } if (!panel) { vtkErrorMacro("Can not raise a page from a NULL panel."); return; } if (!this->HasPanel(panel)) { vtkErrorMacro("Can not raise a page from a panel that is not " "in the manager."); return; } // Make sure the panel is shown (and created) this->ShowPanel(panel); // Raise the notebook page that has this specific title among the notebook // pages that share the same tag (i.e. among the pages that belong to the // same panel). This allow pages from different panels to have the same // title. int tag = this->GetPanelId(panel); if (tag < 0) { vtkErrorMacro("Can not access the panel to raise a page."); return; } this->Notebook->RaisePage(title, tag); } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::RaisePanel( vtkKWUserInterfacePanel *panel) { if (!this->IsCreated()) { vtkErrorMacro("Can not raise pages if the manager has not been created."); return 0; } if (!panel) { vtkErrorMacro("Can not raise the pages from a NULL panel."); return 0; } if (!this->HasPanel(panel)) { vtkErrorMacro("Can not raise the pages from a panel that is not " "in the manager."); return 0; } // As a convenience, if the panel that this page was created for has // not been created yet, it is created now. This allow the GUI creation to // be delayed until it is really needed. if (!panel->IsCreated()) { panel->Create(); } // Show the pages that share the same tag (i.e. the pages that belong to the // same panel). int tag = this->GetPanelId(panel); if (tag < 0) { vtkErrorMacro("Can not access the panel to show its pages."); return 0; } // If the page raised at the moment is part of this panel, then we are // OK already, otherwise raise a page. int current_id = this->Notebook->GetRaisedPageId(); if (!current_id || tag != this->Notebook->GetPageTag(current_id)) { this->Notebook->RaiseFirstPageMatchingTag(tag); } // Then show the remaining pages in the panel if (!this->ShowPanel(panel)) { return 0; } // If there were pages matching that tag, but we end up with the raised // page not matching that tag, then we failed (maybe because of the notebook // constraints, the number of pages already pinned, etc). current_id = this->Notebook->GetRaisedPageId(); if (current_id && this->Notebook->GetNumberOfPagesMatchingTag(tag) && this->Notebook->GetPageTag(current_id) != tag) { return 0; } return 1; } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::ShowPanel( vtkKWUserInterfacePanel *panel) { if (!this->IsCreated()) { vtkErrorMacro("Can not show pages if the manager has not been created."); return 0; } if (!panel) { vtkErrorMacro("Can not show the pages from a NULL panel."); return 0; } if (!this->HasPanel(panel)) { vtkErrorMacro("Can not show the pages from a panel that is not " "in the manager."); return 0; } // As a convenience, if the panel that this page was created for has // not been created yet, it is created now. This allow the GUI creation to // be delayed until it is really needed. if (!panel->IsCreated()) { panel->Create(); } // Show the pages that share the same tag (i.e. the pages that belong to the // same panel). int tag = this->GetPanelId(panel); if (tag < 0) { vtkErrorMacro("Can not access the panel to show its pages."); return 0; } // If the notebook is maintaining most recent pages, we have to show // the pages belonging to the same group starting from the last one, so // that the most recent one will be the first page in that group (i.e. // the last shown) if (this->Notebook->GetShowOnlyMostRecentPages()) { this->Notebook->ShowPagesMatchingTagReverse(tag); } else { this->Notebook->ShowPagesMatchingTag(tag); } // If there were pages matching that tag, but we end up with *no* pages // visible for that tag, then we failed (maybe because of the notebook // constraints, the number of pages already pinned, etc). if (this->Notebook->GetNumberOfPagesMatchingTag(tag) && !this->Notebook->GetNumberOfVisiblePagesMatchingTag(tag)) { return 0; } return 1; } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::HidePanel( vtkKWUserInterfacePanel *panel) { if (!this->IsCreated()) { vtkErrorMacro("Can not hide pages if the manager has not been created."); return 0; } if (!panel) { vtkErrorMacro("Can not hide the pages from a NULL panel."); return 0; } if (!this->HasPanel(panel)) { vtkErrorMacro("Can not hide the pages from a panel that is not " "in the manager."); return 0; } // Hide the pages that share the same tag (i.e. the pages that belong to the // same panel). int tag = this->GetPanelId(panel); if (tag < 0) { vtkErrorMacro("Can not access the panel to hide its pages."); return 0; } this->Notebook->UnpinPagesMatchingTag(tag); this->Notebook->HidePagesMatchingTag(tag); return 1; } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::IsPanelVisible( vtkKWUserInterfacePanel *panel) { if (!this->IsCreated()) { vtkErrorMacro( "Can not check pages visiblity if the manager has not been created."); return 0; } if (!panel) { vtkErrorMacro("Can not check the pages visibility from a NULL panel."); return 0; } if (!this->HasPanel(panel)) { vtkErrorMacro("Can not check the pages visibility from a panel that is " "not in the manager."); return 0; } // Pages share the same tag int tag = this->GetPanelId(panel); if (tag < 0) { vtkErrorMacro("Can not access the panel to show its pages."); return 0; } return (this->Notebook->GetNumberOfPagesMatchingTag(tag) == this->Notebook->GetNumberOfVisiblePagesMatchingTag(tag)); } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::RemovePageWidgets( vtkKWUserInterfacePanel *panel) { if (!this->IsCreated()) { vtkErrorMacro("Can not remove page widgets if the manager has not " "been created."); return 0; } if (!panel) { vtkErrorMacro("Can not remove page widgets from a NULL panel."); return 0; } if (!this->HasPanel(panel)) { vtkErrorMacro("Can not remove page widgets from a panel that is not " "in the manager."); return 0; } int tag = this->GetPanelId(panel); if (tag < 0) { vtkErrorMacro("Can not access the panel to remove page widgets."); return 0; } // Remove the pages that share the same tag (i.e. the pages that // belong to the same panel). this->Notebook->RemovePagesMatchingTag(tag); return 1; } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::UpdatePanel( vtkKWUserInterfacePanel *panel) { this->UpdatePanelDragAndDrop(panel); } //---------------------------------------------------------------------------- vtkKWUserInterfacePanel* vtkKWUserInterfaceManagerNotebook::GetPanelFromPageId(int page_id) { if (!this->Notebook || !this->Notebook->HasPage(page_id)) { return 0; } return this->GetPanel(this->Notebook->GetPageTag(page_id)); } //--------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::SetEnableDragAndDrop(int arg) { if (this->EnableDragAndDrop == arg) { return; } this->EnableDragAndDrop = arg; this->Modified(); // Update all panels Drag And Drop bindings int i, nb_panels = this->GetNumberOfPanels(); for (i = 0; i < nb_panels; i++) { vtkKWUserInterfacePanel *panel = this->GetNthPanel(i); if (panel) { this->UpdatePanelDragAndDrop(panel); } } } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::CanWidgetBeDragAndDropped( vtkKWWidget *widget, vtkKWWidget **anchor) { // Check if the widget is a labeled frame (vtkKWFrameWithLabel). // In that case, the widget can be drag&dropped, and its anchor is // the widget's anchor itself. // If we did not find such a frame, check if it is a widget with a single // labeled frame child (i.e. a vtkKWWidget that uses a vtkKWFrameWithLabel // but did not want to inherit from vtkKWFrameWithLabel) // In that case, the widget can be drag&dropped, and its anchor is // the internal labeled frame's anchor. if (widget) { vtkKWFrameWithLabel *frame = vtkKWFrameWithLabel::SafeDownCast(widget); if (!frame && widget->GetNumberOfChildren() == 1) { frame = vtkKWFrameWithLabel::SafeDownCast(widget->GetNthChild(0)); } if (frame) { if (anchor) { *anchor = frame->GetDragAndDropTargetSet()->GetSourceAnchor(); } return 1; } } return 0; } //---------------------------------------------------------------------------- char* vtkKWUserInterfaceManagerNotebook::GetDragAndDropWidgetLabel( vtkKWWidget *widget) { // See CanWidgetBeDragAndDropped() above to understand how we pick // the right part of the widget. if (widget) { vtkKWFrameWithLabel *frame = vtkKWFrameWithLabel::SafeDownCast(widget); if (!frame && widget->GetNumberOfChildren() == 1) { frame = vtkKWFrameWithLabel::SafeDownCast(widget->GetNthChild(0)); } if (frame) { return frame->GetLabel()->GetText(); } } return NULL; } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::UpdatePanelDragAndDrop( vtkKWUserInterfacePanel *panel) { if (!panel) { vtkErrorMacro("Can not update a NULL panel."); return; } if (!this->HasPanel(panel)) { vtkErrorMacro("Can not update a panel that is not in the manager."); return; } if (!this->Notebook) { return; } // Get the pages parent, and check if there are widgets // that can be Drag&Dropped from one page to the other (since they share the // same parent) vtkKWWidget *parent = this->GetPagesParentWidget(panel); if (!parent) { return; } int nb_children = parent->GetNumberOfChildren(); for (int i = 0; i < nb_children; i++) { vtkKWWidget *widget = parent->GetNthChild(i); vtkKWWidget *anchor = 0; // Enable/Disable Drag & Drop for that widget, // the notebook is the drop target if (this->CanWidgetBeDragAndDropped(widget, &anchor)) { if (this->EnableDragAndDrop) { if (!widget->GetDragAndDropTargetSet()->HasTarget(this->Notebook)) { widget->GetDragAndDropTargetSet()->EnableOn(); widget->GetDragAndDropTargetSet()->SetSourceAnchor(anchor); widget->GetDragAndDropTargetSet()->SetTargetEndCommand( this->Notebook, this, "DragAndDropEndCallback"); } } else { if (widget->GetDragAndDropTargetSet()->HasTarget(this->Notebook)) { widget->GetDragAndDropTargetSet()->RemoveTarget(this->Notebook); } } } } } //--------------------------------------------------------------------------- vtkKWUserInterfaceManagerNotebook::WidgetLocation::WidgetLocation() { this->Empty(); } //--------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::WidgetLocation::Empty() { this->PageId = -1; this->AfterWidget = NULL; } //--------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::GetDragAndDropWidgetLocation( vtkKWWidget *widget, WidgetLocation *loc) { if (!loc || !this->Notebook || !widget || !widget->IsPacked()) { return 0; } // Get the page id. The widget is packed -in a notebook page which ID // is the page ID (and which tag is the panel ID by the way) // Extract the -in parameter from the pack info vtksys_ios::ostringstream in_str; if (!vtkKWTkUtilities::GetMasterInPack(widget, in_str)) { return 0; } int page_id = this->Notebook->GetPageIdFromFrameWidgetName(in_str.str().c_str()); if (page_id < 0) { return 0; } loc->Empty(); loc->PageId = page_id; // Query all the slaves in the same page, find the one located before // our widget (if any) so that we can locate the widget among // its sibblings. vtksys_ios::ostringstream prev_slave_str; vtksys_ios::ostringstream next_slave_str; if (vtkKWTkUtilities::GetPreviousAndNextSlaveInPack( this->Notebook->GetFrame(page_id), widget, prev_slave_str, next_slave_str)) { // Get the page's panel, then the panel's page's parent, and check if we // can find the previous widget (since they share the same parent) vtkKWUserInterfacePanel *panel = this->GetPanelFromPageId(page_id); vtkKWWidget *parent = this->GetPagesParentWidget(panel); if (parent) { if (prev_slave_str.str() != "") { loc->AfterWidget = parent->GetChildWidgetWithName(prev_slave_str.str().c_str()); } } } return 1; } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWUserInterfaceManagerNotebook::GetDragAndDropWidgetFromLabelAndLocation( const char *widget_label, const WidgetLocation *loc_hint) { if (!widget_label || !loc_hint) { return NULL; } // Get the page's panel, then the panel's page's parent, and check if we // can find the widget (since they share the same parent) vtkKWWidget *page = this->Notebook->GetFrame(loc_hint->PageId); vtkKWUserInterfacePanel *panel = this->GetPanelFromPageId(loc_hint->PageId); if (!page || !panel) { return NULL; } vtkKWWidget *found = NULL; // Iterate over widget, find the one that has the same label and is packed // -in the same location (for extra safety reason, since several panels // or pages might have a widget with the same label) vtkKWWidget *parent = panel->GetPagesParentWidget(); int nb_children = parent->GetNumberOfChildren(); for (int i = 0; i < nb_children; i++) { vtkKWWidget *child = parent->GetNthChild(i); if (child && child->IsPacked()) { const char *label = this->GetDragAndDropWidgetLabel(child); if (label && !strcmp(label, widget_label)) { vtksys_ios::ostringstream in_str; if (vtkKWTkUtilities::GetMasterInPack(child, in_str)) { int cmp = strcmp(in_str.str().c_str(), page->GetWidgetName()); if (!cmp) { found = child; break; } } } } } return found; } //--------------------------------------------------------------------------- vtkKWUserInterfaceManagerNotebook::DragAndDropEntry::DragAndDropEntry() { this->Widget = NULL; } //--------------------------------------------------------------------------- vtkKWUserInterfaceManagerNotebook::DragAndDropEntry* vtkKWUserInterfaceManagerNotebook::GetLastDragAndDropEntry(vtkKWWidget *widget) { if (this->Internals && widget) { vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerReverseIterator rit = this->Internals->DragAndDropEntries.rbegin(); vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerReverseIterator rend = this->Internals->DragAndDropEntries.rend(); for (; rit != rend; ++rit) { if (*rit && (*rit)->Widget == widget) { return *rit; } } } return NULL; } //--------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::GetNumberOfDragAndDropEntries() { return this->Internals ? (int)this->Internals->DragAndDropEntries.size() : 0; } //--------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::DeleteAllDragAndDropEntries() { if (this->Internals) { vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerIterator it = this->Internals->DragAndDropEntries.begin(); vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerIterator end = this->Internals->DragAndDropEntries.end(); for (; it != end; ++it) { if (*it) { delete (*it); } } this->Internals->DragAndDropEntries.clear(); return 1; } return 0; } //--------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::GetDragAndDropEntry( int idx, ostream &widget_label, ostream &from_panel_name, ostream &from_page_title, ostream &from_after_widget_label, ostream &to_panel_name, ostream &to_page_title, ostream &to_after_widget_label) { if (this->LockDragAndDropEntries || !this->Internals) { return 0; } vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerIterator it = this->Internals->DragAndDropEntries.begin(); vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerIterator end = this->Internals->DragAndDropEntries.end(); for (; it != end && idx; ++it, --idx) { } if (it == this->Internals->DragAndDropEntries.end() || !(*it)) { return 0; } // Widget vtkKWUserInterfaceManagerNotebook::DragAndDropEntry *dd_entry = *it; if (dd_entry->Widget) { widget_label << this->GetDragAndDropWidgetLabel(dd_entry->Widget); } // From // If both the page title and panel name are the same, do not // output the panel name vtkKWUserInterfaceManagerNotebook::WidgetLocation *from_loc = &dd_entry->FromLocation; const char *page_title = NULL; if (this->Notebook && this->Notebook->HasPage(from_loc->PageId)) { page_title = this->Notebook->GetPageTitle(from_loc->PageId); if (page_title) { from_page_title << page_title; } } vtkKWUserInterfacePanel *from_panel = this->GetPanelFromPageId(from_loc->PageId); if (from_panel) { const char *panel_name = from_panel->GetName(); if (panel_name && (!page_title || strcmp(panel_name, page_title))) { from_panel_name << panel_name; } } if (from_loc->AfterWidget) { from_after_widget_label << this->GetDragAndDropWidgetLabel( from_loc->AfterWidget); } // To // If From == To, do not output any location // If both the page title and panel name are the same, do not // output the page title vtkKWUserInterfaceManagerNotebook::WidgetLocation *to_loc = &dd_entry->ToLocation; if (from_loc->PageId != to_loc->PageId) { page_title = NULL; if (this->Notebook && this->Notebook->HasPage(to_loc->PageId)) { page_title = this->Notebook->GetPageTitle(to_loc->PageId); if (page_title) { to_page_title << page_title; } } vtkKWUserInterfacePanel *to_panel = this->GetPanelFromPageId(to_loc->PageId); if (to_panel) { const char *panel_name = to_panel->GetName(); if (panel_name && (!page_title || strcmp(panel_name, page_title))) { to_panel_name << panel_name; } } } if (to_loc->AfterWidget) { to_after_widget_label << this->GetDragAndDropWidgetLabel( to_loc->AfterWidget); } return 1; } //--------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::DragAndDropWidget( const char *widget_label, const char *from_panel_name, const char *from_page_title, const char *from_after_widget_label, const char *to_panel_name, const char *to_page_title, const char *to_after_widget_label) { if (this->LockDragAndDropEntries || !this->Notebook || !widget_label) { return 0; } // From // If there is no panel name, use page title vtkKWUserInterfaceManagerNotebook::WidgetLocation from_loc; if (!from_panel_name) { from_panel_name = from_page_title; } vtkKWUserInterfacePanel *from_panel = this->GetPanel(from_panel_name); if (from_panel && from_page_title) { if (!from_panel->IsCreated()) { from_panel->Create(); } int from_panel_id = this->GetPanelId(from_panel); if (this->Notebook->HasPage(from_page_title, from_panel_id)) { from_loc.PageId = this->Notebook->GetPageId(from_page_title, from_panel_id); } } if (from_after_widget_label) { from_loc.AfterWidget = this->GetDragAndDropWidgetFromLabelAndLocation( from_after_widget_label, &from_loc); } // Widget vtkKWWidget *widget = this->GetDragAndDropWidgetFromLabelAndLocation( widget_label, &from_loc); // To // If there if no "To page title", use "From page title" // If there is no panel name, use page title vtkKWUserInterfaceManagerNotebook::WidgetLocation to_loc; if (!to_page_title) { to_page_title = from_page_title; } if (!to_panel_name) { to_panel_name = to_page_title; } vtkKWUserInterfacePanel *to_panel = this->GetPanel(to_panel_name); if (to_panel && to_page_title) { if (!to_panel->IsCreated()) { to_panel->Create(); } int to_panel_id = this->GetPanelId(to_panel); if (this->Notebook->HasPage(to_page_title, to_panel_id)) { to_loc.PageId = this->Notebook->GetPageId(to_page_title, to_panel_id); } } if (to_after_widget_label) { to_loc.AfterWidget = this->GetDragAndDropWidgetFromLabelAndLocation( to_after_widget_label, &to_loc); } // Move the widget this->DragAndDropWidget(widget, &from_loc, &to_loc); return 1; } //---------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::DragAndDropWidget( vtkKWWidget *widget, const WidgetLocation *from_loc, const WidgetLocation *to_loc) { if (!widget || !from_loc || !to_loc || !this->Notebook || !widget->IsCreated()) { return 0; } // If a page id was specified, then pack in that specific page vtksys_ios::ostringstream in; vtkKWWidget *page = this->Notebook->GetFrame(to_loc->PageId); if (page) { in << " -in " << page->GetWidgetName(); } // If an "after widget" was specified, then pack after that widget vtksys_ios::ostringstream after; if (to_loc->AfterWidget && to_loc->AfterWidget->IsCreated()) { after << " -after " << to_loc->AfterWidget->GetWidgetName(); } this->Notebook->Script( "pack %s -side top %s %s", widget->GetWidgetName(), in.str().c_str(), after.str().c_str()); // Store the fact that this widget was moved this->AddDragAndDropEntry(widget, from_loc, to_loc); return 1; } //--------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::IsDragAndDropWidgetAtOriginalLocation( vtkKWWidget *widget) { if (!widget) { return 0; } vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerIterator it = this->Internals->DragAndDropEntries.begin(); vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerIterator end = this->Internals->DragAndDropEntries.end(); for (; it != end; ++it) { if (*it && (*it)->Widget == widget) { // Check that we have the same location, and that the after widget // is either NULL or a widget that has not moved either return ((*it)->FromLocation.PageId == (*it)->ToLocation.PageId && (*it)->FromLocation.AfterWidget == (*it)->ToLocation.AfterWidget && ((*it)->ToLocation.AfterWidget == NULL || this->IsDragAndDropWidgetAtOriginalLocation( (*it)->ToLocation.AfterWidget))); } } return 1; } //--------------------------------------------------------------------------- int vtkKWUserInterfaceManagerNotebook::AddDragAndDropEntry( vtkKWWidget *widget, const WidgetLocation *from_loc, const WidgetLocation *to_loc) { if (!widget || !from_loc || !to_loc) { return 0; } vtkKWUserInterfaceManagerNotebook::DragAndDropEntry *dd_entry, *prev_entry; vtkKWUserInterfaceManagerNotebook::WidgetLocation from_loc_fixed = *from_loc; // Do we have an entry for that widget already ? // In that case, remove it, and use the previous "from" location as the // current "from" location prev_entry = this->GetLastDragAndDropEntry(widget); if (prev_entry) { vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerIterator pos = vtksys_stl::find(this->Internals->DragAndDropEntries.begin(), this->Internals->DragAndDropEntries.end(), prev_entry); if (pos == this->Internals->DragAndDropEntries.end()) { vtkErrorMacro( "Error while removing previous Drag & Drop entry from the manager."); return 0; } this->Internals->DragAndDropEntries.erase(pos); from_loc_fixed = prev_entry->FromLocation; } // Append and set an entry dd_entry = new vtkKWUserInterfaceManagerNotebook::DragAndDropEntry; this->Internals->DragAndDropEntries.push_back(dd_entry); dd_entry->Widget = widget; dd_entry->FromLocation = from_loc_fixed; dd_entry->ToLocation = *to_loc; if (prev_entry) { delete prev_entry; } // Browse each entry for any entry representing a widget (W) // dropped after the widget (A) we have moved. Since the location // if A is not valid anymore (it has been repack elsewhere), update the // old entry W so that its destination location matches its current location vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerIterator it = this->Internals->DragAndDropEntries.begin(); vtkKWUserInterfaceManagerNotebookInternals::DragAndDropEntriesContainerIterator end = this->Internals->DragAndDropEntries.end(); for (; it != end; ++it) { if (*it && (*it)->ToLocation.AfterWidget == widget) { this->GetDragAndDropWidgetLocation( (*it)->Widget, &((*it)->ToLocation)); } } // Browse each entry, check if it represents an actual motion, if not // then remove it int keep_going; do { keep_going = 0; it = this->Internals->DragAndDropEntries.begin(); end = this->Internals->DragAndDropEntries.end(); while (it != end) { if (*it && this->IsDragAndDropWidgetAtOriginalLocation((*it)->Widget)) { delete *it; this->Internals->DragAndDropEntries.erase(it); keep_going = 1; break; } ++it; } } while (keep_going); #if 0 cout << "-------------------------------" << endl; it->InitTraversal(); while (!it->IsDoneWithTraversal()) { if (it->GetData(dd_entry) == VTK_OK) { cout << this->GetDragAndDropWidgetLabel(dd_entry->Widget) << " :\n"; cout << " - From (" << this->Notebook->GetPageTitle(dd_entry->FromLocation.PageId) << ", "; char *ptr = this->GetDragAndDropWidgetLabel(dd_entry->FromLocation.AfterWidget); cout << (ptr ? ptr : "-") << ") " << endl; cout << " - To (" << this->Notebook->GetPageTitle(dd_entry->ToLocation.PageId) << ", "; ptr = this->GetDragAndDropWidgetLabel(dd_entry->ToLocation.AfterWidget); cout << (ptr ? ptr : "-") << ") " << endl; } it->GoToNextItem(); } #endif return 1; } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::DragAndDropEndCallback( int x, int y, vtkKWWidget *widget, vtkKWWidget *vtkNotUsed(anchor), vtkKWWidget *target) { // The target must be the current notebook if (!this->Notebook || this->Notebook != target) { return; } // Get the current location of the widget vtkKWUserInterfaceManagerNotebook::WidgetLocation from_loc; if (!this->GetDragAndDropWidgetLocation(widget, &from_loc)) { return; } // If the target is a "tab" in the notebook, move the widget to the page // corresponding to that "tab" int page_id = this->Notebook->GetPageIdContainingCoordinatesInTab(x, y); if (page_id >= 0) { if (page_id != this->Notebook->GetRaisedPageId()) { vtkKWUserInterfaceManagerNotebook::WidgetLocation to_loc; to_loc.PageId = page_id; this->DragAndDropWidget(widget, &from_loc, &to_loc); } return; } // If not, first try to find the panel this widget is located in, // then browse the children of the panel to find the drop zone among the // sibling of the dragged widget vtkKWUserInterfacePanel *panel = this->GetPanelFromPageId(from_loc.PageId); if (!panel) { return; } vtkKWWidget *parent = panel->GetPagesParentWidget(); int nb_children = parent->GetNumberOfChildren(); for (int i = 0; i < nb_children; i++) { vtkKWWidget *sibbling = parent->GetNthChild(i); vtkKWWidget *anchor = 0; // If a compliant sibbling was found, move the dragged widget after it if (sibbling != widget && this->CanWidgetBeDragAndDropped(sibbling, &anchor) && sibbling->IsMapped() && vtkKWTkUtilities::ContainsCoordinates(sibbling, x, y)) { vtkKWUserInterfaceManagerNotebook::WidgetLocation to_loc; to_loc.PageId = from_loc.PageId; to_loc.AfterWidget = sibbling; this->DragAndDropWidget(widget, &from_loc, &to_loc); break; } } } //---------------------------------------------------------------------------- void vtkKWUserInterfaceManagerNotebook::PrintSelf( ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Notebook: " << this->Notebook << endl; os << indent << "EnableDragAndDrop: " << (this->EnableDragAndDrop ? "On" : "Off") << endl; os << indent << "LockDragAndDropEntries: " << (this->LockDragAndDropEntries ? "On" : "Off") << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWCheckButton.h0000644000175000017500000003571010751700431020436 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWCheckButton.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWCheckButton - check button widget // .SECTION Description // A simple widget that represents a check button. It can be modified // and queried using the GetSelectedState and SetSelectedState methods. #ifndef __vtkKWCheckButton_h #define __vtkKWCheckButton_h #include "vtkKWCoreWidget.h" class vtkKWIcon; class KWWidgets_EXPORT vtkKWCheckButton : public vtkKWCoreWidget { public: static vtkKWCheckButton* New(); vtkTypeRevisionMacro(vtkKWCheckButton,vtkKWCoreWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get/Toggle the selected state of the check button 0 = off 1 = on virtual void SetSelectedState(int ); virtual int GetSelectedState(); vtkBooleanMacro(SelectedState, int); virtual void ToggleSelectedState(); virtual void Select() { this->SetSelectedState(1); }; virtual void Deselect() { this->SetSelectedState(0); }; // Description: // Tell the widget whether it should use an indicator (check box) virtual void SetIndicatorVisibility(int ind); vtkGetMacro(IndicatorVisibility, int); vtkBooleanMacro(IndicatorVisibility, int); // Description: // Set the text. virtual void SetText(const char* txt); virtual const char* GetText(); // Description: // Set the variable name. // Important: note that this will *not* copy over the previous variable // value to the new one. vtkGetStringMacro(VariableName); virtual void SetVariableName(const char *); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the button is selected or deselected. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - current selected state: int virtual void SetCommand(vtkObject *object, const char *method); // Description: // Events. The SelectedStateChangedEvent is triggered when the button // is selected or deselected. // The following parameters are also passed as client data: // - the current selected state: int //BTX enum { SelectedStateChangedEvent = 10000 }; //ETX // Description: // Set/Get the background color of the widget. virtual void GetBackgroundColor(double *r, double *g, double *b); virtual double* GetBackgroundColor(); virtual void SetBackgroundColor(double r, double g, double b); virtual void SetBackgroundColor(double rgb[3]) { this->SetBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget. virtual void GetForegroundColor(double *r, double *g, double *b); virtual double* GetForegroundColor(); virtual void SetForegroundColor(double r, double g, double b); virtual void SetForegroundColor(double rgb[3]) { this->SetForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the highlight thickness, a non-negative value indicating the // width of the highlight rectangle to draw around the outside of the // widget when it has the input focus. virtual void SetHighlightThickness(int); virtual int GetHighlightThickness(); // Description: // Set/Get the active background color of the widget. An element // (a widget or portion of a widget) is active if the mouse cursor is // positioned over the element and pressing a mouse button will cause some // action to occur. virtual void GetActiveBackgroundColor(double *r, double *g, double *b); virtual double* GetActiveBackgroundColor(); virtual void SetActiveBackgroundColor(double r, double g, double b); virtual void SetActiveBackgroundColor(double rgb[3]) { this->SetActiveBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the active foreground color of the widget. An element // (a widget or portion of a widget) is active if the mouse cursor is // positioned over the element and pressing a mouse button will cause some // action to occur. virtual void GetActiveForegroundColor(double *r, double *g, double *b); virtual double* GetActiveForegroundColor(); virtual void SetActiveForegroundColor(double r, double g, double b); virtual void SetActiveForegroundColor(double rgb[3]) { this->SetActiveForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget when it is disabled. virtual void GetDisabledForegroundColor(double *r, double *g, double *b); virtual double* GetDisabledForegroundColor(); virtual void SetDisabledForegroundColor(double r, double g, double b); virtual void SetDisabledForegroundColor(double rgb[3]) { this->SetDisabledForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the border width, a non-negative value indicating the width of // the 3-D border to draw around the outside of the widget (if such a border // is being drawn; the Relief option typically determines this). virtual void SetBorderWidth(int); virtual int GetBorderWidth(); // Description: // Set/Get the 3-D effect desired for the widget. // The value indicates how the interior of the widget should appear // relative to its exterior. // Valid constants can be found in vtkKWOptions::ReliefType. virtual void SetRelief(int); virtual int GetRelief(); virtual void SetReliefToRaised(); virtual void SetReliefToSunken(); virtual void SetReliefToFlat(); virtual void SetReliefToRidge(); virtual void SetReliefToSolid(); virtual void SetReliefToGroove(); // Description: // Set/Get the padding that will be applied around each widget (in pixels). // Specifies a non-negative value indicating how much extra space to request // for the widget in the X and Y-direction. When computing how large a // window it needs, the widget will add this amount to the width it would // normally need (as determined by the width of the things displayed // in the widget); if the geometry manager can satisfy this request, the // widget will end up with extra internal space around what it displays // inside. virtual void SetPadX(int); virtual int GetPadX(); virtual void SetPadY(int); virtual int GetPadY(); // Description: // Set/Get the anchoring. // Specifies how the information in a widget (e.g. text or a bitmap) is to // be displayed in the widget. // Valid constants can be found in vtkKWOptions::AnchorType. virtual void SetAnchor(int); virtual int GetAnchor(); virtual void SetAnchorToNorth(); virtual void SetAnchorToNorthEast(); virtual void SetAnchorToEast(); virtual void SetAnchorToSouthEast(); virtual void SetAnchorToSouth(); virtual void SetAnchorToSouthWest(); virtual void SetAnchorToWest(); virtual void SetAnchorToNorthWest(); virtual void SetAnchorToCenter(); // Description: // Set/Get the 3-D effect desired for the widget. // Specifies the relief for the button when the indicator is not drawn // (i.e. IndicatorVisibility is Off) and the button is not selected. // The default value is Raised. By setting this option to Flat and setting // IndicatorVisibility to Off and OverRelief to Raised or Flat, the effect // is achieved of having a flat button that raises on mouse-over and which // is depressed when activated. This is the behavior typically exhibited by // the Bold, Italic, and Underline checkbuttons on the toolbar of a // word-processor, for example. // Valid constants can be found in vtkKWOptions::ReliefType. virtual void SetOffRelief(int); virtual int GetOffRelief(); virtual void SetOffReliefToRaised(); virtual void SetOffReliefToSunken(); virtual void SetOffReliefToFlat(); virtual void SetOffReliefToRidge(); virtual void SetOffReliefToSolid(); virtual void SetOffReliefToGroove(); // Description: // Set/Get the 3-D effect desired for the widget. // Specifies an alternative relief for the button, to be used when the mouse // cursor is over the widget. This option can be used to make toolbar // buttons, by configuring SetRelief to Flat and OverRelief to Raised. // Valid constants can be found in vtkKWOptions::ReliefType. // If the value of this option is None, then no alternative relief is used // when the mouse cursor is over the checkbutton. virtual void SetOverRelief(int); virtual int GetOverRelief(); virtual void SetOverReliefToRaised(); virtual void SetOverReliefToSunken(); virtual void SetOverReliefToFlat(); virtual void SetOverReliefToRidge(); virtual void SetOverReliefToSolid(); virtual void SetOverReliefToGroove(); virtual void SetOverReliefToNone(); // Description: // Specifies the font to use when drawing text inside the widget. // You can use predefined font names (e.g. 'system'), or you can specify // a set of font attributes with a platform-independent name, for example, // 'times 12 bold'. In this example, the font is specified with a three // element list: the first element is the font family, the second is the // size, the third is a list of style parameters (normal, bold, roman, // italic, underline, overstrike). Example: 'times 12 {bold italic}'. // The Times, Courier and Helvetica font families are guaranteed to exist // and will be matched to the corresponding (closest) font on your system. // If you are familiar with the X font names specification, you can also // describe the font that way (say, '*times-medium-r-*-*-12*'). virtual void SetFont(const char *font); virtual const char* GetFont(); // Description: // Specifies an image to display in the widget. Typically, if the image // is specified then it overrides other options that specify a bitmap or // textual value to display in the widget. Invoke vtkKWWidget's // SetConfigurationOption("-image", imagename) to use a specific // pre-existing Tk image, or call one of the following functions: // The SetImageToPredefinedIcon method accepts an index to one of the // predefined icon listed in vtkKWIcon. // The SetImageToPixels method sets the image using pixel data. It expects // a pointer to the pixels and the structure of the image, i.e. its width, // height and the pixel_size (how many bytes per pixel, say 3 for RGB, or // 1 for grayscale). If buffer_length = 0, it is computed automatically // from the previous parameters. If it is not, it will most likely indicate // that the buffer has been encoded using base64 and/or zlib. // If pixel_size > 3 (i.e. RGBA), the image is blend the with background // color of the widget. // Check the SetCompoundMode method if you want to display both the // image and the label at the same time. virtual void SetImageToIcon(vtkKWIcon *icon); virtual void SetImageToPredefinedIcon(int icon_index); virtual void SetImageToPixels( const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length = 0); // Description: // Specifies an image to display in the widget when the button is selected. // This option is ignored unless an image has been set for the unselected // state of the button already (see SetImageToIcon). // Typically, if the image is specified then it overrides other options that // specify a bitmap or textual value to display in the widget. // Invoke vtkKWWidget's SetConfigurationOption("-selectimage", imagename) // to use a specific pre-existing Tk image, or call one of the following // functions: // The SetSelectImageToPredefinedIcon method accepts an index to one of the // predefined icon listed in vtkKWIcon. // The SetSelectImageToPixels method sets the image using pixel data. It // expects a pointer to the pixels and the structure of the image, i.e. its // width, height and the pixel_size (how many bytes per pixel, say 3 for RGB, // or 1 for grayscale). If buffer_length = 0, it is computed automatically // from the previous parameters. If it is not, it will most likely indicate // that the buffer has been encoded using base64 and/or zlib. // If pixel_size > 3 (i.e. RGBA), the image is blend the with background // color of the widget. // Check the SetCompoundMode method if you want to display both the // image and the label at the same time. virtual void SetSelectImageToIcon(vtkKWIcon *icon); virtual void SetSelectImageToPredefinedIcon(int icon_index); virtual void SetSelectImageToPixels( const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length = 0); // Description: // Specifies if the widget should display text and bitmaps/images at the // same time, and if so, where the bitmap/image should be placed relative // to the text. // Valid constants can be found in vtkKWOptions::CompoundModeType. // The (default) value CompoundModeNone specifies that the bitmap or image // should (if defined) be displayed instead of the text. virtual void SetCompoundMode(int); virtual int GetCompoundMode(); virtual void SetCompoundModeToNone(); virtual void SetCompoundModeToLeft(); virtual void SetCompoundModeToCenter(); virtual void SetCompoundModeToRight(); virtual void SetCompoundModeToTop(); virtual void SetCompoundModeToBottom(); // Description: // Set/Get the background color to use when the widget is selected. virtual void GetSelectColor(double *r, double *g, double *b); virtual double* GetSelectColor(); virtual void SetSelectColor(double r, double g, double b); virtual void SetSelectColor(double rgb[3]) { this->SetSelectColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Callbacks. Internal, do not use. virtual void CommandCallback(); protected: // Description: // Create the widget. virtual void CreateWidget(); vtkSetStringMacro(InternalText); vtkKWCheckButton(); ~vtkKWCheckButton(); int IndicatorVisibility; char *InternalText; char *VariableName; virtual void Configure(); char *Command; virtual void InvokeCommand(int state); private: vtkKWCheckButton(const vtkKWCheckButton&); // Not implemented void operator=(const vtkKWCheckButton&); // Not Implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWRenderWidget.cxx0000644000175000017500000022222711207300676021170 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWRenderWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWRenderWidget.h" #include "vtkCallbackCommand.h" #include "vtkCamera.h" #include "vtkCommand.h" #include "vtkCornerAnnotation.h" #include "vtkInteractorStyleSwitch.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkProperty2D.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkRendererCollection.h" #include "vtkTextActor.h" #include "vtkTextProperty.h" #include "vtkKWApplication.h" #include "vtkKWColorPickerWidget.h" #include "vtkKWColorPickerDialog.h" #include "vtkKWEvent.h" #include "vtkKWGenericRenderWindowInteractor.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" #include "vtkKWMenu.h" #include "vtkKWTkUtilities.h" #include "vtkKWWindow.h" #ifdef _WIN32 #include "vtkWin32OpenGLRenderWindow.h" #endif #include #include #include vtkStandardNewMacro(vtkKWRenderWidget); vtkCxxRevisionMacro(vtkKWRenderWidget, "$Revision: 1.171 $"); //---------------------------------------------------------------------------- class vtkKWRenderWidgetInternals { public: typedef vtksys_stl::vector RendererPoolType; typedef vtksys_stl::vector::iterator RendererPoolIterator; RendererPoolType RendererPool; RendererPoolType OverlayRendererPool; class TimerAdapter { public: vtkRenderWindowInteractor *Interactor; int TimerId; Tcl_TimerToken TclTimerToken; }; typedef vtksys_stl::map TimerAdapterPoolType; typedef vtksys_stl::map::iterator TimerAdapterPoolTypeIterator; TimerAdapterPoolType TimerAdapterPool; }; //---------------------------------------------------------------------------- void vtkKWRenderWidget::Register(vtkObjectBase* o) { this->Superclass::Register(o); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::UnRegister(vtkObjectBase* o) { this->Superclass::UnRegister(o); } //---------------------------------------------------------------------------- vtkKWRenderWidget::vtkKWRenderWidget() { this->Internals = new vtkKWRenderWidgetInternals; // The vtkTkRenderWidget this->VTKWidget = vtkKWCoreWidget::New(); // Create a render window this->RenderWindow = vtkRenderWindow::New(); this->RenderWindow->SetNumberOfLayers(2); this->RenderWindow->SetAlphaBitPlanes(1); // Create a default (generic) interactor, which is pretty much // the only way to interact with a VTK Tk render widget vtkKWGenericRenderWindowInteractor *interactor = vtkKWGenericRenderWindowInteractor::New(); interactor->SetRenderWidget(this); interactor->SetRenderWindow(this->RenderWindow); this->RenderWindow->SetInteractor(interactor); interactor->Delete(); // Switch to trackball style, it's nicer if (this->GetRenderWindowInteractor()) { vtkInteractorStyleSwitch *istyle = vtkInteractorStyleSwitch::SafeDownCast( this->GetRenderWindowInteractor()->GetInteractorStyle()); if (istyle) { istyle->SetCurrentStyleToTrackballCamera(); } } // Corner annotation this->CornerAnnotation = vtkCornerAnnotation::New(); this->CornerAnnotation->SetMaximumLineHeight(0.07); this->CornerAnnotation->VisibilityOff(); this->SupportCornerAnnotation = 1; // Header annotation this->HeaderAnnotation = vtkTextActor::New(); this->HeaderAnnotation->SetNonLinearFontScale(0.7,10); this->HeaderAnnotation->SetMaximumLineHeight(0.07); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION >= 2) this->HeaderAnnotation->SetTextScaleModeToProp(); #else this->HeaderAnnotation->ScaledTextOn(); #endif this->HeaderAnnotation->VisibilityOff(); vtkTextProperty *tprop = this->HeaderAnnotation->GetTextProperty(); tprop->SetJustificationToCentered(); tprop->SetVerticalJustificationToTop(); tprop->ShadowOn(); tprop->ItalicOn(); vtkCoordinate *coord = this->HeaderAnnotation->GetPositionCoordinate(); coord->SetCoordinateSystemToNormalizedViewport(); coord->SetValue(0.15, 0.0); vtkCoordinate *coord2= this->HeaderAnnotation->GetPosition2Coordinate(); coord2->SetCoordinateSystemToNormalizedViewport(); coord2->SetValue(0.85, 0.92); // Distance units this->DistanceUnits = NULL; // Current state (render mode, in expose, printing, etc) this->RenderMode = vtkKWRenderWidget::StillRender; this->PreviousRenderMode = this->RenderMode; this->RenderState = 1; this->CollapsingRenders = 0; this->InExpose = 0; this->Printing = 0; // Context menu this->UseContextMenu = 0; this->ContextMenu = NULL; this->RendererBackgroundColorRegKey = NULL; this->RendererBackgroundColor2RegKey = NULL; this->RendererGradientBackgroundRegKey = NULL; } //---------------------------------------------------------------------------- vtkKWRenderWidget::~vtkKWRenderWidget() { this->Close(); // Remove all renderers this->RemoveAllRenderers(); this->RemoveAllOverlayRenderers(); // Delete our pool delete this->Internals; if (this->RenderWindow) { vtkKWGenericRenderWindowInteractor *interactor = vtkKWGenericRenderWindowInteractor::SafeDownCast( this->RenderWindow->GetInteractor()); if (interactor) { interactor->SetRenderWidget(NULL); interactor->SetInteractorStyle(NULL); } this->RenderWindow->Delete(); this->RenderWindow = NULL; } /* if (this->Interactor) { this->Interactor->SetRenderWidget(NULL); this->Interactor->SetInteractorStyle(NULL); this->Interactor->Delete(); this->Interactor = NULL; } */ if (this->VTKWidget) { this->VTKWidget->Delete(); this->VTKWidget = NULL; } if (this->CornerAnnotation) { this->CornerAnnotation->Delete(); this->CornerAnnotation = NULL; } if (this->HeaderAnnotation) { this->HeaderAnnotation->Delete(); this->HeaderAnnotation = NULL; } this->SetDistanceUnits(NULL); if (this->ContextMenu) { this->ContextMenu->Delete(); this->ContextMenu = NULL; } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Create the default renderers this->CreateDefaultRenderers(); // Get the first renderer camera, set it to parallel // then make sure all renderers use the same vtkRenderer *ren = this->GetNthRenderer(0); if (ren) { vtkCamera *cam = ren->GetActiveCamera(); if (cam) { cam->ParallelProjectionOn(); int i, nb_renderers = this->GetNumberOfRenderers(); for (i = 1; i < nb_renderers; i++) { ren = this->GetNthRenderer(i); if (ren) { ren->SetActiveCamera(cam); } } nb_renderers = this->GetNumberOfOverlayRenderers(); for (i = 0; i < nb_renderers; i++) { ren = this->GetNthOverlayRenderer(i); if (ren) { ren->SetActiveCamera(cam); } } } } // Install the renderers this->InstallRenderers(); // Create the VTK Tk render widget in VTKWidget char opts[1024]; sprintf(opts, "-rw Addr=%p -width 10 -height 10", this->RenderWindow); this->VTKWidget->SetParent(this); vtkKWWidget::CreateSpecificTkWidget( this->VTKWidget, "vtkTkRenderWidget", opts); this->Script("grid rowconfigure %s 0 -weight 1", this->GetWidgetName()); this->Script("grid columnconfigure %s 0 -weight 1", this->GetWidgetName()); this->Script("grid %s -row 0 -column 0 -sticky nsew", this->VTKWidget->GetWidgetName()); // When the render window is created by the Tk render widget, it // is Render()'ed, which calls Initialize() on the interactor, which // always reset its Enable state. // Make the corner annotation visibile this->SetCornerAnnotationVisibility(1); // Add the bindings this->AddBindings(); // Retrieve default settings this->SetRenderersDefaultValues(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::CreateDefaultRenderers() { // Create two renderers by default (main one and overlay) if (this->GetNumberOfRenderers() <= 0) { vtkRenderer *renderer = vtkRenderer::New(); this->AddRenderer(renderer); renderer->Delete(); } if (this->GetNumberOfOverlayRenderers() <= 0) { vtkRenderer *renderer = vtkRenderer::New(); this->AddOverlayRenderer(renderer); renderer->Delete(); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetRenderersDefaultValues() { double rgb[3]; if (this->GetRendererBackgroundColorRegKey() && this->GetApplication()->RetrieveColorRegistryValue( 2, this->GetRendererBackgroundColorRegKey(), rgb)) { this->SetRendererBackgroundColor(rgb); } if (this->GetRendererBackgroundColor2RegKey() && this->GetApplication()->RetrieveColorRegistryValue( 2, this->GetRendererBackgroundColor2RegKey(), rgb)) { this->SetRendererBackgroundColor2(rgb); } if (this->GetRendererGradientBackgroundRegKey() && this->GetApplication()->HasRegistryValue( 2, "Colors", this->GetRendererGradientBackgroundRegKey())) { this->SetRendererGradientBackground( this->GetApplication()->GetIntRegistryValue( 2, "Colors", this->GetRendererGradientBackgroundRegKey())); } } //---------------------------------------------------------------------------- vtkRenderWindowInteractor* vtkKWRenderWidget::GetRenderWindowInteractor() { if (this->RenderWindow) { return this->RenderWindow->GetInteractor(); } return NULL; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::InstallRenderers() { if (!this->RenderWindow) { return; } this->RenderWindow->GetRenderers()->RemoveAllItems(); int i, nb_renderers = this->GetNumberOfOverlayRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthOverlayRenderer(i); if (renderer) { this->RenderWindow->AddRenderer(renderer); } } nb_renderers = this->GetNumberOfRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { this->RenderWindow->AddRenderer(renderer); } } } //---------------------------------------------------------------------------- vtkRenderer* vtkKWRenderWidget::GetNthRenderer(int index) { if (index < 0 || index >= this->GetNumberOfRenderers()) { return NULL; } return this->Internals->RendererPool[index]; } //---------------------------------------------------------------------------- int vtkKWRenderWidget::GetNumberOfRenderers() { return (int)this->Internals->RendererPool.size(); } //---------------------------------------------------------------------------- int vtkKWRenderWidget::GetRendererIndex(vtkRenderer *ren) { vtkKWRenderWidgetInternals::RendererPoolIterator it = this->Internals->RendererPool.begin(); vtkKWRenderWidgetInternals::RendererPoolIterator end = this->Internals->RendererPool.end(); int rank = 0; for (; it != end; ++it, ++rank) { if (*it == ren) { return rank; } } return -1; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::AddRenderer(vtkRenderer *ren) { if (this->GetRendererIndex(ren) >= 0) { return; } ren->SetLayer(0); this->Internals->RendererPool.push_back(ren); ren->Register(this); this->InstallRenderers(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveRenderer(vtkRenderer *ren) { this->RemoveNthRenderer(this->GetRendererIndex(ren)); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveNthRenderer(int index) { if (index < 0 || index >= this->GetNumberOfRenderers()) { return; } vtkKWRenderWidgetInternals::RendererPoolIterator it = this->Internals->RendererPool.begin() + index; (*it)->RemoveAllViewProps(); (*it)->Delete(); this->Internals->RendererPool.erase(it); this->InstallRenderers(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveAllRenderers() { vtkKWRenderWidgetInternals::RendererPoolIterator it = this->Internals->RendererPool.begin(); vtkKWRenderWidgetInternals::RendererPoolIterator end = this->Internals->RendererPool.end(); for (; it != end; ++it) { (*it)->RemoveAllViewProps(); (*it)->Delete(); } this->Internals->RendererPool.clear(); this->InstallRenderers(); } //---------------------------------------------------------------------------- vtkRenderer* vtkKWRenderWidget::GetNthOverlayRenderer(int index) { if (index < 0 || index >= this->GetNumberOfOverlayRenderers()) { return NULL; } return this->Internals->OverlayRendererPool[index]; } //---------------------------------------------------------------------------- int vtkKWRenderWidget::GetNumberOfOverlayRenderers() { return (int)this->Internals->OverlayRendererPool.size(); } //---------------------------------------------------------------------------- int vtkKWRenderWidget::GetOverlayRendererIndex(vtkRenderer *ren) { vtkKWRenderWidgetInternals::RendererPoolIterator it = this->Internals->OverlayRendererPool.begin(); vtkKWRenderWidgetInternals::RendererPoolIterator end = this->Internals->OverlayRendererPool.end(); int rank = 0; for (; it != end; ++it, ++rank) { if (*it == ren) { return rank; } } return -1; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::AddOverlayRenderer(vtkRenderer *ren) { if (this->GetOverlayRendererIndex(ren) >= 0) { return; } ren->SetLayer(1); this->Internals->OverlayRendererPool.push_back(ren); ren->Register(this); this->InstallRenderers(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveOverlayRenderer(vtkRenderer *ren) { this->RemoveNthOverlayRenderer(this->GetOverlayRendererIndex(ren)); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveNthOverlayRenderer(int index) { if (index < 0 || index >= this->GetNumberOfOverlayRenderers()) { return; } vtkKWRenderWidgetInternals::RendererPoolIterator it = this->Internals->OverlayRendererPool.begin() + index; (*it)->RemoveAllViewProps(); (*it)->Delete(); this->Internals->OverlayRendererPool.erase(it); this->InstallRenderers(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveAllOverlayRenderers() { vtkKWRenderWidgetInternals::RendererPoolIterator it = this->Internals->OverlayRendererPool.begin(); vtkKWRenderWidgetInternals::RendererPoolIterator end = this->Internals->OverlayRendererPool.end(); for (; it != end; ++it) { (*it)->RemoveAllViewProps(); (*it)->Delete(); } this->Internals->OverlayRendererPool.clear(); this->InstallRenderers(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetRendererBackgroundColor(double r, double g, double b) { double color[3]; this->GetRendererBackgroundColor(color, color + 1, color + 2); if (color[0] == r && color[1] == g && color[2] == b) { return; } if (r < 0 || g < 0 || b < 0) { return; } int nb_renderers = this->GetNumberOfRenderers(); for (int i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { renderer->SetBackground(r, g, b); } } this->Render(); color[0] = r; color[1] = g; color[2] = b; this->InvokeEvent( vtkKWRenderWidget::RendererBackgroundColorChangedEvent, color); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::GetRendererBackgroundColor(double *r, double *g, double *b) { int nb_renderers = this->GetNumberOfRenderers(); for (int i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { renderer->GetBackground(*r, *g, *b); return; } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetRendererBackgroundColor2(double r, double g, double b) { double color[3]; this->GetRendererBackgroundColor2(color, color + 1, color + 2); if (color[0] == r && color[1] == g && color[2] == b) { return; } if (r < 0 || g < 0 || b < 0) { return; } int nb_renderers = this->GetNumberOfRenderers(); for (int i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { renderer->SetBackground2(r, g, b); } } this->Render(); color[0] = r; color[1] = g; color[2] = b; this->InvokeEvent( vtkKWRenderWidget::RendererBackgroundColor2ChangedEvent, color); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::GetRendererBackgroundColor2(double *r, double *g, double *b) { int nb_renderers = this->GetNumberOfRenderers(); for (int i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { renderer->GetBackground2(*r, *g, *b); return; } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetRendererGradientBackground(int flag) { if (flag == this->GetRendererGradientBackground()) { return; } int nb_renderers = this->GetNumberOfRenderers(); for (int i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { renderer->SetGradientBackground(flag ? true : false); } } this->Render(); this->InvokeEvent( vtkKWRenderWidget::RendererGradientBackgroundChangedEvent, &flag); } //---------------------------------------------------------------------------- int vtkKWRenderWidget::GetRendererGradientBackground() { int nb_renderers = this->GetNumberOfRenderers(); for (int i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { return renderer->GetGradientBackground(); } } return 0; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ToggleRendererGradientBackground() { this->SetRendererGradientBackground(!this->GetRendererGradientBackground()); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::AddViewProp(vtkProp *prop) { int i, nb_renderers = this->GetNumberOfRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { renderer->AddViewProp(prop); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::AddViewPropToNthRenderer(vtkProp *p, int index) { vtkRenderer *ren = this->GetNthRenderer(index); if (ren && !ren->GetViewProps()->IsItemPresent(p)) { ren->AddViewProp(p); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::AddOverlayViewProp(vtkProp *prop) { int i, nb_renderers = this->GetNumberOfOverlayRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthOverlayRenderer(i); if (renderer) { renderer->AddViewProp(prop); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::AddViewPropToNthOverlayRenderer(vtkProp *p, int index) { vtkRenderer *ren = this->GetNthOverlayRenderer(index); if (ren && !ren->GetViewProps()->IsItemPresent(p)) { ren->AddViewProp(p); } } //---------------------------------------------------------------------------- int vtkKWRenderWidget::HasViewProp(vtkProp *prop) { int i, nb_renderers = this->GetNumberOfRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer && renderer->GetViewProps()->IsItemPresent(prop)) { return 1; } } nb_renderers = this->GetNumberOfOverlayRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthOverlayRenderer(i); if (renderer && renderer->GetViewProps()->IsItemPresent(prop)) { return 1; } } return 0; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveViewProp(vtkProp* prop) { // safe to call both, vtkViewport does a check first int i, nb_renderers = this->GetNumberOfRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { renderer->RemoveViewProp(prop); } } nb_renderers = this->GetNumberOfOverlayRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthOverlayRenderer(i); if (renderer) { renderer->RemoveViewProp(prop); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveAllViewProps() { int i, nb_renderers = this->GetNumberOfRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { renderer->RemoveAllViewProps(); } } nb_renderers = this->GetNumberOfOverlayRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthOverlayRenderer(i); if (renderer) { renderer->RemoveAllViewProps(); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ComputeVisiblePropBounds(int index, double bounds[6]) { vtkRenderer *renderer = this->GetNthRenderer(index); if (renderer) { renderer->ComputeVisiblePropBounds(bounds); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetDistanceUnits(const char* _arg) { if (this->DistanceUnits == NULL && _arg == NULL) { return; } if (this->DistanceUnits && _arg && (!strcmp(this->DistanceUnits, _arg))) { return; } if (this->DistanceUnits) { delete [] this->DistanceUnits; } if (_arg) { this->DistanceUnits = new char[strlen(_arg)+1]; strcpy(this->DistanceUnits, _arg); } else { this->DistanceUnits = NULL; } this->Modified(); this->UpdateAccordingToUnits(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::AddBindings() { if (!this->IsAlive()) { return; } // First remove the old one so that bindings don't get duplicated this->RemoveBindings(); if (this->VTKWidget->IsAlive()) { // Setup some default bindings this->VTKWidget->SetBinding("", this, "ExposeCallback"); } // Many attemps have been made to attach to the VTKWidget // instead, this sounds more logical since the side effect of the callback // is to resize the window, but it seems impossible to do so effetively, // the event for the VTKWidget is probably called to early // in respect to when we can resize the renderwindow // Both the vtkRenderWindow and vtkTkRenderWidget have callbacks that // react to the window manager's configure event, and as such they // resize the render window properly, but this binding is actually only // a helper in case the whole widget is resized but we do not want // to explicitly 'update' or Render. this->SetBinding("", this, "ConfigureCallback %w %h"); this->AddInteractionBindings(); this->AddCallbackCommandObservers(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveBindings() { if (!this->IsAlive()) { return; } if (this->VTKWidget->IsAlive()) { this->VTKWidget->RemoveBinding(""); } this->RemoveBinding(""); this->RemoveInteractionBindings(); this->RemoveCallbackCommandObservers(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::AddInteractionBindings() { if (!this->IsCreated()) { return; } // First remove the old one so that bindings don't get duplicated this->RemoveInteractionBindings(); // If we are disabled, don't do anything if (!this->GetEnabled()) { return; } if (this->VTKWidget->IsAlive()) { this->VTKWidget->SetBinding("", this, "EnterCallback %x %y"); this->VTKWidget->SetBinding("", this, "LeaveCallback %x %y"); this->VTKWidget->SetBinding("", this, "FocusInCallback"); this->VTKWidget->SetBinding("", this, "FocusOutCallback"); typedef struct { const char *Modifier; int Ctrl; int Shift; int Alt; } EventTranslator; EventTranslator translators[] = { { "", 0, 0, 0 }, { "Control-", 1, 0, 0 }, { "Shift-", 0, 1, 0 }, { "Alt-", 0, 0, 1 }, { "Shift-Control-", 1, 1, 0 }, { "Shift-Alt-", 0, 1, 1 }, { "Control-Alt-", 1, 0, 1 }, { "Control-Shift-Alt-", 1, 1, 1 } }; char event[256]; char callback[256]; for (size_t i = 0; i < sizeof(translators) / sizeof(translators[0]); i++) { sprintf(event, "<%sAny-ButtonPress>", translators[i].Modifier); sprintf(callback, "MouseButtonPressCallback %%b %%x %%y %d %d %d 0", translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); sprintf(event, "", translators[i].Modifier); sprintf(callback, "MouseButtonPressCallback %%b %%x %%y %d %d %d 1", translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); sprintf(event, "<%sAny-ButtonRelease>", translators[i].Modifier); sprintf(callback, "MouseButtonReleaseCallback %%b %%x %%y %d %d %d", translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); sprintf(event, "<%sMotion>", translators[i].Modifier); sprintf(callback, "MouseMoveCallback 0 %%x %%y %d %d %d", translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); for (int b = 1; b <= 3; b++) { sprintf(event, "<%sB%d-Motion>", translators[i].Modifier, b); sprintf(callback, "MouseMoveCallback %d %%x %%y %d %d %d", b, translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); } sprintf(event, "<%sMouseWheel>", translators[i].Modifier); sprintf(callback, "MouseWheelCallback %%D %d %d %d", translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); #if !defined(_WIN32) && !defined(MAC_TCL) && !defined(MAC_OSX_TK) sprintf(event, "<%sButton-4>", translators[i].Modifier); sprintf(callback, "MouseWheelCallback 120 %d %d %d", translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); sprintf(event, "<%sButton-5>", translators[i].Modifier); sprintf(callback, "MouseWheelCallback -120 %d %d %d", translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); #endif sprintf(event, "<%sKeyPress>", translators[i].Modifier); sprintf(callback, "KeyPressCallback %%A %%x %%y %d %d %d %%K", translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); sprintf(event, "<%sKeyRelease>", translators[i].Modifier); sprintf(callback, "KeyReleaseCallback %%A %%x %%y %d %d %d %%K", translators[i].Ctrl, translators[i].Shift, translators[i].Alt); this->VTKWidget->SetBinding(event, this, callback); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveInteractionBindings() { if (!this->IsCreated()) { return; } if (this->VTKWidget->IsAlive()) { this->VTKWidget->RemoveBinding(""); this->VTKWidget->RemoveBinding(""); this->VTKWidget->RemoveBinding(""); this->VTKWidget->RemoveBinding(""); typedef struct { const char *Modifier; int Ctrl; int Shift; int Alt; } EventTranslator; EventTranslator translators[] = { { "", 0, 0, 0 }, { "Control-", 1, 0, 0 }, { "Shift-", 0, 1, 0 }, { "Alt-", 0, 0, 1 }, { "Shift-Control-", 1, 1, 0 }, { "Shift-Alt-", 0, 1, 1 }, { "Control-Alt-", 1, 0, 1 }, { "Control-Shift-Alt-", 1, 1, 1 } }; char event[256]; for (size_t i = 0; i < sizeof(translators) / sizeof(translators[0]); i++) { sprintf(event, "<%sAny-ButtonPress>", translators[i].Modifier); this->VTKWidget->RemoveBinding(event); sprintf(event, "", translators[i].Modifier); this->VTKWidget->RemoveBinding(event); sprintf(event, "<%sAny-ButtonRelease>", translators[i].Modifier); this->VTKWidget->RemoveBinding(event); sprintf(event, "<%sMotion>", translators[i].Modifier); this->VTKWidget->RemoveBinding(event); for (int b = 1; b <= 3; b++) { sprintf(event, "<%sB%d-Motion>", translators[i].Modifier, b); this->VTKWidget->RemoveBinding(event); } sprintf(event, "<%sMouseWheel>", translators[i].Modifier); this->VTKWidget->RemoveBinding(event); #if !defined(_WIN32) && !defined(MAC_TCL) && !defined(MAC_OSX_TK) sprintf(event, "<%sButton-4>", translators[i].Modifier); this->VTKWidget->RemoveBinding(event); sprintf(event, "<%sButton-5>", translators[i].Modifier); this->VTKWidget->RemoveBinding(event); #endif sprintf(event, "<%sKeyPress>", translators[i].Modifier); this->VTKWidget->RemoveBinding(event); sprintf(event, "<%sKeyRelease>", translators[i].Modifier); this->VTKWidget->RemoveBinding(event); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::MouseMoveCallback( int vtkNotUsed(num), int x, int y, int ctrl, int shift, int alt) { vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (!interactor) { return; } interactor->SetEventInformationFlipY(x, y, ctrl, shift); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) interactor->SetAltKey(alt); #else (void)alt; #endif vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(interactor); if (gen_interactor) { gen_interactor->MouseMoveEvent(); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::MouseWheelCallback( int delta, int ctrl, int shift, int alt) { vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (!interactor) { return; } interactor->SetControlKey(ctrl); interactor->SetShiftKey(shift); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) interactor->SetAltKey(alt); #else (void)alt; #endif vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(interactor); if (gen_interactor) { if (delta < 0) { gen_interactor->MouseWheelBackwardEvent(); } else { gen_interactor->MouseWheelForwardEvent(); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::MouseButtonPressCallback( int num, int x, int y, int ctrl, int shift, int alt, int repeat) { this->VTKWidget->Focus(); vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (!interactor) { return; } if (this->UseContextMenu && num == 3 && repeat == 0) { if (!this->ContextMenu) { this->ContextMenu = vtkKWMenu::New(); } if (!this->ContextMenu->IsCreated()) { this->ContextMenu->SetParent(this); this->ContextMenu->Create(); } this->ContextMenu->DeleteAllItems(); this->PopulateContextMenu(this->ContextMenu); if (this->ContextMenu->GetNumberOfItems()) { int px, py; vtkKWTkUtilities::GetMousePointerCoordinates(this->VTKWidget, &px, &py); this->ContextMenu->PopUp(px, py); } } else { interactor->SetEventInformationFlipY(x, y, ctrl, shift, 0, repeat); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) interactor->SetAltKey(alt); #else (void)alt; #endif vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(interactor); if (gen_interactor) { switch (num) { case 1: gen_interactor->LeftButtonPressEvent(); break; case 2: gen_interactor->MiddleButtonPressEvent(); break; case 3: gen_interactor->RightButtonPressEvent(); break; } } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::MouseButtonReleaseCallback( int num, int x, int y, int ctrl, int shift, int alt) { vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (!interactor) { return; } interactor->SetEventInformationFlipY(x, y, ctrl, shift); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) interactor->SetAltKey(alt); #else (void)alt; #endif vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(interactor); if (gen_interactor) { switch (num) { case 1: gen_interactor->LeftButtonReleaseEvent(); break; case 2: gen_interactor->MiddleButtonReleaseEvent(); break; case 3: gen_interactor->RightButtonReleaseEvent(); break; } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::KeyPressCallback(char key, int x, int y, int ctrl, int shift, int alt, char *keysym) { vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (!interactor) { return; } interactor->SetEventInformationFlipY(x, y, ctrl, shift, key, 0, keysym); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) interactor->SetAltKey(alt); #else (void)alt; #endif vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(interactor); if (gen_interactor) { gen_interactor->KeyPressEvent(); gen_interactor->CharEvent(); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::KeyReleaseCallback(char key, int x, int y, int ctrl, int shift, int alt, char *keysym) { vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (!interactor) { return; } interactor->SetEventInformationFlipY(x, y, ctrl, shift, key, 0, keysym); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) interactor->SetAltKey(alt); #else (void)alt; #endif vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(interactor); if (gen_interactor) { gen_interactor->KeyReleaseEvent(); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::EnterCallback(int x, int y) { vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (!interactor) { return; } interactor->SetEventInformationFlipY(x, y); vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(interactor); if (gen_interactor) { gen_interactor->EnterEvent(); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::LeaveCallback(int x, int y) { vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (!interactor) { return; } interactor->SetEventInformationFlipY(x, y); vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(interactor); if (gen_interactor) { gen_interactor->LeaveEvent(); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::UpdateRenderWindowInteractorSize(int width, int height) { vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (!interactor) { return; } // When calling the superclass's SetWidth or SetHeight, the // other field will be set to 1 (i.e. a width/height of 0 for a Tk frame // translates to a size 1 in that dimension). Fix that. if (width <= 1) { width = interactor->GetSize()[0]; } if (height <= 1) { height = interactor->GetSize()[1]; } // Interactor->GetSize() can return 0. in that case set the size to 1. if (width == 0) { width = 1; } if (height == 0) { height = 1; } // We *need* to propagate the size to the vtkTkRenderWidget // if we specified the widget's width/height explicitly int frame_width = this->GetWidth(); if (frame_width) { width = frame_width; } int frame_height = this->GetHeight(); if (frame_height) { height = frame_height; } if (frame_width || frame_height) { this->VTKWidget->SetConfigurationOptionAsInt("-width", width); this->VTKWidget->SetConfigurationOptionAsInt("-height", height); } // Propagate to the interactor too, for safety interactor->UpdateSize(width, height); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ConfigureCallback(int width, int height) { this->UpdateRenderWindowInteractorSize(width, height); vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast( this->GetRenderWindowInteractor()); if (gen_interactor) { gen_interactor->ConfigureEvent(); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ExposeCallback() { if (this->InExpose) { return; } this->InExpose = 1; this->GetApplication()->ProcessPendingEvents(); this->Render(); vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(interactor); if (gen_interactor) { gen_interactor->ExposeEvent(); } // If the renderwindow interactor has never been resized, do it now if (interactor->GetSize()[0] == 0 && interactor->GetSize()[1] == 0) { int width = 0, height = 0; if (vtkKWTkUtilities::GetWidgetSize(this->VTKWidget, &width, &height) && width && height) { this->UpdateRenderWindowInteractorSize(width, height); } } this->InExpose = 0; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::FocusInCallback() { this->InvokeEvent(vtkKWEvent::FocusInEvent, NULL); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::FocusOutCallback() { this->InvokeEvent(vtkKWEvent::FocusOutEvent, NULL); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::PopulateContextMenu(vtkKWMenu *menu) { if (!menu) { return; } int nb_items, new_nb_items; nb_items = menu->GetNumberOfItems(); // Interactions this->PopulateContextMenuWithInteractionEntries(menu); new_nb_items = menu->GetNumberOfItems(); if (nb_items && new_nb_items > nb_items) { menu->InsertSeparator(nb_items); new_nb_items++; } nb_items = new_nb_items; // Annotations this->PopulateContextMenuWithAnnotationEntries(menu); new_nb_items = menu->GetNumberOfItems(); if (nb_items && new_nb_items > nb_items) { menu->InsertSeparator(nb_items); new_nb_items++; } nb_items = new_nb_items; // Options this->PopulateContextMenuWithOptionEntries(menu); new_nb_items = menu->GetNumberOfItems(); if (nb_items && new_nb_items > nb_items) { menu->InsertSeparator(nb_items); new_nb_items++; } nb_items = new_nb_items; // Camera this->PopulateContextMenuWithCameraEntries(menu); new_nb_items = menu->GetNumberOfItems(); if (nb_items && new_nb_items > nb_items) { menu->InsertSeparator(nb_items); new_nb_items++; } nb_items = new_nb_items; // Color this->PopulateContextMenuWithColorEntries(menu); new_nb_items = menu->GetNumberOfItems(); if (nb_items && new_nb_items > nb_items) { menu->InsertSeparator(nb_items); new_nb_items++; } nb_items = new_nb_items; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::PopulateContextMenuWithAnnotationEntries( vtkKWMenu *menu) { if (!menu) { return; } int tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); int show_icons = (tcl_major > 8 || (tcl_major == 8 && tcl_minor >= 5)); int index; // Corner Annotation if (this->SupportCornerAnnotation) { index = menu->AddCheckButton( ks_("Annotation|Corner Annotation"), this, "ToggleCornerAnnotationVisibility"); menu->SetItemSelectedState(index, this->GetCornerAnnotationVisibility()); if (show_icons) { menu->SetItemImageToPredefinedIcon( index, vtkKWIcon::IconCornerAnnotation); menu->SetItemCompoundModeToLeft(index); } } // Header Annotation const char *header = this->GetHeaderAnnotationText(); if (header && *header) { index = menu->AddCheckButton( ks_("Annotation|Header Annotation"), this, "ToggleHeaderAnnotationVisibility"); menu->SetItemSelectedState(index, this->GetHeaderAnnotationVisibility()); if (show_icons) { menu->SetItemImageToPredefinedIcon( index, vtkKWIcon::IconHeaderAnnotation); menu->SetItemCompoundModeToLeft(index); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::PopulateContextMenuWithCameraEntries(vtkKWMenu *menu) { if (!menu) { return; } int tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); int show_icons = (tcl_major > 8 || (tcl_major == 8 && tcl_minor >= 5)); int index; // Reset camera index = menu->AddCommand(k_("Reset Camera"), this, "Reset"); if (show_icons) { menu->SetItemImageToPredefinedIcon( index, vtkKWIcon::IconResetCamera); menu->SetItemCompoundModeToLeft(index); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::PopulateContextMenuWithColorEntries(vtkKWMenu *menu) { if (!menu) { return; } int tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); int show_icons = (tcl_major > 8 || (tcl_major == 8 && tcl_minor >= 5)); int index, cascade_index; // Background Color vtkKWMenu *bg_color_menu = vtkKWMenu::New(); bg_color_menu->SetParent(this->ContextMenu); bg_color_menu->Create(); const int icon_size = 16; // Primary Background Color cascade_index = bg_color_menu->AddCommand( k_("Primary Background Color"), this, "RendererBackgroundColorCallback"); if (show_icons) { double r, g, b; this->GetRendererBackgroundColor(&r, &g, &b); vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImageToSolidRGBColor( r, g, b, icon_size, icon_size, vtkKWIcon::ImageOptionDrawDoubleBorder); bg_color_menu->SetItemImageToIcon(cascade_index, icon); bg_color_menu->SetItemCompoundModeToLeft(cascade_index); icon->Delete(); } // Secondary Background Color cascade_index = bg_color_menu->AddCommand( k_("Secondary Background Color"), this, "RendererBackgroundColor2Callback"); if (show_icons) { double r, g, b; this->GetRendererBackgroundColor2(&r, &g, &b); vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImageToSolidRGBColor( r, g, b, icon_size, icon_size, vtkKWIcon::ImageOptionDrawDoubleBorder); bg_color_menu->SetItemImageToIcon(cascade_index, icon); bg_color_menu->SetItemCompoundModeToLeft(cascade_index); icon->Delete(); } // Use secondary as gradient cascade_index = bg_color_menu->AddCheckButton( k_("Display Gradient"), this, "RendererGradientBackgroundCallback"); bg_color_menu->SetItemSelectedState( cascade_index, this->GetRendererGradientBackground()); // Background color menu itself index = menu->AddCascade(k_("Background Color"), bg_color_menu); if (show_icons) { double r1, g1, b1, r2, g2, b2; this->GetRendererBackgroundColor(&r1, &g1, &b1); vtkKWIcon *icon = vtkKWIcon::New(); if (this->GetRendererGradientBackground()) { this->GetRendererBackgroundColor2(&r2, &g2, &b2); icon->SetImageToRGBGradient( r2, g2, b2, r1, g1, b1, icon_size, icon_size, vtkKWIcon::ImageOptionDrawDoubleBorder | vtkKWIcon::ImageOptionDrawVertically); } else { icon->SetImageToSolidRGBColor( r1, g1, b1, icon_size, icon_size, vtkKWIcon::ImageOptionDrawDoubleBorder); } menu->SetItemImageToIcon(index, icon); menu->SetItemCompoundModeToLeft(index); icon->Delete(); } bg_color_menu->Delete(); } //---------------------------------------------------------------------------- int vtkKWRenderWidget::RendererBackgroundColorCallback() { double rgb[3], new_rgb[3]; this->GetRendererBackgroundColor(rgb, rgb + 1, rgb + 2); vtkKWColorPickerWidget *color_picker_widget = NULL; vtkKWColorPickerDialog *color_picker_dlg = this->GetApplication()->GetColorPickerDialog(); void *event_calldata = NULL; if (color_picker_dlg) { color_picker_widget = color_picker_dlg->GetColorPickerWidget(); // Since we are listening to the color picker widget for both // the primary and secondary background color but for the same events, // use is EventCallData to "hint" in which context we are. event_calldata = color_picker_widget->GetEventCallData(); color_picker_widget->SetEventCallData( (void*)(vtkKWRenderWidget::RendererBackgroundColorChangedEvent)); this->AddCallbackCommandObserver( color_picker_widget, vtkKWColorPickerWidget::NewColorChangedEvent); this->AddCallbackCommandObserver( color_picker_widget, vtkKWColorPickerWidget::NewColorChangingEvent); } int ok = vtkKWTkUtilities::QueryUserForColor( this->GetApplication(), this, k_("Primary Background Color"), rgb[0], rgb[1], rgb[2], new_rgb, new_rgb + 1, new_rgb + 2); if (ok) { if (this->GetRendererBackgroundColorRegKey()) { this->GetApplication()->SaveColorRegistryValue( 2, this->GetRendererBackgroundColorRegKey(), new_rgb); } } else { this->SetRendererBackgroundColor(rgb[0], rgb[1], rgb[2]); } if (color_picker_dlg) { this->RemoveCallbackCommandObserver( color_picker_widget, vtkKWColorPickerWidget::NewColorChangedEvent); this->RemoveCallbackCommandObserver( color_picker_widget, vtkKWColorPickerWidget::NewColorChangingEvent); color_picker_widget->SetEventCallData(event_calldata); } return ok; } //---------------------------------------------------------------------------- int vtkKWRenderWidget::RendererBackgroundColor2Callback() { double rgb[3], new_rgb[3]; this->GetRendererBackgroundColor2(rgb, rgb + 1, rgb + 2); vtkKWColorPickerWidget *color_picker_widget = NULL; vtkKWColorPickerDialog *color_picker_dlg = this->GetApplication()->GetColorPickerDialog(); void *event_calldata = NULL; if (color_picker_dlg) { color_picker_widget = color_picker_dlg->GetColorPickerWidget(); // Since we are listening to the color picker widget for both // the primary and secondary background color but for the same events, // use is EventCallData to "hint" in which context we are. event_calldata = color_picker_widget->GetEventCallData(); color_picker_widget->SetEventCallData( (void*)(vtkKWRenderWidget::RendererBackgroundColor2ChangedEvent)); this->AddCallbackCommandObserver( color_picker_widget, vtkKWColorPickerWidget::NewColorChangedEvent); this->AddCallbackCommandObserver( color_picker_widget, vtkKWColorPickerWidget::NewColorChangingEvent); } int ok = vtkKWTkUtilities::QueryUserForColor( this->GetApplication(), this, k_("Secondary Background Color"), rgb[0], rgb[1], rgb[2], new_rgb, new_rgb + 1, new_rgb + 2); if (ok) { if (this->GetRendererBackgroundColor2RegKey()) { this->GetApplication()->SaveColorRegistryValue( 2, this->GetRendererBackgroundColor2RegKey(), new_rgb); } } else { this->SetRendererBackgroundColor2(rgb[0], rgb[1], rgb[2]); } if (color_picker_dlg) { this->RemoveCallbackCommandObserver( color_picker_widget, vtkKWColorPickerWidget::NewColorChangedEvent); this->RemoveCallbackCommandObserver( color_picker_widget, vtkKWColorPickerWidget::NewColorChangingEvent); color_picker_widget->SetEventCallData(event_calldata); } return ok; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RendererGradientBackgroundCallback() { this->ToggleRendererGradientBackground(); if (this->GetRendererGradientBackgroundRegKey()) { this->GetApplication()->SetRegistryValue( 2, "Colors", this->GetRendererGradientBackgroundRegKey(), "%d", this->GetRendererGradientBackground()); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::Reset() { this->ResetCamera(); this->Render(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ResetCamera() { int i, nb_renderers = this->GetNumberOfRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { renderer->ResetCamera(); } } this->ResetCameraClippingRange(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ResetCameraClippingRange() { int i, nb_renderers = this->GetNumberOfRenderers(); for (i = 0; i < nb_renderers; i++) { vtkRenderer *renderer = this->GetNthRenderer(i); if (renderer) { double bounds[6]; this->ComputeVisiblePropBounds(i, bounds); renderer->ResetCameraClippingRange(bounds); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::Render() { if (this->CollapsingRenders) { this->CollapsingRendersCount++; return; } if (!this->RenderState) { return; } static int static_in_render = 0; if (static_in_render) { return; } static_in_render = 1; if (this->RenderMode != vtkKWRenderWidget::DisabledRender && this->VTKWidget->IsCreated()) { this->ResetCameraClippingRange(); this->RenderWindow->Render(); } static_in_render = 0; } //---------------------------------------------------------------------------- int vtkKWRenderWidget::GetOffScreenRendering() { if (this->GetRenderWindow()) { return this->GetRenderWindow()->GetOffScreenRendering(); } return 0; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetOffScreenRendering(int val) { if (this->GetRenderWindow()) { this->GetRenderWindow()->SetOffScreenRendering(val); } this->SetPrinting(val); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetPrinting(int arg) { if (arg == this->Printing) { return; } this->Printing = arg; this->Modified(); if (this->Printing) { this->PreviousRenderMode = this->GetRenderMode(); this->SetRenderModeToSingle(); } else { this->SetRenderMode(this->PreviousRenderMode); // SetupPrint will call SetupMemoryRendering(). // As convenience, let's call ResumeScreenRendering() this->ResumeScreenRendering(); } } //---------------------------------------------------------------------------- #if defined(_WIN32) && !defined(__CYGWIN__) void vtkKWRenderWidget::SetupPrint(RECT &rcDest, HDC ghdc, int printerPageSizeX, int printerPageSizeY, int printerDPIX, int printerDPIY, float scaleX, float scaleY, int screenSizeX, int screenSizeY) { double scale; int cxDIB = screenSizeX; // Size of DIB - x int cyDIB = screenSizeY; // Size of DIB - y // target DPI specified here if (this->GetApplication()) { scale = printerDPIX/this->GetApplication()->GetPrintTargetDPI(); } else { scale = printerDPIX/100.0; } // Best Fit case -- create a rectangle which preserves // the DIB's aspect ratio, and fills the page horizontally. // // The formula in the "->bottom" field below calculates the Y // position of the printed bitmap, based on the size of the // bitmap, the width of the page, and the relative size of // a printed pixel (printerDPIY / printerDPIX). // rcDest.bottom = rcDest.left = 0; if (((float)cyDIB*(float)printerPageSizeX/(float)printerDPIX) > ((float)cxDIB*(float)printerPageSizeY/(float)printerDPIY)) { rcDest.top = printerPageSizeY; rcDest.right = (static_cast(printerPageSizeY)*printerDPIX*cxDIB) / (static_cast(printerDPIY)*cyDIB); } else { rcDest.right = printerPageSizeX; rcDest.top = (static_cast(printerPageSizeX)*printerDPIY*cyDIB) / (static_cast(printerDPIX)*cxDIB); } this->SetupMemoryRendering(rcDest.right/scale*scaleX, rcDest.top/scale*scaleY, ghdc); } #endif //---------------------------------------------------------------------------- void* vtkKWRenderWidget::GetMemoryDC() { #ifdef _WIN32 return (void *)vtkWin32OpenGLRenderWindow:: SafeDownCast(this->RenderWindow)->GetMemoryDC(); #else return NULL; #endif } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetupMemoryRendering( int x, int y, void *cd) { #ifdef _WIN32 if (!cd) { cd = this->RenderWindow->GetGenericContext(); } vtkWin32OpenGLRenderWindow:: SafeDownCast(this->RenderWindow)->SetupMemoryRendering(x, y, (HDC)cd); #else (void)x; (void)y; (void)cd; #endif } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ResumeScreenRendering() { #ifdef _WIN32 vtkWin32OpenGLRenderWindow:: SafeDownCast(this->RenderWindow)->ResumeScreenRendering(); #endif } //---------------------------------------------------------------------------- void vtkKWRenderWidget::Close() { this->RemoveAllViewProps(); this->RemoveBindings(); // Clear all corner annotation texts if (this->GetCornerAnnotation()) { this->GetCornerAnnotation()->ClearAllTexts(); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetAnnotationsVisibility(int v) { this->SetCornerAnnotationVisibility(v); this->SetHeaderAnnotationVisibility(v); } //---------------------------------------------------------------------------- int vtkKWRenderWidget::GetCornerAnnotationVisibility() { return (this->CornerAnnotation && this->HasViewProp(this->CornerAnnotation) && this->CornerAnnotation->GetVisibility()); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetSupportCornerAnnotation(int s) { if (this->SupportCornerAnnotation == s) { return; } this->SupportCornerAnnotation = s; this->Modified(); this->SetCornerAnnotationVisibility( this->GetCornerAnnotationVisibility() & s); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetCornerAnnotationVisibility(int v) { if (this->GetCornerAnnotationVisibility() == v) { return; } if (v) { if (this->SupportCornerAnnotation) { this->CornerAnnotation->VisibilityOn(); this->InvokeEvent(vtkKWRenderWidget:: CornerAnnotationVisibilityChangedEvent, &v); if (!this->HasViewProp(this->CornerAnnotation)) { this->AddOverlayViewProp(this->CornerAnnotation); } } } else { this->CornerAnnotation->VisibilityOff(); this->InvokeEvent(vtkKWRenderWidget:: CornerAnnotationVisibilityChangedEvent, &v); if (this->HasViewProp(this->CornerAnnotation)) { this->RemoveViewProp(this->CornerAnnotation); } } this->Render(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ToggleCornerAnnotationVisibility() { this->SetCornerAnnotationVisibility(!this->GetCornerAnnotationVisibility()); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetCornerAnnotationColor(double r, double g, double b) { double *color = this->GetCornerAnnotationColor(); if (!color || (color[0] == r && color[1] == g && color[2] == b)) { return; } if (this->CornerAnnotation && this->CornerAnnotation->GetTextProperty()) { this->CornerAnnotation->GetTextProperty()->SetColor(r, g, b); if (this->GetCornerAnnotationVisibility()) { this->Render(); } } } //---------------------------------------------------------------------------- double* vtkKWRenderWidget::GetCornerAnnotationColor() { if (!this->CornerAnnotation || !this->CornerAnnotation->GetTextProperty()) { return 0; } double *color = this->CornerAnnotation->GetTextProperty()->GetColor(); if (color[0] < 0 || color[1] < 0 || color[2] < 0) { color = this->CornerAnnotation->GetProperty()->GetColor(); } return color; } //---------------------------------------------------------------------------- int vtkKWRenderWidget::GetHeaderAnnotationVisibility() { return (this->HeaderAnnotation && this->HasViewProp(this->HeaderAnnotation) && this->HeaderAnnotation->GetVisibility()); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetHeaderAnnotationVisibility(int v) { if (this->GetHeaderAnnotationVisibility() == v) { return; } if (v) { this->HeaderAnnotation->VisibilityOn(); if (!this->HasViewProp(this->HeaderAnnotation)) { this->AddOverlayViewProp(this->HeaderAnnotation); } } else { this->HeaderAnnotation->VisibilityOff(); if (this->HasViewProp(this->HeaderAnnotation)) { this->RemoveViewProp(this->HeaderAnnotation); } } this->Render(); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ToggleHeaderAnnotationVisibility() { this->SetHeaderAnnotationVisibility(!this->GetHeaderAnnotationVisibility()); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetHeaderAnnotationColor(double r, double g, double b) { double *color = this->GetHeaderAnnotationColor(); if (!color || (color[0] == r && color[1] == g && color[2] == b)) { return; } if (this->HeaderAnnotation && this->HeaderAnnotation->GetTextProperty()) { this->HeaderAnnotation->GetTextProperty()->SetColor(r, g, b); if (this->GetHeaderAnnotationVisibility()) { this->Render(); } } } //---------------------------------------------------------------------------- double* vtkKWRenderWidget::GetHeaderAnnotationColor() { if (!this->HeaderAnnotation || !this->HeaderAnnotation->GetTextProperty()) { return 0; } double *color = this->HeaderAnnotation->GetTextProperty()->GetColor(); if (color[0] < 0 || color[1] < 0 || color[2] < 0) { color = this->HeaderAnnotation->GetProperty()->GetColor(); } return color; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetHeaderAnnotationText(const char *text) { if (this->HeaderAnnotation) { this->HeaderAnnotation->SetInput(text); if (this->GetHeaderAnnotationVisibility()) { this->Render(); } } } //---------------------------------------------------------------------------- char* vtkKWRenderWidget::GetHeaderAnnotationText() { if (this->HeaderAnnotation) { return this->HeaderAnnotation->GetInput(); } return 0; } //---------------------------------------------------------------------------- void vtkKWRenderWidget::SetCollapsingRenders(int r) { if (r) { this->CollapsingRenders = 1; this->CollapsingRendersCount = 0; } else { this->CollapsingRenders = 0; if (this->CollapsingRendersCount) { this->Render(); } } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::AddCallbackCommandObservers() { this->Superclass::AddCallbackCommandObservers(); vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (interactor) { this->AddCallbackCommandObserver( interactor, vtkCommand::CreateTimerEvent); this->AddCallbackCommandObserver( interactor, vtkCommand::DestroyTimerEvent); } this->AddCallbackCommandObserver( this->RenderWindow, vtkCommand::CursorChangedEvent); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::RemoveCallbackCommandObservers() { this->Superclass::RemoveCallbackCommandObservers(); vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (interactor) { this->RemoveCallbackCommandObserver( interactor, vtkCommand::CreateTimerEvent); this->RemoveCallbackCommandObserver( interactor, vtkCommand::DestroyTimerEvent); } this->RemoveCallbackCommandObserver( this->RenderWindow, vtkCommand::CursorChangedEvent); } //---------------------------------------------------------------------------- void vtkKWRenderWidget_InteractorTimer( vtkKWRenderWidgetInternals::TimerAdapter *adapter) { if (adapter) { vtkGenericRenderWindowInteractor *gen_interactor = vtkGenericRenderWindowInteractor::SafeDownCast(adapter->Interactor); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) if (!adapter->Interactor->GetEnabled()) { return; } adapter->Interactor->InvokeEvent( vtkCommand::TimerEvent, (void*)&adapter->TimerId); if (!adapter->Interactor->IsOneShotTimer(adapter->TimerId) && (!gen_interactor || gen_interactor->GetTimerEventResetsTimer())) { adapter->Interactor->ResetTimer(adapter->TimerId); } #else if (gen_interactor) { gen_interactor->TimerEvent(); } #endif } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::ProcessCallbackCommandEvents(vtkObject *caller, unsigned long event, void *calldata) { // Handle the timer event for the generic interactor vtkRenderWindowInteractor *interactor = this->GetRenderWindowInteractor(); if (caller == interactor) { int timer_platform_id, timer_duration; vtkKWRenderWidgetInternals::TimerAdapter *adapter = NULL; switch (event) { case vtkCommand::CreateTimerEvent: #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) timer_platform_id = interactor->GetTimerEventId(); timer_duration = interactor->GetTimerEventDuration(); interactor->SetTimerEventPlatformId(timer_platform_id); #else timer_platform_id = 0; timer_duration = 10; #endif adapter = &this->Internals->TimerAdapterPool[timer_platform_id]; adapter->TimerId = timer_platform_id; adapter->Interactor = interactor; adapter->TclTimerToken = Tcl_CreateTimerHandler( timer_duration, (Tcl_TimerProc*)vtkKWRenderWidget_InteractorTimer, (ClientData)adapter); break; case vtkCommand::DestroyTimerEvent: #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) timer_platform_id = interactor->GetTimerEventPlatformId(); #else timer_platform_id = 0; #endif vtkKWRenderWidgetInternals::TimerAdapterPoolType::iterator it = this->Internals->TimerAdapterPool.find(timer_platform_id); if (it != this->Internals->TimerAdapterPool.end()) { Tcl_DeleteTimerHandler(it->second.TclTimerToken); this->Internals->TimerAdapterPool.erase(it); } break; } return; } /* What is really going on below? The vtkRenderWindow this vtkTkRenderWidget is part of supports a few different mouse cursor shapes that can be set using the SetCurrentCursor method. These cursor shapes are used extensively by VTK's 3D widget, like the distance measurement widget, or the angle widget, to provide the user some visual feedback when the mouse is over an element of the 3D widget that can be interacted with (say, the handle at each end of the measurement widget) This works just fine in a native window, but alas not so well when the renderwindow is part of a vtkTkRenderWidget inside a Tk UI, as it is the case in this class; the problem is that Tk seems to try very hard to enforce its own cursor policy by refreshing the cursor shape as often as it can; each Tk widget does indeed support a -cursor option that can be used to specify the cursor shape to set when the mouse is hovering over that widget. Therefore, one can notice an annoying flickering between VTK trying to set a cursor shape, and Tk trying to set it back to its current value for the vtkTkRenderWidget this renderwindow is part of. In order to avoid this, we are listening to the CursorChangedEvent event that is emitted by the renderwindow when its cursor shape is about to change (see vtkWin32OpenGLRenderWindow::SetCurrentCursor for example). Now what we need to do is to make sure we set the cursor shape of the Tk widget to the same shape VTK is trying to use too. This does not work so well on even "recent" version of Tk (say 8.4.5) because some native cursor shapes (like "hand") are not supported: what we see then is yet another flickering between the native "hand" cursor and the non-native Tk "hand" cursor. This can be fixed by using a more recent version of Tk (say 8.4.9). This could also be solved by preventing VTK from actually changing any cursor shape, and letting Tk doing it below (i.e. even if the shapes would not all look "native", they would at least look consistent and would not flicker). */ #if 1 if (caller == this->RenderWindow) { const char *cptr = 0; int shape; switch (event) { case vtkCommand::CursorChangedEvent: shape = *(static_cast(calldata)); if (shape != this->RenderWindow->GetCurrentCursor()) { switch (shape) { // Tk Cursors: // http://www.xed.ch/lwm/tcltkref/tk.cursor.html case VTK_CURSOR_DEFAULT: cptr = ""; break; case VTK_CURSOR_SIZENE: #ifdef _WIN32 cptr = "size_ne_sw"; #else cptr = "top_right_corner"; #endif break; case VTK_CURSOR_SIZENW: #ifdef _WIN32 cptr = "size_nw_se"; #else cptr = "top_left_corner"; #endif break; case VTK_CURSOR_SIZESW: #ifdef _WIN32 cptr = "size_ne_sw"; #else cptr = "bottom_left_corner"; #endif break; case VTK_CURSOR_SIZESE: #ifdef _WIN32 cptr = "size_nw_se"; #else cptr = "bottom_right_corner"; #endif break; case VTK_CURSOR_SIZENS: cptr = "sb_v_double_arrow"; break; case VTK_CURSOR_SIZEWE: cptr = "sb_h_double_arrow"; break; case VTK_CURSOR_SIZEALL: #ifdef _WIN32 // should be "size" if we upgrade to Tcl/Tk > 8.4.5 cptr = "fleur"; #else cptr = "fleur"; #endif break; case VTK_CURSOR_HAND: cptr = "hand2"; break; } if (cptr) { vtkKWTkUtilities::SetTopLevelMouseCursor(this, cptr); } } break; } } #endif vtkKWColorPickerWidget *cpw = vtkKWColorPickerWidget::SafeDownCast(caller); if (cpw && (event == vtkKWColorPickerWidget::NewColorChangedEvent || event == vtkKWColorPickerWidget::NewColorChangingEvent)) { if (calldata == (void*)(vtkKWRenderWidget::RendererBackgroundColorChangedEvent)) { this->SetRendererBackgroundColor(cpw->GetNewColorAsRGB()); } else if (calldata == (void*)(vtkKWRenderWidget::RendererBackgroundColor2ChangedEvent)) { this->SetRendererBackgroundColor2(cpw->GetNewColorAsRGB()); } } this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata); } //---------------------------------------------------------------------------- void vtkKWRenderWidget::UpdateEnableState() { this->Superclass::UpdateEnableState(); // If enabled back, set up the bindings, otherwise remove if (this->GetEnabled()) { this->AddInteractionBindings(); } else { this->RemoveInteractionBindings(); } } //---------------------------------------------------------------------------- void vtkKWRenderWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); int i; os << indent << "Renderers: " << endl; for (i = 0; i < this->GetNumberOfRenderers(); i++) { os << indent << " #" << i << ": " << this->GetNthRenderer(i) << endl; } os << indent << "Overlay Renderers: " << endl; for (i = 0; i < this->GetNumberOfOverlayRenderers(); i++) { os << indent << " #" << i << ": " << this->GetNthOverlayRenderer(i) << endl; } os << indent << "SupportCornerAnnotation: " << (this->SupportCornerAnnotation ? "On" : "Off") << endl; os << indent << "CornerAnnotation: " << this->CornerAnnotation << endl; os << indent << "HeaderAnnotation: " << this->HeaderAnnotation << endl; os << indent << "Printing: " << this->Printing << endl; os << indent << "VTKWidget: " << this->VTKWidget << endl; os << indent << "RenderWindow: " << this->RenderWindow << endl; os << indent << "RenderMode: " << this->RenderMode << endl; os << indent << "RenderState: " << this->RenderState << endl; os << indent << "Renderer: " << this->GetRenderer() << endl; os << indent << "CollapsingRenders: " << this->CollapsingRenders << endl; os << indent << "DistanceUnits: " << (this->DistanceUnits ? this->DistanceUnits : "(none)") << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWPresetSelector.cxx0000644000175000017500000041364011305300761021543 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWPresetSelector.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWPresetSelector.h" #include "vtkKWApplication.h" #include "vtkImageData.h" #include "vtkImageResample.h" #include "vtkKWBalloonHelpManager.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWMessageDialog.h" #include "vtkKWLabelWithLabel.h" #include "vtkKWMenu.h" #include "vtkKWWindowBase.h" #include "vtkKWMultiColumnList.h" #include "vtkKWMultiColumnListWithScrollbars.h" #include "vtkKWPushButton.h" #include "vtkKWPushButtonSet.h" #include "vtkKWToolbar.h" #include "vtkKWTkUtilities.h" #include "vtkObjectFactory.h" #include "vtkRenderWindow.h" #include "vtkWindowToImageFilter.h" #include "vtkImagePermute.h" #include "vtkImageClip.h" #include #include #include #include #include #include #include const char *vtkKWPresetSelector::IdColumnName = "Id"; const char *vtkKWPresetSelector::ThumbnailColumnName = "Image"; const char *vtkKWPresetSelector::GroupColumnName = "Group"; const char *vtkKWPresetSelector::CommentColumnName = "Comment"; //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWPresetSelector); vtkCxxRevisionMacro(vtkKWPresetSelector, "$Revision: 1.86 $"); //---------------------------------------------------------------------------- class vtkKWPresetSelectorInternals { public: // User slot typedef vtksys_stl::string UserSlotNameType; class UserSlotValueType { public: int Type; double DoubleValue; int IntValue; unsigned long UnsignedLongValue; vtkTypeInt64 Int64Value; vtksys_stl::string StringValue; void *PointerValue; vtkObject *ObjectValue; void DeAllocate(); }; // User slot pool typedef vtksys_stl::map UserSlotPoolType; typedef vtksys_stl::map::iterator UserSlotPoolIterator; // Preset node class PresetNode { public: int Id; UserSlotPoolType UserSlotPool; }; // Preset pool // We maintain two pools, one is a list, because the ordering of the // preset matters (one can insert at any position), and the another one // as a map for faster/direct access. int PresetNodeCounter; typedef vtksys_stl::list PresetPoolType; typedef vtksys_stl::list::iterator PresetPoolIterator; PresetPoolType PresetPool; PresetPoolIterator GetPresetNodeIterator(int id); typedef vtksys_stl::map SortedPresetPoolType; typedef vtksys_stl::map::iterator SortedPresetPoolIterator; SortedPresetPoolType SortedPresetPool; // for faster quick access SortedPresetPoolIterator GetSortedPresetNodeIterator(int id); PresetNode* GetPresetNode(int id); // Timers for updating preset rows typedef vtksys_stl::map ScheduleUpdatePresetRowTimerPoolType; typedef vtksys_stl::map::iterator ScheduleUpdatePresetRowTimerPoolIterator; ScheduleUpdatePresetRowTimerPoolType ScheduleUpdatePresetRowTimerPool; vtksys_stl::string ScheduleUpdatePresetRowsTimerId; vtksys_stl::string SchedulePresetSelectionCallbackTimerId; vtksys_stl::string SchedulePresetSelectionChangedCallbackTimerId; // User slot name for the default fields vtksys_stl::string GroupSlotName; vtksys_stl::string CommentSlotName; vtksys_stl::string FileNameSlotName; vtksys_stl::string CreationTimeSlotName; vtksys_stl::string ThumbnailSlotName; vtksys_stl::string ScreenshotSlotName; // Filter constraint class PresetFilterConstraint { public: vtksys_stl::string StringValue; int IsRegularExpression; }; // Filter pool typedef vtksys_stl::map PresetFilterType; typedef vtksys_stl::map::iterator PresetFilterIterator; PresetFilterType PresetFilter; // Button label (internal purposes) vtksys_stl::string SelectPreviousButtonLabel; vtksys_stl::string SelectNextButtonLabel; vtksys_stl::string AddButtonLabel; vtksys_stl::string ApplyButtonLabel; vtksys_stl::string UpdateButtonLabel; vtksys_stl::string RemoveButtonLabel; vtksys_stl::string RemoveAllButtonLabel; vtksys_stl::string LocateButtonLabel; vtksys_stl::string EmailButtonLabel; vtksys_stl::string LoadButtonLabel; vtksys_stl::string FilterButtonLabel; // Let's try to speed things up by caching some info // - preset id to row index // - row index to preset id typedef vtksys_stl::map PresetIdToRowIndexCacheType; typedef vtksys_stl::map::iterator PresetIdToRowIndexCacheTypeIterator; PresetIdToRowIndexCacheType PresetIdToRowIndexCache; typedef vtksys_stl::map RowIndexToPresetIdCacheType; typedef vtksys_stl::map::iterator RowIndexToPresetIdCacheTypeIterator; RowIndexToPresetIdCacheType RowIndexToPresetIdCache; }; //--------------------------------------------------------------------------- vtkKWPresetSelectorInternals::PresetPoolIterator vtkKWPresetSelectorInternals::GetPresetNodeIterator(int id) { vtkKWPresetSelectorInternals::PresetPoolIterator it = this->PresetPool.begin(); vtkKWPresetSelectorInternals::PresetPoolIterator end = this->PresetPool.end(); for (; it != end; it++) { if ((*it)->Id == id) { return it; } } return end; } //--------------------------------------------------------------------------- vtkKWPresetSelectorInternals::SortedPresetPoolIterator vtkKWPresetSelectorInternals::GetSortedPresetNodeIterator(int id) { return this->SortedPresetPool.find(id); } //--------------------------------------------------------------------------- vtkKWPresetSelectorInternals::PresetNode* vtkKWPresetSelectorInternals::GetPresetNode(int id) { #if 1 vtkKWPresetSelectorInternals::SortedPresetPoolIterator it = this->GetSortedPresetNodeIterator(id); if (it != this->SortedPresetPool.end()) { return it->second; } #else vtkKWPresetSelectorInternals::PresetPoolIterator it = this->GetPresetNodeIterator(id); if (it != this->PresetPool.end()) { return *it; } #endif return NULL; } //--------------------------------------------------------------------------- void vtkKWPresetSelectorInternals::UserSlotValueType::DeAllocate() { if (this->Type == vtkKWPresetSelector::UserSlotObjectType && this->ObjectValue) { this->ObjectValue->UnRegister(NULL); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::DeAllocatePreset(int id) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.begin(); vtkKWPresetSelectorInternals::UserSlotPoolIterator s_end = node->UserSlotPool.end(); while (s_it != s_end) { s_it->second.DeAllocate(); ++s_it; } } } } //---------------------------------------------------------------------------- vtkKWPresetSelector::vtkKWPresetSelector() { this->Internals = new vtkKWPresetSelectorInternals; this->Internals->PresetNodeCounter = 0; this->Internals->GroupSlotName = "DefaultGroupSlot"; this->Internals->CommentSlotName = "DefaultCommentSlot"; this->Internals->FileNameSlotName = "DefaultFileNameSlot"; this->Internals->CreationTimeSlotName = "DefaultCreationTimeSlot"; this->Internals->ThumbnailSlotName = "DefaultThumbnailSlot"; this->Internals->ScreenshotSlotName = "DefaultScreenshotSlot"; this->Internals->SelectPreviousButtonLabel = ks_("Preset Selector|Button|Previous"); this->Internals->SelectNextButtonLabel = ks_("Preset Selector|Button|Next"); this->Internals->AddButtonLabel = ks_("Preset Selector|Button|Add"); this->Internals->ApplyButtonLabel = ks_("Preset Selector|Button|Apply"); this->Internals->UpdateButtonLabel = ks_("Preset Selector|Button|Update"); this->Internals->RemoveButtonLabel = ks_("Preset Selector|Button|Remove"); this->Internals->RemoveAllButtonLabel = ks_("Preset Selector|Button|Remove All"); this->Internals->LocateButtonLabel = ks_("Preset Selector|Button|Locate"); this->Internals->EmailButtonLabel = ks_("Preset Selector|Button|Email"); this->Internals->LoadButtonLabel = ks_("Preset Selector|Button|Load"); this->Internals->FilterButtonLabel = ks_("Preset Selector|Button|Filter"); this->PresetAddCommand = NULL; this->PresetUpdateCommand = NULL; this->PresetApplyCommand = NULL; this->PresetRemoveCommand = NULL; this->PresetRemovedCommand = NULL; this->PresetHasChangedCommand = NULL; this->PresetLoadCommand = NULL; this->PresetFilteringHasChangedCommand = NULL; this->CreateUserPresetButtonsCommand = NULL; this->UpdateUserPresetButtonsCommand = NULL; this->SetUserPresetButtonsIconsCommand = NULL; this->SetUserPresetButtonsHelpStringsCommand = NULL; this->PresetList = NULL; this->PresetControlFrame = NULL; this->PresetButtons = NULL; this->HelpLabel = NULL; this->ApplyPresetOnSelection = 1; this->SelectSpinButtonsVisibility = 1; this->LocateButtonVisibility = 0; this->LocateMenuEntryVisibility = 0; this->RemoveButtonVisibility = 1; this->RemoveMenuEntryVisibility = 1; this->EmailButtonVisibility = 0; this->EmailMenuEntryVisibility = 0; this->HelpLabelVisibility = 0; this->FilterButtonVisibility = 0; this->ThumbnailSize = 32; this->ScreenshotSize = 144; this->PromptBeforeRemovePreset = 1; this->MaximumNumberOfPresets = 0; this->EmailBody = NULL; this->FilterButtonSlotName = NULL; this->ContextMenu = NULL; this->Toolbar = NULL; this->PresetButtonsBaseIcon = NULL; this->SetPresetButtonsBaseIconToPredefinedIcon(vtkKWIcon::IconDocument); } //---------------------------------------------------------------------------- vtkKWPresetSelector::~vtkKWPresetSelector() { if (this->PresetList) { this->PresetList->Delete(); this->PresetList = NULL; } if (this->PresetControlFrame) { this->PresetControlFrame->Delete(); this->PresetControlFrame = NULL; } if (this->PresetButtons) { this->PresetButtons->Delete(); this->PresetButtons = NULL; } if (this->HelpLabel) { this->HelpLabel->Delete(); this->HelpLabel = NULL; } if (this->PresetAddCommand) { delete [] this->PresetAddCommand; this->PresetAddCommand = NULL; } if (this->PresetUpdateCommand) { delete [] this->PresetUpdateCommand; this->PresetUpdateCommand = NULL; } if (this->PresetApplyCommand) { delete [] this->PresetApplyCommand; this->PresetApplyCommand = NULL; } if (this->PresetRemoveCommand) { delete [] this->PresetRemoveCommand; this->PresetRemoveCommand = NULL; } if (this->PresetRemovedCommand) { delete [] this->PresetRemovedCommand; this->PresetRemovedCommand = NULL; } if (this->PresetHasChangedCommand) { delete [] this->PresetHasChangedCommand; this->PresetHasChangedCommand = NULL; } if (this->PresetLoadCommand) { delete [] this->PresetLoadCommand; this->PresetLoadCommand = NULL; } if (this->PresetFilteringHasChangedCommand) { delete [] this->PresetFilteringHasChangedCommand; this->PresetFilteringHasChangedCommand = NULL; } if (this->CreateUserPresetButtonsCommand) { delete [] this->CreateUserPresetButtonsCommand; this->CreateUserPresetButtonsCommand = NULL; } if (this->UpdateUserPresetButtonsCommand) { delete [] this->UpdateUserPresetButtonsCommand; this->UpdateUserPresetButtonsCommand = NULL; } if (this->SetUserPresetButtonsIconsCommand) { delete [] this->SetUserPresetButtonsIconsCommand; this->SetUserPresetButtonsIconsCommand = NULL; } if (this->SetUserPresetButtonsHelpStringsCommand) { delete [] this->SetUserPresetButtonsHelpStringsCommand; this->SetUserPresetButtonsHelpStringsCommand = NULL; } // Remove all presets this->DeleteAllPresets(); // Delete our pool delete this->Internals; this->Internals = NULL; if (this->ContextMenu) { this->ContextMenu->Delete(); this->ContextMenu = NULL; } if (this->Toolbar) { this->Toolbar->Delete(); this->Toolbar = NULL; } if (this->PresetButtonsBaseIcon) { this->PresetButtonsBaseIcon->Delete(); this->PresetButtonsBaseIcon = NULL; } this->SetEmailBody(NULL); this->SetFilterButtonSlotName(NULL); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // -------------------------------------------------------------- // Preset : preset list if (!this->PresetList) { this->PresetList = vtkKWMultiColumnListWithScrollbars::New(); } this->PresetList->SetParent(this); this->PresetList->Create(); //this->PresetList->HorizontalScrollbarVisibilityOff(); this->Script( "pack %s -side top -anchor nw -fill both -expand t -padx 2 -pady 2", this->PresetList->GetWidgetName()); vtkKWMultiColumnList *list = this->PresetList->GetWidget(); if (this->ApplyPresetOnSelection) { list->SetSelectionModeToBrowse(); } else { list->SetSelectionModeToBrowse(); } list->SetSelectionCommand( this, "SchedulePresetSelectionCallback"); list->SetSelectionChangedCommand( this, "SchedulePresetSelectionChangedCallback"); list->SetPotentialCellColorsChangedCommand( list, "ScheduleRefreshColorsOfAllCellsWithWindowCommand"); list->ColumnSeparatorsVisibilityOn(); list->ResizableColumnsOn(); list->StretchableColumnsOn(); list->SetEditStartCommand(this, "PresetCellEditStartCallback"); list->SetEditEndCommand(this, "PresetCellEditEndCallback"); list->SetCellUpdatedCommand(this, "PresetCellUpdatedCallback"); list->SetRightClickCommand(this, "PresetRightClickCallback"); list->SetColumnSortedCommand(this, "ColumnSortedCallback"); list->SetRowMovedCommand(this, "RowMovedCallback"); this->AddCallbackCommandObserver( list, vtkKWMultiColumnList::NumberOfRowsChangedEvent); this->CreateColumns(); // -------------------------------------------------------------- // Preset : control frame if (!this->PresetControlFrame) { this->PresetControlFrame = vtkKWFrame::New(); } this->PresetControlFrame->SetParent(this); this->PresetControlFrame->Create(); this->Script("pack %s -side top -anchor nw -fill both -expand f", this->PresetControlFrame->GetWidgetName()); // -------------------------------------------------------------- // Preset : buttons if (!this->PresetButtons) { this->PresetButtons = vtkKWToolbar::New(); } this->PresetButtons->SetParent(this->PresetControlFrame); this->PresetButtons->Create(); this->PresetButtons->SetWidgetsFlatAdditionalPadX( this->PresetButtons->GetWidgetsFlatAdditionalPadX() + 1); this->PresetButtons->SetWidgetsFlatAdditionalInternalPadX( this->PresetButtons->GetWidgetsFlatAdditionalInternalPadX() + 1); this->PresetButtons->SetWidgetsFlatAdditionalInternalPadY( this->PresetButtons->GetWidgetsFlatAdditionalInternalPadY() + 1); this->CreateToolbarPresetButtons(this->PresetButtons, 1); this->SetToolbarPresetButtonsIcons(this->PresetButtons); this->SetToolbarPresetButtonsHelpStrings(this->PresetButtons); // -------------------------------------------------------------- // Help message if (!this->HelpLabel) { this->HelpLabel = vtkKWLabelWithLabel::New(); } this->HelpLabel->SetParent(this->PresetControlFrame); this->HelpLabel->Create(); this->HelpLabel->ExpandWidgetOn(); this->HelpLabel->GetLabel()->SetImageToPredefinedIcon( vtkKWIcon::IconSilkHelp); vtkKWLabel *msg = this->HelpLabel->GetWidget(); msg->SetJustificationToLeft(); msg->SetAnchorToNorthWest(); msg->AdjustWrapLengthToWidthOn(); // Pack this->Pack(); // Update enable state this->Update(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::CreateToolbar() { if (!this->Toolbar) { return; } if (!this->Toolbar->GetParent()) { this->Toolbar->SetParent(this); } this->Toolbar->Create(); this->Toolbar->SetWidgetsFlatAdditionalPadX( this->Toolbar->GetWidgetsFlatAdditionalPadX() + 1); this->Toolbar->SetWidgetsFlatAdditionalInternalPadX( this->Toolbar->GetWidgetsFlatAdditionalInternalPadX() + 1); this->CreateToolbarPresetButtons(this->Toolbar, 0); this->SetToolbarPresetButtonsIcons(this->Toolbar); this->SetToolbarPresetButtonsHelpStrings(this->Toolbar); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetButtonsBaseIcon(vtkKWIcon *icon) { if (this->PresetButtonsBaseIcon == icon) { return; } if (this->PresetButtonsBaseIcon) { this->PresetButtonsBaseIcon->UnRegister(this); this->PresetButtonsBaseIcon = NULL; } if (icon) { this->PresetButtonsBaseIcon = icon; this->PresetButtonsBaseIcon->Register(this); } this->Modified(); this->SetToolbarPresetButtonsIcons(this->PresetButtons); this->SetToolbarPresetButtonsIcons(this->Toolbar); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetButtonsBaseIconToPredefinedIcon( int icon_index) { vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImage(icon_index); icon->TrimTop(); icon->TrimRight(); this->SetPresetButtonsBaseIcon(icon); icon->Delete(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::CreateToolbarPresetButtons( vtkKWToolbar *toolbar, int use_separators) { if (!toolbar) { return; } vtkKWPushButton *toolbar_pb; // Select previous preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetSelectPreviousButtonLabel()); toolbar_pb->SetCommand(this, "SelectPreviousPreset"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); // Select next preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetSelectNextButtonLabel()); toolbar_pb->SetCommand(this, "SelectNextPreset"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); if (use_separators) { toolbar->AddSeparator(); } // Add preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetAddButtonLabel()); toolbar_pb->SetCommand(this, "PresetAddCallback"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); // Apply preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetApplyButtonLabel()); toolbar_pb->SetCommand(this, "PresetApplyCallback"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); // Update preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetUpdateButtonLabel()); toolbar_pb->SetCommand(this, "PresetUpdateCallback"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); // Remove preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetRemoveButtonLabel()); toolbar_pb->SetCommand(this, "PresetRemoveCallback"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); if (use_separators) { toolbar->AddSeparator(); } // Locate preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetLocateButtonLabel()); toolbar_pb->SetCommand(this, "PresetLocateCallback"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); // Email preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetEmailButtonLabel()); toolbar_pb->SetCommand(this, "PresetEmailCallback"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); // Load preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetLoadButtonLabel()); toolbar_pb->SetCommand(this, "PresetLoadCallback"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); if (use_separators) { toolbar->AddSeparator(); } // Filter By Group preset toolbar_pb = vtkKWPushButton::New(); toolbar_pb->SetParent(toolbar->GetFrame()); toolbar_pb->Create(); toolbar_pb->SetText(this->GetFilterButtonLabel()); toolbar_pb->SetCommand(this, "PresetFilterCallback"); toolbar->AddWidget(toolbar_pb); toolbar_pb->Delete(); // User buttons this->InvokeCreateUserPresetButtonsCommand(toolbar, use_separators); } //--------------------------------------------------------------------------- void vtkKWPresetSelector::UpdateToolbarPresetButtons(vtkKWToolbar *toolbar) { if (!toolbar) { return; } toolbar->SetEnabled(this->GetEnabled()); int has_selection = (this->PresetList && this->PresetList->GetWidget()->GetNumberOfSelectedCells()); int has_filenames_in_selection = has_selection ? this->GetNumberOfSelectedPresetsWithFileName() : 0; int has_presets = this->GetNumberOfVisiblePresets(); vtkKWPushButton *toolbar_pb; // Select prev toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetSelectPreviousButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, this->SelectSpinButtonsVisibility); toolbar_pb->SetEnabled( has_presets ? toolbar->GetEnabled() : 0); } // Select next toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetSelectNextButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, this->SelectSpinButtonsVisibility); toolbar_pb->SetEnabled( has_presets ? toolbar->GetEnabled() : 0); } // Add toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetAddButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, (this->PresetAddCommand && *this->PresetAddCommand) ? 1 : 0); } // Apply toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetApplyButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, this->PresetApplyCommand && *this->PresetApplyCommand && !this->ApplyPresetOnSelection ? 1 : 0); toolbar_pb->SetEnabled( has_selection ? toolbar->GetEnabled() : 0); } // Update toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetUpdateButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, (this->PresetUpdateCommand && *this->PresetUpdateCommand) ? 1 : 0); toolbar_pb->SetEnabled( has_selection ? toolbar->GetEnabled() : 0); } // Remove toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetRemoveButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, this->RemoveButtonVisibility ? 1 : 0); toolbar_pb->SetEnabled( has_selection ? toolbar->GetEnabled() : 0); } // Locate toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetLocateButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, this->LocateButtonVisibility ? 1 : 0); toolbar_pb->SetEnabled( has_filenames_in_selection ? toolbar->GetEnabled() : 0); } // Email toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetEmailButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, this->EmailButtonVisibility ? 1 : 0); toolbar_pb->SetEnabled( has_filenames_in_selection ? toolbar->GetEnabled() : 0); } // Load toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetLoadButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, (this->PresetLoadCommand && *this->PresetLoadCommand) ? 1 : 0); } // Filter By Group toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetFilterButtonLabel())); if (toolbar_pb) { toolbar->SetWidgetVisibility( toolbar_pb, this->FilterButtonVisibility ? 1 : 0); toolbar_pb->SetEnabled( this->FilterButtonSlotName ? toolbar->GetEnabled() : 0); } // User buttons this->InvokeUpdateUserPresetButtonsCommand(toolbar); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetToolbarPresetButtonsIcons(vtkKWToolbar *toolbar) { if (!toolbar) { return; } vtkKWPushButton *toolbar_pb; vtkKWIcon *icon = NULL; if (this->PresetButtonsBaseIcon) { icon = vtkKWIcon::New(); } // Select previous preset toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetSelectPreviousButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetPrevious); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetPrevious); } } // Select next preset toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetSelectNextButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetNext); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetNext); } } // Add preset toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetAddButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetAdd); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetAdd); } } // Apply preset toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetApplyButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetApply); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetApply); } } // Update preset toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetUpdateButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetUpdate); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetUpdate); } } // Remove preset toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetRemoveButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetDelete); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetDelete); } } // Locate preset toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetLocateButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetLocate); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetLocate); } } // Email preset toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetEmailButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetEmail); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetEmail); } } // Load preset toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetLoadButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetLoad); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetLoad); } } // Filter By Group toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetFilterButtonLabel())); if (toolbar_pb) { if (this->PresetButtonsBaseIcon) { icon->SetImage(this->PresetButtonsBaseIcon); icon->Compose(vtkKWIcon::IconPresetFilter); toolbar_pb->SetImageToIcon(icon); } else { toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPresetFilter); } } // Release icon if (icon) { icon->Delete(); } // User buttons this->InvokeSetUserPresetButtonsIconsCommand(toolbar); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetToolbarPresetButtonsHelpStrings(vtkKWToolbar *toolbar) { if (!toolbar) { return; } vtkKWWidget *toolbar_pb; // Select previous preset toolbar_pb = toolbar->GetWidget(this->GetSelectPreviousButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Select previous preset")); } // Select next preset toolbar_pb = toolbar->GetWidget(this->GetSelectNextButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Select next preset")); } // Add preset toolbar_pb = toolbar->GetWidget(this->GetAddButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Add a preset")); } // Apply preset toolbar_pb = toolbar->GetWidget(this->GetApplyButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Apply the selected preset(s)")); } // Update preset toolbar_pb = toolbar->GetWidget(this->GetUpdateButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Update the selected preset(s)")); } // Remove preset toolbar_pb = toolbar->GetWidget(this->GetRemoveButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Delete the selected preset(s)")); } // Locate preset toolbar_pb = toolbar->GetWidget(this->GetLocateButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Find the location of the selected preset(s) on disk")); } // Email preset toolbar_pb = toolbar->GetWidget(this->GetEmailButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Email the selected preset(s)")); } // Load preset toolbar_pb = toolbar->GetWidget(this->GetLoadButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Load a preset")); } // Filter By Group preset toolbar_pb = toolbar->GetWidget(this->GetFilterButtonLabel()); if (toolbar_pb) { toolbar_pb->SetBalloonHelpString( ks_("Preset Selector|Filter preset(s)")); } // User buttons this->InvokeSetUserPresetButtonsHelpStringsCommand(toolbar); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::PopulatePresetContextMenu(vtkKWMenu *menu, int id) { if (!this->HasPreset(id)) { return; } char command[256], label[256]; int tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); int show_icons = (tcl_major > 8 || (tcl_major == 8 && tcl_minor >= 5)); int index; vtkKWToolbar *toolbar = this->PresetButtons; vtkKWPushButton *toolbar_pb; const char *filename = this->GetPresetFileName(id); int has_file = (filename && *filename && vtksys::SystemTools::FileExists(filename)); // Apply preset if (this->PresetApplyCommand) { sprintf(command, "PresetApplyCallback %d", id); index = menu->AddCommand(this->GetApplyButtonLabel(), this, command); if (show_icons) { toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetApplyButtonLabel())); menu->SetItemImage(index, toolbar_pb->GetConfigurationOption("-image")); menu->SetItemCompoundModeToLeft(index); } } // Update preset if (this->PresetUpdateCommand) { sprintf(command, "PresetUpdateCallback %d", id); index = menu->AddCommand(this->GetUpdateButtonLabel(), this, command); if (show_icons) { toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetUpdateButtonLabel())); menu->SetItemImage(index, toolbar_pb->GetConfigurationOption("-image")); menu->SetItemCompoundModeToLeft(index); } } // Remove preset if (this->RemoveMenuEntryVisibility) { sprintf(command, "PresetRemoveCallback %d", id); index = menu->AddCommand(this->GetRemoveButtonLabel(), this, command); if (show_icons) { toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetRemoveButtonLabel())); menu->SetItemImage(index, toolbar_pb->GetConfigurationOption("-image")); menu->SetItemCompoundModeToLeft(index); } index = menu->AddCommand( this->GetRemoveAllButtonLabel(), this, "PresetRemoveAllCallback"); } // Locate preset if (has_file && this->LocateMenuEntryVisibility) { sprintf(command, "PresetLocateCallback %d", id); index = menu->AddCommand(this->GetLocateButtonLabel(), this, command); if (show_icons) { toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetLocateButtonLabel())); menu->SetItemImage(index, toolbar_pb->GetConfigurationOption("-image")); menu->SetItemCompoundModeToLeft(index); } } // Email preset if (has_file && this->EmailMenuEntryVisibility) { sprintf(command, "PresetEmailCallback %d", id); index = menu->AddCommand(this->GetEmailButtonLabel(), this, command); if (show_icons) { toolbar_pb = vtkKWPushButton::SafeDownCast( toolbar->GetWidget(this->GetEmailButtonLabel())); menu->SetItemImage(index, toolbar_pb->GetConfigurationOption("-image")); menu->SetItemCompoundModeToLeft(index); } } // now the editable fields vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int added_editable = 0, col_vis = 0, nb_columns = list->GetNumberOfColumns(); for (int col = 0; col < nb_columns; col++) { if (list->GetColumnVisibility(col)) { col_vis++; if (list->GetColumnEditable(col)) { int row = this->GetPresetRow(id); if (row >= 0 && list->GetCellEditable(row, col)) { sprintf(command, "EditCell %d %d", row, col); const char *col_name = list->GetColumnName(col); if (col_name) { sprintf(label, "Edit %s", col_name); } else { sprintf(label, "Edit column %d", col_vis); } if (!added_editable) { menu->AddSeparator(); added_editable = 1; } menu->AddCommand(label, list, command); } } } } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::Pack() { if (!this->IsCreated()) { return; } if (this->PresetControlFrame) { this->PresetControlFrame->UnpackChildren(); } if (this->PresetButtons && this->PresetButtons->IsCreated()) { this->Script("pack %s -side top -anchor nw -fill none -expand t", this->PresetButtons->GetWidgetName()); } if (this->HelpLabelVisibility && this->HelpLabel) { this->Script("pack %s -side bottom -anchor nw -fill x -expand n -after %s", this->HelpLabel->GetWidgetName(), this->PresetButtons->GetWidgetName()); } else { this->HelpLabel->Unpack(); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::CreateColumns() { vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int col; // We need that column to retrieve the Id col = list->AddColumn(ks_("Preset Selector|Column|Id")); list->SetColumnName(col, vtkKWPresetSelector::IdColumnName); list->ColumnVisibilityOff(col); // Thumbnail col = list->AddColumn(ks_("Preset Selector|Column|Image")); list->SetColumnName(col, vtkKWPresetSelector::ThumbnailColumnName); list->SetColumnWidth(col, -this->ThumbnailSize); list->SetColumnResizable(col, 1); list->SetColumnStretchable(col, 0); list->SetColumnEditable(col, 0); list->SetColumnSortModeToReal(col); list->SetColumnFormatCommandToEmptyOutput(col); list->ColumnVisibilityOff(col); // Group col = list->AddColumn(ks_("Preset Selector|Column|Group")); list->SetColumnName(col, vtkKWPresetSelector::GroupColumnName); list->SetColumnResizable(col, 1); list->SetColumnStretchable(col, 0); list->SetColumnEditable(col, 0); list->ColumnVisibilityOff(col); // Comment col = list->AddColumn(ks_("Preset Selector|Column|Comment")); list->SetColumnName(col, vtkKWPresetSelector::CommentColumnName); list->SetColumnResizable(col, 1); list->SetColumnStretchable(col, 1); list->SetColumnEditable(col, 1); } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetIdColumnIndex() { return this->PresetList ? this->PresetList->GetWidget()->GetColumnIndexWithName( vtkKWPresetSelector::IdColumnName) : -1; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetThumbnailColumnIndex() { return this->PresetList ? this->PresetList->GetWidget()->GetColumnIndexWithName( vtkKWPresetSelector::ThumbnailColumnName) : -1; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetGroupColumnIndex() { return this->PresetList ? this->PresetList->GetWidget()->GetColumnIndexWithName( vtkKWPresetSelector::GroupColumnName) : -1; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetCommentColumnIndex() { return this->PresetList ? this->PresetList->GetWidget()->GetColumnIndexWithName( vtkKWPresetSelector::CommentColumnName) : -1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetApplyPresetOnSelection(int arg) { if (this->ApplyPresetOnSelection == arg) { return; } this->ApplyPresetOnSelection = arg; this->Modified(); if (this->PresetList) { if (this->ApplyPresetOnSelection) { this->PresetList->GetWidget()->SetSelectionModeToBrowse(); } else { this->PresetList->GetWidget()->SetSelectionModeToBrowse(); } } // visibility of the apply preset button this->UpdateToolbarPresetButtons(this->PresetButtons); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetSelectSpinButtonsVisibility(int arg) { if (this->SelectSpinButtonsVisibility == arg) { return; } this->SelectSpinButtonsVisibility = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetLocateButtonVisibility(int arg) { if (this->LocateButtonVisibility == arg) { return; } this->LocateButtonVisibility = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetRemoveButtonVisibility(int arg) { if (this->RemoveButtonVisibility == arg) { return; } this->RemoveButtonVisibility = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetEmailButtonVisibility(int arg) { if (this->EmailButtonVisibility == arg) { return; } this->EmailButtonVisibility = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetFilterButtonVisibility(int arg) { if (this->FilterButtonVisibility == arg) { return; } this->FilterButtonVisibility = arg; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetHelpLabelVisibility(int arg) { if (this->HelpLabelVisibility == arg) { return; } this->HelpLabelVisibility = arg; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetHelpLabelText(const char *str) { if (this->HelpLabel) { this->HelpLabel->GetWidget()->SetText(str); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetListHeight(int h) { if (this->PresetList) { this->PresetList->GetWidget()->SetHeight(h); } } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetListHeight() { if (this->PresetList) { return this->PresetList->GetWidget()->GetHeight(); } return 0; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetListWidth(int h) { if (this->PresetList) { this->PresetList->GetWidget()->SetWidth(h); } } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetListWidth() { if (this->PresetList) { return this->PresetList->GetWidget()->GetWidth(); } return 0; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetThumbnailColumnVisibility(int arg) { if (this->PresetList && this->GetThumbnailColumnVisibility() != arg) { this->PresetList->GetWidget()->SetColumnVisibility( this->GetThumbnailColumnIndex(), arg); this->ScheduleUpdatePresetRows(); // fill thumbnail column } } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetThumbnailColumnVisibility() { if (this->PresetList) { return this->PresetList->GetWidget()->GetColumnVisibility( this->GetThumbnailColumnIndex()); } return 0; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetCommentColumnVisibility(int arg) { if (this->PresetList && this->GetCommentColumnVisibility() != arg) { this->PresetList->GetWidget()->SetColumnVisibility( this->GetCommentColumnIndex(), arg); } } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetCommentColumnVisibility() { if (this->PresetList) { return this->PresetList->GetWidget()->GetColumnVisibility( this->GetCommentColumnIndex()); } return 0; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetGroupColumnVisibility(int arg) { if (this->PresetList && this->GetGroupColumnVisibility() != arg) { this->PresetList->GetWidget()->SetColumnVisibility( this->GetGroupColumnIndex(), arg); this->ScheduleUpdatePresetRows(); // fill group column } } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetGroupColumnVisibility() { if (this->PresetList) { return this->PresetList->GetWidget()->GetColumnVisibility( this->GetGroupColumnIndex()); } return 0; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetGroupColumnTitle(const char *arg) { if (this->PresetList) { this->PresetList->GetWidget()->SetColumnTitle( this->GetGroupColumnIndex(), arg); } } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetGroupColumnTitle() { if (this->PresetList) { return this->PresetList->GetWidget()->GetColumnTitle( this->GetGroupColumnIndex()); } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::AddPreset() { vtkKWPresetSelectorInternals::PresetNode *node = new vtkKWPresetSelectorInternals::PresetNode; node->Id = this->Internals->PresetNodeCounter++; this->Internals->PresetPool.push_back(node); this->Internals->SortedPresetPool[node->Id] = node; this->ConfigureNewPreset(node->Id); this->ConstrainNumberOfPresets(); this->NumberOfPresetsHasChanged(); return node->Id; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::InsertPreset(int id) { vtkKWPresetSelectorInternals::PresetPoolIterator it; if (id < 0) { it = this->Internals->PresetPool.begin(); } else { it = this->Internals->GetPresetNodeIterator(id); if (it == this->Internals->PresetPool.end()) { return -1; } } vtkKWPresetSelectorInternals::PresetNode *node = new vtkKWPresetSelectorInternals::PresetNode; node->Id = this->Internals->PresetNodeCounter++; this->Internals->PresetPool.insert(it, node); this->Internals->SortedPresetPool[node->Id] = node; this->ConfigureNewPreset(node->Id); this->ConstrainNumberOfPresets(); this->NumberOfPresetsHasChanged(); return node->Id; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::ConfigureNewPreset(int id) { int row = this->UpdatePresetRowInMultiColumnList(id, 1); // Even though ScheduleUpdatePresetRow() is called by SetPresetCreationTime // let's update the row *now* so that people can both add a preset *and* // select it or see it right away programmatically. If we rely on // ScheduleUpdatePresetRow, the row will *not* be created on time once // we hit SeeRow or SelectPreset, it will only be created the next time // the event loop is idle enough to do so. // Also, if some rows were schedules to be updated, do so now, otherwise // some rows may popup after this one. // UPDATE: not needed anymore, call UpdatePresetRowInMultiColumnList // to create the row with the id, which is more lightweight than updating // the full row contents. //this->CancelScheduleUpdatePresetRows(); //this->UpdatePresetRow(id); vtkTypeInt64 c_time = (vtkTypeInt64)(vtksys::SystemTools::GetTime() * 1000.0); this->SetPresetCreationTime(id, c_time); if (this->PresetList && this->PresetList->IsMapped() && row >= 0) { this->PresetList->GetWidget()->SeeRow(row); } } //---------------------------------------------------------------------------- int vtkKWPresetSelector::RemovePreset(int id) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->GetPresetNodeIterator(id); if (it != this->Internals->PresetPool.end()) { vtkKWPresetSelectorInternals::SortedPresetPoolIterator it2 = this->Internals->GetSortedPresetNodeIterator(id); vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; this->DeAllocatePreset(id); if (this->PresetList) { int row = this->GetPresetRow(id); if (row >= 0) { this->PresetList->GetWidget()->DeleteRow(row); } } delete preset; this->Internals->PresetPool.erase(it); this->Internals->SortedPresetPool.erase(it2); this->NumberOfPresetsHasChanged(); return 1; } } return 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::DeleteAllPresets() { if (this->Internals) { int nb_deleted = this->GetNumberOfPresets(); vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); vtkKWPresetSelectorInternals::PresetPoolIterator it; // First give a chance to third-party or subclasses to deallocate // the presets cleanly (without messing up the iterator framework) it = this->Internals->PresetPool.begin(); for (; it != end; ++it) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; this->DeAllocatePreset(preset->Id); } // Then remove the presets it = this->Internals->PresetPool.begin(); for (; it != end; ++it) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; delete preset; } this->Internals->PresetPool.clear(); this->Internals->SortedPresetPool.clear(); return nb_deleted; } return 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::RemoveAllPresetsWithGroup(const char *group) { // Is faster than calling RemovePreset on each preset if (this->Internals && group && *group) { vtkKWPresetSelectorInternals::PresetPoolIterator it; vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); // First give a chance to third-party or subclasses to deallocate // the presets cleanly (without messing up the iterator framework) it = this->Internals->PresetPool.begin(); for (; it != end; ++it) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = preset->UserSlotPool.find(this->GetPresetGroupSlotName()); if (s_it != preset->UserSlotPool.end() && !s_it->second.StringValue.compare(group)) { this->DeAllocatePreset(preset->Id); if (this->PresetList) { int row = this->GetPresetRow(preset->Id); if (row >= 0) { this->PresetList->GetWidget()->DeleteRow(row); } } } } // Then remove the presets int nb_deleted = 0; int done = 0; while (!done) { done = 1; it = this->Internals->PresetPool.begin(); for (; it != end; ++it) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = preset->UserSlotPool.find(this->GetPresetGroupSlotName()); if (s_it != preset->UserSlotPool.end() && !s_it->second.StringValue.compare(group)) { vtkKWPresetSelectorInternals::SortedPresetPoolIterator it2 = this->Internals->GetSortedPresetNodeIterator(preset->Id); delete preset; this->Internals->PresetPool.erase(it); this->Internals->SortedPresetPool.erase(it2); nb_deleted++; done = 0; break; } } } if (nb_deleted) { this->NumberOfPresetsHasChanged(); } } return 1; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::RemoveAllPresets() { int nb_deleted = this->DeleteAllPresets(); if (this->PresetList && this->PresetList->GetWidget()->GetNumberOfRows()) { this->PresetList->GetWidget()->DeleteAllRows(); } if (nb_deleted) { this->NumberOfPresetsHasChanged(); } return 1; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::HasPreset(int id) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); return node ? 1 : 0; } return 0; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetGroupSlotName(const char *name) { if (name && *name && this->Internals && this->Internals->GroupSlotName.compare(name)) { this->Internals->GroupSlotName = name; this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetGroupSlotName() { if (this->Internals) { return this->Internals->GroupSlotName.c_str(); } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetGroup(int id, const char *group) { int res = this->SetPresetUserSlotAsString( id, this->GetPresetGroupSlotName(), group); if (res && this->GetPresetFilterGroupConstraint()) { // Changing the group of a preset may change the number of visible widgets // (for example, if the visibility of presets is filtered by groups), // which can enable/disable some buttons this->PresetFilteringMayHaveChanged(); this->Update(); } return res; } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetGroup(int id) { return this->GetPresetUserSlotAsString(id, this->GetPresetGroupSlotName()); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetCommentSlotName(const char *name) { if (name && *name && this->Internals && this->Internals->CommentSlotName.compare(name)) { this->Internals->CommentSlotName = name; this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetCommentSlotName() { if (this->Internals) { return this->Internals->CommentSlotName.c_str(); } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetComment(int id, const char *comment) { return this->SetPresetUserSlotAsString( id, this->GetPresetCommentSlotName(), comment); } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetComment(int id) { return this->GetPresetUserSlotAsString( id, this->GetPresetCommentSlotName()); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetFileNameSlotName(const char *name) { if (name && *name && this->Internals && this->Internals->FileNameSlotName.compare(name)) { this->Internals->FileNameSlotName = name; this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetFileNameSlotName() { if (this->Internals) { return this->Internals->FileNameSlotName.c_str(); } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetFileName(int id, const char *filename) { return this->SetPresetUserSlotAsString( id, this->GetPresetFileNameSlotName(), filename); } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetFileName(int id) { return this->GetPresetUserSlotAsString( id, this->GetPresetFileNameSlotName()); } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetIdOfPresetWithFileName(const char *filename) { if (this->Internals && filename) { int is_full = vtksys::SystemTools::FileIsFullPath(filename) ? 1 : 0; vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->PresetPool.begin(); vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); for (; it != end; it++) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; const char *it_filename = this->GetPresetFileName(preset->Id); if (it_filename) { if (is_full) { if (!strcmp(it_filename, filename)) { return preset->Id; } } else { vtksys_stl::string it_name = vtksys::SystemTools::GetFilenameName(it_filename); if (!strcmp(it_name.c_str(), filename)) { return preset->Id; } } } } } return -1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetCreationTimeSlotName(const char *name) { if (name && *name && this->Internals && this->Internals->CreationTimeSlotName.compare(name)) { this->Internals->CreationTimeSlotName = name; this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetCreationTimeSlotName() { if (this->Internals) { return this->Internals->CreationTimeSlotName.c_str(); } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetCreationTime(int id, vtkTypeInt64 value) { return this->SetPresetUserSlotAsInt64( id, this->GetPresetCreationTimeSlotName(), value); } //---------------------------------------------------------------------------- vtkTypeInt64 vtkKWPresetSelector::GetPresetCreationTime(int id) { return this->GetPresetUserSlotAsInt64( id, this->GetPresetCreationTimeSlotName()); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetThumbnailSlotName(const char *name) { if (name && *name && this->Internals && this->Internals->ThumbnailSlotName.compare(name)) { this->Internals->ThumbnailSlotName = name; this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetThumbnailSlotName() { if (this->Internals) { return this->Internals->ThumbnailSlotName.c_str(); } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetThumbnail( int id, vtkKWIcon *icon) { if (this->HasPreset(id)) { if (icon) { vtkKWIcon *ptr = this->GetPresetThumbnail(id); if (!ptr) { ptr = vtkKWIcon::New(); ptr->DeepCopy(icon); this->SetPresetUserSlotAsObject( id, this->GetPresetThumbnailSlotName(), ptr); ptr->Delete(); } else { ptr->DeepCopy(icon); this->ScheduleUpdatePresetRow(id); } } else { this->DeletePresetUserSlot(id, this->GetPresetThumbnailSlotName()); } return 1; } return 0; } //---------------------------------------------------------------------------- vtkKWIcon* vtkKWPresetSelector::GetPresetThumbnail(int id) { return (vtkKWIcon*)this->GetPresetUserSlotAsObject( id, this->GetPresetThumbnailSlotName()); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetScreenshotSlotName(const char *name) { if (name && *name && this->Internals && this->Internals->ScreenshotSlotName.compare(name)) { this->Internals->ScreenshotSlotName = name; this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetScreenshotSlotName() { if (this->Internals) { return this->Internals->ScreenshotSlotName.c_str(); } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetScreenshot( int id, vtkKWIcon *icon) { if (this->HasPreset(id)) { if (icon) { vtkKWIcon *ptr = this->GetPresetScreenshot(id); if (!ptr) { ptr = vtkKWIcon::New(); ptr->DeepCopy(icon); this->SetPresetUserSlotAsObject( id, this->GetPresetScreenshotSlotName(), ptr); ptr->Delete(); } else { ptr->DeepCopy(icon); this->ScheduleUpdatePresetRow(id); } } else { this->DeletePresetUserSlot(id, this->GetPresetScreenshotSlotName()); } return 1; } return 0; } //---------------------------------------------------------------------------- vtkKWIcon* vtkKWPresetSelector::GetPresetScreenshot(int id) { return (vtkKWIcon*)this->GetPresetUserSlotAsObject( id, this->GetPresetScreenshotSlotName()); } //--------------------------------------------------------------------------- int vtkKWPresetSelector::BuildPresetThumbnailAndScreenshotFromImage( int id, vtkImageData *image) { #ifdef KWWidgets_BUILD_VTK_WIDGETS if (!this->HasPreset(id)) { return 0; } // Empty image, remove thumbnail/screenshot int image_dims[3]; image->GetDimensions(image_dims); if (image_dims[0] == 0 || image_dims[1] == 0 || image_dims[2] == 0) { this->SetPresetThumbnail(id, NULL); this->SetPresetScreenshot(id, NULL); return 1; } double factor; vtkImageData *resample_input, *resample_output; // First, let's make sure we are processing the image as it // is by clipping its UpdateExtent. By doing so, we prevent our resample // and permute filter the process the image's *whole* extent. vtkImageClip *clip = vtkImageClip::New(); clip->SetInput(image); clip->SetOutputWholeExtent(image->GetUpdateExtent()); clip->Update(); // Permute, as a convenience int clip_dims[3]; clip->GetOutput()->GetDimensions(clip_dims); vtkImagePermute *permute = NULL; if (clip_dims[2] != 1) { permute = vtkImagePermute::New(); permute->SetInput(clip->GetOutput()); if (clip_dims[0] == 1) { permute->SetFilteredAxes(1, 2, 0); } else { permute->SetFilteredAxes(0, 2, 1); } resample_input = permute->GetOutput(); } else { resample_input = clip->GetOutput(); } resample_input->Update(); int resample_input_dims[3], resample_output_dims[3]; resample_input->GetDimensions(resample_input_dims); double *resample_input_spacing = resample_input->GetSpacing(); int large_dim = 0, small_dim = 1; if (resample_input_dims[0] < resample_input_dims[1]) { large_dim = 1; small_dim = 0; } vtkImageResample *resample = vtkImageResample::New(); resample->SetInput(resample_input); resample->SetInterpolationModeToCubic(); resample->SetDimensionality(2); // Create the screenshot factor = (double)this->ScreenshotSize / (double)resample_input_dims[large_dim]; resample->SetAxisMagnificationFactor(large_dim, factor); resample->SetAxisMagnificationFactor( small_dim, factor * (resample_input_spacing[small_dim] / resample_input_spacing[large_dim])); resample->Update(); resample_output = resample->GetOutput(); resample_output->GetDimensions(resample_output_dims); vtkKWIcon *screenshot = vtkKWIcon::New(); screenshot->SetImage( (const unsigned char*)resample_output->GetScalarPointer(), resample_output_dims[0], resample_output_dims[1], 3, 0, vtkKWIcon::ImageOptionFlipVertical); this->SetPresetScreenshot(id, screenshot); screenshot->Delete(); // Create the thumbnail factor = (double)this->ThumbnailSize / (double)resample_input_dims[large_dim]; resample->SetAxisMagnificationFactor(large_dim, factor); resample->SetAxisMagnificationFactor( small_dim, factor * (resample_input_spacing[small_dim] / resample_input_spacing[large_dim])); resample->Update(); resample_output = resample->GetOutput(); resample_output->GetDimensions(resample_output_dims); vtkKWIcon *thumbnail = vtkKWIcon::New(); thumbnail->SetImage( (const unsigned char*)resample_output->GetScalarPointer(), resample_output_dims[0], resample_output_dims[1], 3, 0, vtkKWIcon::ImageOptionFlipVertical); this->SetPresetThumbnail(id, thumbnail); thumbnail->Delete(); // Deallocate clip->Delete(); resample->Delete(); if (permute) { permute->Delete(); } // Update the icon cell this->ScheduleUpdatePresetRow(id); #endif return 1; } //--------------------------------------------------------------------------- int vtkKWPresetSelector::BuildPresetThumbnailAndScreenshotFromRenderWindow( int id, vtkRenderWindow *win) { #ifdef KWWidgets_BUILD_VTK_WIDGETS if (win) { vtkWindowToImageFilter *filter = vtkWindowToImageFilter::New(); filter->ShouldRerenderOff(); filter->SetInput(win); filter->Update(); int res = this->BuildPresetThumbnailAndScreenshotFromImage( id, filter->GetOutput()); filter->Delete(); return res; } #endif return 0; } //--------------------------------------------------------------------------- int vtkKWPresetSelector::FlipPresetThumbnailAndScreenshotVertically( int id) { if (!this->HasPreset(id)) { return 0; } int modified = 0; vtkKWIcon *screenshot = this->GetPresetScreenshot(id); if (screenshot) { screenshot->SetImage(screenshot->GetData(), screenshot->GetWidth(), screenshot->GetHeight(), screenshot->GetPixelSize(), 0, vtkKWIcon::ImageOptionFlipVertical); modified++; } vtkKWIcon *thumbnail = this->GetPresetThumbnail(id); if (thumbnail) { thumbnail->SetImage(thumbnail->GetData(), thumbnail->GetWidth(), thumbnail->GetHeight(), thumbnail->GetPixelSize(), 0, vtkKWIcon::ImageOptionFlipVertical); modified++; } // Update the icon cell if (modified) { this->ScheduleUpdatePresetRow(id); } return 1; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::HasPresetUserSlot(int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { return 1; } } } return 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetPresetUserSlotType(int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { return s_it->second.Type; } } } return vtkKWPresetSelector::UserSlotUnknownType; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::DeletePresetUserSlot(int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { s_it->second.DeAllocate(); node->UserSlotPool.erase(s_it); this->ScheduleUpdatePresetRow(id); return 1; } } } return 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetUserSlotAsDouble( int id, const char *slot_name, double value) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { if (s_it->second.Type == vtkKWPresetSelector::UserSlotDoubleType && s_it->second.DoubleValue == value) { return 1; } s_it->second.DeAllocate(); } vtkKWPresetSelectorInternals::UserSlotValueType &slot = node->UserSlotPool[slot_name]; slot.DoubleValue = value; slot.Type = vtkKWPresetSelector::UserSlotDoubleType; if (this->GetPresetFilterUserSlotConstraint(slot_name)) { this->PresetFilteringMayHaveChanged(); this->UpdatePresetRow(id); } else { this->ScheduleUpdatePresetRow(id); } return 1; } } return 0; } //---------------------------------------------------------------------------- double vtkKWPresetSelector::GetPresetUserSlotAsDouble( int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { return s_it->second.DoubleValue; } } } return 0.0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetUserSlotAsInt( int id, const char *slot_name, int value) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { if (s_it->second.Type == vtkKWPresetSelector::UserSlotIntType && s_it->second.IntValue == value) { return 1; } s_it->second.DeAllocate(); } vtkKWPresetSelectorInternals::UserSlotValueType &slot = node->UserSlotPool[slot_name]; slot.IntValue = value; slot.Type = vtkKWPresetSelector::UserSlotIntType; if (this->GetPresetFilterUserSlotConstraint(slot_name)) { this->PresetFilteringMayHaveChanged(); this->UpdatePresetRow(id); } else { this->ScheduleUpdatePresetRow(id); } return 1; } } return 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetPresetUserSlotAsInt( int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { return s_it->second.IntValue; } } } return 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetUserSlotAsUnsignedLong( int id, const char *slot_name, unsigned long value) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { if (s_it->second.Type == vtkKWPresetSelector::UserSlotUnsignedLongType && s_it->second.UnsignedLongValue == value) { return 1; } s_it->second.DeAllocate(); } vtkKWPresetSelectorInternals::UserSlotValueType &slot = node->UserSlotPool[slot_name]; slot.UnsignedLongValue = value; slot.Type = vtkKWPresetSelector::UserSlotUnsignedLongType; if (this->GetPresetFilterUserSlotConstraint(slot_name)) { this->PresetFilteringMayHaveChanged(); this->UpdatePresetRow(id); } else { this->ScheduleUpdatePresetRow(id); } return 1; } } return 0; } //---------------------------------------------------------------------------- unsigned long vtkKWPresetSelector::GetPresetUserSlotAsUnsignedLong( int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { return s_it->second.UnsignedLongValue; } } } return 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetUserSlotAsInt64( int id, const char *slot_name, vtkTypeInt64 value) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { if (s_it->second.Type == vtkKWPresetSelector::UserSlotInt64Type && s_it->second.Int64Value == value) { return 1; } s_it->second.DeAllocate(); } vtkKWPresetSelectorInternals::UserSlotValueType &slot = node->UserSlotPool[slot_name]; slot.Int64Value = value; slot.Type = vtkKWPresetSelector::UserSlotInt64Type; if (this->GetPresetFilterUserSlotConstraint(slot_name)) { this->PresetFilteringMayHaveChanged(); this->UpdatePresetRow(id); } else { this->ScheduleUpdatePresetRow(id); } return 1; } } return 0; } //---------------------------------------------------------------------------- vtkTypeInt64 vtkKWPresetSelector::GetPresetUserSlotAsInt64( int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { return s_it->second.Int64Value; } } } return 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetUserSlotAsString( int id, const char *slot_name, const char* value) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { const char *fixed_value = value ? value : ""; vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { if (s_it->second.Type == vtkKWPresetSelector::UserSlotStringType && s_it->second.StringValue == fixed_value) { return 1; } s_it->second.DeAllocate(); } vtkKWPresetSelectorInternals::UserSlotValueType &slot = node->UserSlotPool[slot_name]; slot.StringValue = fixed_value; slot.Type = vtkKWPresetSelector::UserSlotStringType; if (this->GetPresetFilterUserSlotConstraint(slot_name)) { this->PresetFilteringMayHaveChanged(); this->UpdatePresetRow(id); } else { this->ScheduleUpdatePresetRow(id); } return 1; } } return 0; } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetUserSlotAsString( int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { return s_it->second.StringValue.c_str(); } } } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetUserSlotAsPointer( int id, const char *slot_name, void *value) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { if (s_it->second.Type == vtkKWPresetSelector::UserSlotPointerType && s_it->second.PointerValue == value) { return 1; } s_it->second.DeAllocate(); } vtkKWPresetSelectorInternals::UserSlotValueType &slot = node->UserSlotPool[slot_name]; slot.PointerValue = value; slot.Type = vtkKWPresetSelector::UserSlotPointerType; if (this->GetPresetFilterUserSlotConstraint(slot_name)) { this->PresetFilteringMayHaveChanged(); this->UpdatePresetRow(id); } else { this->ScheduleUpdatePresetRow(id); } return 1; } } return 0; } //---------------------------------------------------------------------------- void* vtkKWPresetSelector::GetPresetUserSlotAsPointer( int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { return s_it->second.PointerValue; } } } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::SetPresetUserSlotAsObject( int id, const char *slot_name, vtkObject *value) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { if (s_it->second.Type == vtkKWPresetSelector::UserSlotObjectType && s_it->second.ObjectValue == value) { return 1; } s_it->second.DeAllocate(); } vtkKWPresetSelectorInternals::UserSlotValueType &slot = node->UserSlotPool[slot_name]; slot.ObjectValue = value; slot.Type = vtkKWPresetSelector::UserSlotObjectType; if (value) { value->Register(this); } if (this->GetPresetFilterUserSlotConstraint(slot_name)) { this->PresetFilteringMayHaveChanged(); this->UpdatePresetRow(id); } else { this->ScheduleUpdatePresetRow(id); } return 1; } } return 0; } //---------------------------------------------------------------------------- vtkObject* vtkKWPresetSelector::GetPresetUserSlotAsObject( int id, const char *slot_name) { if (this->Internals) { vtkKWPresetSelectorInternals::PresetNode *node = this->Internals->GetPresetNode(id); if (node) { vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = node->UserSlotPool.find(slot_name); if (s_it != node->UserSlotPool.end()) { return s_it->second.ObjectValue; } } } return NULL; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetNumberOfPresets() { if (this->Internals) { return (int)this->Internals->PresetPool.size(); } return 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetNumberOfPresetsWithGroup(const char *group) { int count = 0; if (this->Internals && group && *group) { vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->PresetPool.begin(); vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); for (; it != end; ++it) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = preset->UserSlotPool.find(this->GetPresetGroupSlotName()); if (s_it != preset->UserSlotPool.end() && !s_it->second.StringValue.compare(group)) { count++; } } } return count; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetNumberOfVisiblePresets() { if (this->PresetList) { return this->PresetList->GetWidget()->GetNumberOfRows(); } return 0; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetMaximumNumberOfPresets(int _arg) { if (this->MaximumNumberOfPresets == _arg || _arg < 0) { return; } this->MaximumNumberOfPresets = _arg; this->Modified(); this->ConstrainNumberOfPresets(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::ConstrainNumberOfPresets() { if (this->MaximumNumberOfPresets <= 0) { return; } while (this->GetNumberOfPresets() > this->MaximumNumberOfPresets) { vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->PresetPool.begin(); vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it; const char *c_time_slot_name = this->GetPresetCreationTimeSlotName(); vtkTypeInt64 min_c_time = this->GetPresetCreationTime((*it)->Id); int min_id = -1; for (; it != end; ++it) { #if 0 vtkTypeInt64 c_time = this->GetPresetCreationTime((*it)->Id); #else s_it =(*it)->UserSlotPool.find(c_time_slot_name); if (s_it != (*it)->UserSlotPool.end()) { vtkTypeInt64 c_time = s_it->second.Int64Value; if (c_time < min_c_time) { min_c_time = c_time; min_id = (*it)->Id; } } #endif } if (min_id != -1) { this->RemovePreset(min_id); } } } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetPresetVisibility(int id) { return this->GetPresetRow(id) >= 0 ? 1 : 0; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetIdOfNthPreset(int index) { if (this->Internals && index >= 0 && index < this->GetNumberOfPresets()) { vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->PresetPool.begin(); while (index > 0) { ++it; --index; } vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; return preset->Id; } return -1; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetIdOfNthPresetWithGroup(int index, const char *group) { int rank = this->GetRankOfNthPresetWithGroup(index, group); if (rank >= 0) { return this->GetIdOfNthPreset(rank); } return -1; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetIdOfPresetAtRow(int row_index) { if (!this->PresetList) { return -1; } int id = this->GetRowIndexToPresetIdCacheEntry(row_index); if (id < 0) { vtkKWMultiColumnList *list = this->PresetList->GetWidget(); if (row_index >= 0 && row_index < list->GetNumberOfRows()) { id = list->GetCellTextAsInt(row_index, this->GetIdColumnIndex()); this->SetRowIndexToPresetIdCacheEntry(row_index, id); } } return id; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetPresetRow(int id) { if (!this->PresetList) { return -1; } int row_index = this->GetPresetIdToRowIndexCacheEntry(id); if (row_index < 0) { row_index = this->PresetList->GetWidget()->FindCellTextAsIntInColumn( this->GetIdColumnIndex(), id); this->SetPresetIdToRowIndexCacheEntry(id, row_index); } return row_index; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetRankOfNthPresetWithGroup( int index, const char *group) { if (this->Internals && index >= 0 && group && *group) { vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->PresetPool.begin(); vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); for (int nth = 0; it != end; ++it, nth++) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = preset->UserSlotPool.find(this->GetPresetGroupSlotName()); if (s_it != preset->UserSlotPool.end() && !s_it->second.StringValue.compare(group)) { index--; if (index < 0) { return nth; } } } } return -1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SelectPreset(int id) { int row = this->GetPresetRow(id); if (row >= 0 && this->PresetList) { this->PresetList->GetWidget()->SelectSingleRow(row); this->PresetList->GetWidget()->SeeRow(row); this->UpdateToolbarPresetButtons(this->PresetButtons); this->UpdateToolbarPresetButtons(this->Toolbar); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SelectPreviousPreset() { if (this->PresetList) { vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int nb_rows = list->GetNumberOfRows(); if (nb_rows) { int prev_row; if (!list->GetNumberOfSelectedRows()) { prev_row = nb_rows - 1; } else { int sel_row = list->GetIndexOfFirstSelectedRow(); prev_row = (nb_rows == 1 || sel_row == 0) ? nb_rows - 1 : sel_row - 1; } list->SelectSingleRow(prev_row); list->SeeRow(prev_row); this->UpdateToolbarPresetButtons(this->PresetButtons); this->UpdateToolbarPresetButtons(this->Toolbar); } } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SelectNextPreset() { if (this->PresetList) { vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int nb_rows = list->GetNumberOfRows(); if (nb_rows) { int next_row; if (!list->GetNumberOfSelectedRows()) { next_row = 0; } else { int sel_row = list->GetIndexOfFirstSelectedRow(); next_row = (nb_rows == 1 || sel_row == nb_rows - 1) ? 0 : sel_row + 1; } list->SelectSingleRow(next_row); list->SeeRow(next_row); this->UpdateToolbarPresetButtons(this->PresetButtons); this->UpdateToolbarPresetButtons(this->Toolbar); } } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::ClearSelection() { if (this->PresetList) { this->PresetList->GetWidget()->ClearSelection(); this->UpdateToolbarPresetButtons(this->PresetButtons); this->UpdateToolbarPresetButtons(this->Toolbar); } } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetIdOfSelectedPreset() { if (this->PresetList) { return this->GetIdOfPresetAtRow( this->PresetList->GetWidget()->GetIndexOfFirstSelectedRow()); } return -1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::NumberOfPresetsHasChanged() { this->Update(); // enable/disable some buttons valid only if we have presets } //---------------------------------------------------------------------------- void vtkKWPresetSelector::PresetFilteringMayHaveChanged() { // Since filtering may have changed, some presets may show up or be // hidden, hence their location will change this->InvalidatePresetIdToRowIndexCache(); this->InvalidateRowIndexToPresetIdCache(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::PresetFilteringHasChanged() { this->PresetFilteringMayHaveChanged(); this->InvokePresetFilteringHasChangedCommand(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::ClearPresetFilter() { if (this->Internals && this->Internals->PresetFilter.size()) { this->Internals->PresetFilter.clear(); this->PresetFilteringHasChanged(); this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetFilterUserSlotConstraint( const char *slot_name, const char *value) { int update = 1; vtkKWPresetSelectorInternals::PresetFilterIterator it = this->Internals->PresetFilter.find(slot_name); if (it != this->Internals->PresetFilter.end()) { if (value) { if ((*it).second.StringValue.compare(value)) { (*it).second.StringValue = value; } else { update = 0; } } else { this->Internals->PresetFilter.erase(it); } } else { if (value) { this->Internals->PresetFilter[slot_name].StringValue = value; this->Internals->PresetFilter[slot_name].IsRegularExpression = 0; } else { update = 0; } } if (update) { this->PresetFilteringHasChanged(); this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetFilterUserSlotConstraint( const char *slot_name) { vtkKWPresetSelectorInternals::PresetFilterIterator it = this->Internals->PresetFilter.find(slot_name); if (it != this->Internals->PresetFilter.end()) { return (*it).second.StringValue.c_str(); } return NULL; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::DeletePresetFilterUserSlotConstraint( const char *slot_name) { vtkKWPresetSelectorInternals::PresetFilterIterator it = this->Internals->PresetFilter.find(slot_name); if (it != this->Internals->PresetFilter.end()) { this->Internals->PresetFilter.erase(it); this->PresetFilteringHasChanged(); this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetFilterUserSlotConstraintToRegularExpression( const char *slot_name) { vtkKWPresetSelectorInternals::PresetFilterIterator it = this->Internals->PresetFilter.find(slot_name); if (it != this->Internals->PresetFilter.end() && !(*it).second.IsRegularExpression) { (*it).second.IsRegularExpression = 1; this->PresetFilteringHasChanged(); this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetFilterUserSlotConstraintToString( const char *slot_name) { vtkKWPresetSelectorInternals::PresetFilterIterator it = this->Internals->PresetFilter.find(slot_name); if (it != this->Internals->PresetFilter.end() && (*it).second.IsRegularExpression) { (*it).second.IsRegularExpression = 0; this->PresetFilteringHasChanged(); this->ScheduleUpdatePresetRows(); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetFilterGroupConstraint(const char *value) { this->SetPresetFilterUserSlotConstraint( this->GetPresetGroupSlotName(), value); } //---------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetPresetFilterGroupConstraint() { return this->GetPresetFilterUserSlotConstraint( this->GetPresetGroupSlotName()); } //---------------------------------------------------------------------------- int vtkKWPresetSelector::IsPresetFiltered(int id) { if (this->Internals->PresetFilter.empty()) { return 1; } char buffer[100]; vtkKWPresetSelectorInternals::PresetFilterIterator it = this->Internals->PresetFilter.begin(); vtkKWPresetSelectorInternals::PresetFilterIterator end = this->Internals->PresetFilter.end(); for (; it != end; ++it) { const char *slot_name = (*it).first.c_str(); int slot_type = this->GetPresetUserSlotType(id, slot_name); const char *slot_value = NULL; if (slot_type == vtkKWPresetSelector::UserSlotStringType) { slot_value = this->GetPresetUserSlotAsString(id, slot_name); } else if (slot_type == vtkKWPresetSelector::UserSlotIntType) { sprintf(buffer, "%d", this->GetPresetUserSlotAsInt(id, slot_name)); slot_value = buffer; } const char *filter_value = (*it).second.StringValue.c_str(); if ((*it).second.IsRegularExpression) { vtksys::RegularExpression re(filter_value); if (!re.find((slot_value ? slot_value : ""))) { return 0; } } else { if (strcmp((slot_value ? slot_value : ""), filter_value)) { return 0; } } } return 1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::UpdatePresetRows() { int nb_visible_presets = this->GetNumberOfVisiblePresets(); vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->PresetPool.begin(); vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); for (; it != end; ++it) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; this->UpdatePresetRow(preset->Id); } // If the number of visible presets changed, this can enable/disable // some buttons if (nb_visible_presets != this->GetNumberOfVisiblePresets()) { this->Update(); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::ScheduleUpdatePresetRows() { // Already scheduled if (this->Internals->ScheduleUpdatePresetRowsTimerId.size()) { return; } this->Internals->ScheduleUpdatePresetRowsTimerId = this->Script( "after idle {catch {%s UpdatePresetRowsCallback}}", this->GetTclName()); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::CancelScheduleUpdatePresetRows() { // Not scheduled if (!this->Internals->ScheduleUpdatePresetRowsTimerId.size()) { return; } this->Script("after cancel %s", this->Internals->ScheduleUpdatePresetRowsTimerId.c_str()); this->UpdatePresetRowsCallback(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::UpdatePresetRowsCallback() { if (!this->GetApplication() || this->GetApplication()->GetInExit() || !this->IsAlive()) { return; } this->UpdatePresetRows(); this->Internals->ScheduleUpdatePresetRowsTimerId = ""; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::UpdatePresetRowInMultiColumnList(int id, int is_new) { const int err_code = -1; if (!this->HasPreset(id)) { return err_code; } vtkKWMultiColumnList *list = this->PresetList->GetWidget(); // Look for this row in the list int row = is_new ? -1 : this->GetPresetRow(id); int is_preset_filtered = this->IsPresetFiltered(id); // Not found ? Insert it, or ignore it if the group filter does not match if (row < 0) { if (!is_preset_filtered) { return err_code; } // Let's find where to insert it, we need to try to keep the order // of the internal list as consistent as possible vtkKWPresetSelectorInternals::PresetPoolIterator begin = this->Internals->PresetPool.begin(); vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); // Fast case, we just added this one at the end. vtkKWPresetSelectorInternals::PresetPoolIterator back = end; --back; if ((*back)->Id == id) { row = list->GetNumberOfRows(); } // Slow case, we need to find the row of the first visible preset // following the one we are trying to insert else { vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->GetPresetNodeIterator(id); for (++it; it != end; ++it) { if (this->IsPresetFiltered((*it)->Id)) { row = this->GetPresetRow((*it)->Id); if (row >= 0) { break; } } } if (it == end) // we didn't find any that was visible :( { row = list->GetNumberOfRows(); } } list->InsertRow(row); // Id (not shown, but useful to retrieve the id of a preset from // a cell position list->SetCellTextAsInt(row, this->GetIdColumnIndex(), id); } // Found ? Remove it if the group filter does not match else { if (!is_preset_filtered) { list->DeleteRow(row); return err_code; } } return row; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::UpdatePresetRow(int id) { int row = this->UpdatePresetRowInMultiColumnList(id); if (row < 0) { return 0; } vtkKWMultiColumnList *list = this->PresetList->GetWidget(); if (this->GetThumbnailColumnVisibility()) { int image_col_index = this->GetThumbnailColumnIndex(); vtkKWIcon *thumbnail = this->GetPresetThumbnail(id); vtkKWIcon *screenshot = this->GetPresetScreenshot(id); list->SetCellWindowCommand( row, image_col_index, this, "PresetCellThumbnailCallback"); list->SetCellWindowDestroyCommandToRemoveChild(row, image_col_index); if (this->GetThumbnailColumnVisibility()) { list->RefreshCellWithWindowCommand(row, image_col_index); } list->SetCellTextAsDouble( row, image_col_index, (double)this->GetPresetCreationTime(id)); } if (this->GetGroupColumnVisibility()) { list->SetCellText( row, this->GetGroupColumnIndex(), this->GetPresetGroup(id)); } list->SetCellText( row, this->GetCommentColumnIndex(), this->GetPresetComment(id)); return 1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::ScheduleUpdatePresetRow(int id) { // Already scheduled vtkKWPresetSelectorInternals::ScheduleUpdatePresetRowTimerPoolIterator it = this->Internals->ScheduleUpdatePresetRowTimerPool.find(id); if (it != this->Internals->ScheduleUpdatePresetRowTimerPool.end()) { return; } this->Internals->ScheduleUpdatePresetRowTimerPool[id] = this->Script("after idle {catch {%s UpdatePresetRowCallback %d}}", this->GetTclName(), id); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::UpdatePresetRowCallback(int id) { if (!this->GetApplication() || this->GetApplication()->GetInExit() || !this->IsAlive()) { return; } this->UpdatePresetRow(id); this->Internals->ScheduleUpdatePresetRowTimerPool.erase( this->Internals->ScheduleUpdatePresetRowTimerPool.find(id)); } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetCellThumbnailCallback( const char *, int row, int, const char *widget) { if (!this->PresetList || !widget) { return; } vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int id = this->GetIdOfPresetAtRow(row); if (id >= 0) { vtkKWLabel *child = vtkKWLabel::New(); child->SetWidgetName(widget); child->SetParent(list); vtkKWIcon *screenshot = this->GetPresetScreenshot(id); if (screenshot) { // Create out own balloon help manager for this one, so that // we can set a much shorter delay vtkKWBalloonHelpManager *mgr = vtkKWBalloonHelpManager::New(); mgr->SetApplication(list->GetApplication()); mgr->SetIgnoreIfNotEnabled(1); child->SetBalloonHelpManager(mgr); mgr->SetDelay(10); mgr->Delete(); child->SetBalloonHelpIcon(screenshot); } else { child->SetBalloonHelpIcon(NULL); } child->Create(); child->SetBorderWidth(0); child->SetHighlightThickness(0); child->SetWidth(this->ThumbnailSize); child->SetHeight(this->ThumbnailSize); child->SetBackgroundColor(list->GetCellCurrentBackgroundColor( row, this->GetThumbnailColumnIndex())); vtkKWIcon *thumbnail = this->GetPresetThumbnail(id); if (thumbnail) { child->SetImageToIcon(thumbnail); } else { child->SetImageToPredefinedIcon(vtkKWIcon::IconEmpty1x1); } list->AddBindingsToWidget(child); child->Delete(); } } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::PresetCellEditStartCallback( int, int, const char *text) { return text; } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::PresetCellEditEndCallback( int, int, const char *text) { return text; } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetCellUpdatedCallback( int row, int col, const char *text) { int id = this->GetIdOfPresetAtRow(row); if (this->HasPreset(id)) { if (col == this->GetCommentColumnIndex()) { this->SetPresetComment(id, text); this->InvokePresetHasChangedCommand(id); return; } } } //--------------------------------------------------------------------------- int vtkKWPresetSelector::PresetAddCallback() { return this->InvokePresetAddCommand(); } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetApplyCallback(int id) { if (this->HasPreset(id)) { this->InvokePresetApplyCommand(id); } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetApplyCallback() { if (this->PresetList) { vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int *indices = new int [list->GetNumberOfRows()]; int i, nb_selected_rows = list->GetSelectedRows(indices); for (i = 0; i < nb_selected_rows; i++) { this->PresetApplyCallback(this->GetIdOfPresetAtRow(indices[i])); } delete [] indices; } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetUpdateCallback(int id) { if (this->HasPreset(id)) { this->InvokePresetUpdateCommand(id); } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetUpdateCallback() { if (this->PresetList) { // First collect the indices of the presets to update // Then update them vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int *indices = new int [list->GetNumberOfRows()]; int *ids = new int [list->GetNumberOfRows()]; int i, nb_selected_rows = list->GetSelectedRows(indices); for (i = 0; i < nb_selected_rows; i++) { ids[i] = this->GetIdOfPresetAtRow(indices[i]); } for (i = 0; i < nb_selected_rows; i++) { this->PresetUpdateCallback(ids[i]); } delete [] indices; delete [] ids; } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetRemoveCallback(int id) { if (!this->PromptBeforeRemovePreset || vtkKWMessageDialog::PopupYesNo( this->GetApplication(), this->GetParentTopLevel(), ks_("Preset Selector|Delete Preset Dialog|Title|Delete Preset?"), k_("Are you sure you want to delete the selected item?"), vtkKWMessageDialog::WarningIcon | vtkKWMessageDialog::InvokeAtPointer)) { if (this->InvokePresetRemoveCommand(id) && this->RemovePreset(id)) { this->InvokePresetRemovedCommand(); } } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetRemoveAllCallback() { if (!this->PromptBeforeRemovePreset || vtkKWMessageDialog::PopupYesNo( this->GetApplication(), this->GetParentTopLevel(), ks_("Preset Selector|Delete Preset Dialog|Title|Delete All Presets?"), k_("Are you sure you want to delete all items?"), vtkKWMessageDialog::WarningIcon | vtkKWMessageDialog::InvokeAtPointer)) { vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); int has_removed; do { has_removed = 0; vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->PresetPool.begin(); for (; it != end; ++it) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; int id = preset->Id; if (this->GetPresetVisibility(id) && this->InvokePresetRemoveCommand(id) && this->RemovePreset(id)) { this->InvokePresetRemovedCommand(); has_removed = 1; break; } } } while (has_removed); } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetRemoveCallback() { if (this->PresetList) { // First collect the indices of the presets to remove // Then remove them vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int *indices = new int [list->GetNumberOfRows()]; int *ids = new int [list->GetNumberOfRows()]; int i, nb_selected_rows = list->GetSelectedRows(indices); for (i = 0; i < nb_selected_rows; i++) { ids[i] = this->GetIdOfPresetAtRow(indices[i]); } for (i = 0; i < nb_selected_rows; i++) { this->PresetRemoveCallback(ids[i]); } delete [] indices; delete [] ids; } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetFilterCallback() { int x, y; vtkKWTkUtilities::GetMousePointerCoordinates( this->GetApplication()->GetMainInterp(), ".", &x, &y); // Create the context menu if needed if (!this->ContextMenu) { this->ContextMenu = vtkKWMenu::New(); } if (!this->ContextMenu->IsCreated()) { this->ContextMenu->SetParent(this); this->ContextMenu->Create(); } this->ContextMenu->DeleteAllItems(); // Parse the current values // It is expected to be in the ^(value1|value2|)$ form, where the last value // may be empty to match presets with no value for this specific slot. vtksys_stl::map current_values; const char *res = this->GetPresetFilterUserSlotConstraint( this->GetFilterButtonSlotName()); if (res) { // Remove ^( and )$ const char *res_end = res + strlen(res); const char *open_regexp = "^("; if (vtksys::SystemTools::StringStartsWith(res, open_regexp)) { res += strlen(open_regexp); } const char *close_regexp = ")$"; if (vtksys::SystemTools::StringEndsWith(res, close_regexp)) { res_end -= strlen(close_regexp); } vtksys_stl::string res_safe(res, res_end - res); // Split at | and build a map of unique current values // We actually *do* need the empty value to be registered as // a valid filtering value. vtksys_stl::vector split_elems; vtksys::SystemTools::Split(res_safe.c_str(), split_elems, '|'); if (!split_elems.size()) { split_elems.push_back(""); } vtksys_stl::vector::iterator it = split_elems.begin(); vtksys_stl::vector::iterator end = split_elems.end(); for (; it != end; it++) { current_values[*it] = 1; } } // Collect all the unique possible values for that slot vtksys_stl::map possible_values; vtksys_stl::string empty_value; vtkKWPresetSelectorInternals::PresetPoolIterator it = this->Internals->PresetPool.begin(); vtkKWPresetSelectorInternals::PresetPoolIterator end = this->Internals->PresetPool.end(); for (; it != end; ++it) { vtkKWPresetSelectorInternals::PresetNode *preset = *it; // it->second; vtkKWPresetSelectorInternals::UserSlotPoolIterator s_it = preset->UserSlotPool.find(this->GetFilterButtonSlotName()); vtksys_stl::string *possible_value = NULL; // If the slot was not found, accept it as an empty value... if (s_it != preset->UserSlotPool.end()) { possible_value = &s_it->second.StringValue; } else { possible_value = &empty_value; } // Register the unique empty value (and count the occurences) vtksys_stl::map::iterator p_it_found = possible_values.find(*possible_value); if (p_it_found == possible_values.end()) { possible_values[*possible_value] = 1; } else { ++possible_values[*possible_value]; } } // Also add the current values, even if they were not found, they need // to be displayed (execept the empty one) vtksys_stl::map::iterator c_it = current_values.begin(); vtksys_stl::map::iterator c_end = current_values.end(); for (; c_it != c_end; ++c_it) { if (c_it->first.size()) { possible_values[c_it->first] = 0; } } // Build the menu, allowing the new possible values vtksys_stl::map::iterator p_it = possible_values.begin(); vtksys_stl::map::iterator p_end = possible_values.end(); for (; p_it != p_end; ++p_it) { vtksys_ios::ostringstream label; const char *possible_value = p_it->first.c_str(); label << (*possible_value ? possible_value : k_("Unknown")); // << " (" << p_it->second << ")"; int id = this->ContextMenu->AddCheckButton(label.str().c_str()); // Build the filter for this specific button (i.e. the list of // current values minus or plus this specific new possible value) vtksys_stl::map new_values(current_values); vtksys_stl::map::iterator n_it = new_values.find(p_it->first); if (n_it == new_values.end()) { new_values[p_it->first] = 1; } else { this->ContextMenu->SetItemSelectedState(id, 1); new_values.erase(n_it); } vtksys_stl::string cmd("PresetFilterApplyCallback"); if (new_values.size()) { vtksys_stl::map::iterator n_begin = new_values.begin(); vtksys_stl::map::iterator n_end = new_values.end(); vtksys_stl::string new_values_collated; for (n_it = n_begin; n_it != n_end; ++n_it) { if (n_it != n_begin) { new_values_collated += '|'; } new_values_collated += n_it->first; } cmd = cmd + " \"^(" + new_values_collated + ")$\""; } else { cmd = cmd + " \"\""; } this->ContextMenu->SetItemCommand(id, this, cmd.c_str()); } // Popup if (this->ContextMenu->GetNumberOfItems()) { this->ContextMenu->PopUp(x, y); } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetFilterApplyCallback(const char *regexp) { if (regexp && *regexp) { this->SetPresetFilterUserSlotConstraint( this->GetFilterButtonSlotName(), regexp); this->SetPresetFilterUserSlotConstraintToRegularExpression( this->GetFilterButtonSlotName()); } else { this->DeletePresetFilterUserSlotConstraint( this->GetFilterButtonSlotName()); } } //--------------------------------------------------------------------------- int vtkKWPresetSelector::GetNumberOfSelectedPresetsWithFileName() { int nb = 0; if (this->PresetList) { vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int *indices = new int [list->GetNumberOfRows()]; int i, nb_selected_rows = list->GetSelectedRows(indices); for (i = 0; i < nb_selected_rows; i++) { int id = this->GetIdOfPresetAtRow(indices[i]); const char *filename = this->GetPresetFileName(id); if (filename && *filename && vtksys::SystemTools::FileExists(filename)) { nb++; } } delete [] indices; } return nb; } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetLocateCallback(int id) { if (this->HasPreset(id)) { const char *filename = this->GetPresetFileName(id); if (filename && *filename && vtksys::SystemTools::FileExists(filename)) { this->GetApplication()->ExploreLink(filename); } } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetLocateCallback() { if (this->PresetList) { vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int *indices = new int [list->GetNumberOfRows()]; int i, nb_selected_rows = list->GetSelectedRows(indices); for (i = 0; i < nb_selected_rows; i++) { this->PresetLocateCallback(this->GetIdOfPresetAtRow(indices[i])); } delete [] indices; } } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetEmailCallback(int id) { if (!this->HasPreset(id)) { return; } const char *filename = this->GetPresetFileName(id); if (!filename || !*filename ||!vtksys::SystemTools::FileExists(filename)) { return; } vtksys_stl::string collapsed_filename = vtksys::SystemTools::CollapseFullPath(filename); vtksys_stl::string native_filename(collapsed_filename); #if _WIN32 vtksys::SystemTools::ReplaceString(native_filename, "/", "\\"); #endif const char *comment = this->GetPresetComment(id); vtksys_stl::string subject; subject = this->GetApplication()->GetPrettyName(); subject += ": \""; subject += vtksys::SystemTools::GetFilenameName(native_filename); subject += "\""; if (comment && *comment) { subject += " ("; subject += comment; subject += ")"; } vtksys_stl::string message; char buffer[500]; sprintf(buffer, ks_("Preset Selector|Email Preset|This file was sent from %s"), this->GetApplication()->GetPrettyName()); message = buffer; message += "\n\n"; message += ks_("Preset Selector|Email Preset|File:"); message += " "; message += native_filename; message += "\n"; if (comment && *comment) { message += ks_("Preset Selector|Email Preset|Comment:"); message += " "; message += comment; message += "\n"; } time_t t = (time_t)(this->GetPresetCreationTime(id) / 1000); const char *ctime_buffer = ctime(&t); if (ctime_buffer) { message += ks_("Preset Selector|Email Preset|Creation Time:"); message += " "; message += ctime_buffer; } if (this->EmailBody) { message += "\n"; message += this->EmailBody; } this->GetApplication()->SendEmail( NULL, subject.c_str(), message.c_str(), native_filename.c_str(), NULL); } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetEmailCallback() { if (this->PresetList) { vtkKWMultiColumnList *list = this->PresetList->GetWidget(); int *indices = new int [list->GetNumberOfRows()]; int i, nb_selected_rows = list->GetSelectedRows(indices); for (i = 0; i < nb_selected_rows; i++) { this->PresetEmailCallback(this->GetIdOfPresetAtRow(indices[i])); } delete [] indices; } } //--------------------------------------------------------------------------- int vtkKWPresetSelector::PresetLoadCallback() { return this->InvokePresetLoadCommand(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SchedulePresetSelectionCallback() { // Already scheduled if (this->Internals->SchedulePresetSelectionCallbackTimerId.size()) { return; } this->Internals->SchedulePresetSelectionCallbackTimerId = this->Script( "after idle {catch {%s PresetSelectionCallback}}", this->GetTclName()); } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetSelectionCallback() { this->Internals->SchedulePresetSelectionCallbackTimerId = ""; this->Update(); // this enable/disable the remove button if no selection if (this->ApplyPresetOnSelection) { this->PresetApplyCallback(); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SchedulePresetSelectionChangedCallback() { // Already scheduled if (this->Internals->SchedulePresetSelectionChangedCallbackTimerId.size()) { return; } this->Internals->SchedulePresetSelectionChangedCallbackTimerId = this->Script( "after idle {catch {%s PresetSelectionChangedCallback}}", this->GetTclName()); } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetSelectionChangedCallback() { this->Internals->SchedulePresetSelectionChangedCallbackTimerId = ""; } //--------------------------------------------------------------------------- void vtkKWPresetSelector::PresetRightClickCallback( int row, int vtkNotUsed(col), int x, int y) { int id = this->GetIdOfPresetAtRow(row); if (!this->HasPreset(id)) { return; } if (!this->ContextMenu) { this->ContextMenu = vtkKWMenu::New(); } if (!this->ContextMenu->IsCreated()) { this->ContextMenu->SetParent(this); this->ContextMenu->Create(); } this->ContextMenu->DeleteAllItems(); this->PopulatePresetContextMenu(this->ContextMenu, id); if (this->ContextMenu->GetNumberOfItems()) { this->ContextMenu->PopUp(x, y); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetAddCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->PresetAddCommand, object, method); this->Update(); // this show/hide the add button } //---------------------------------------------------------------------------- int vtkKWPresetSelector::InvokePresetAddCommand() { if (this->PresetAddCommand && *this->PresetAddCommand && this->IsCreated()) { return atoi(vtkKWTkUtilities::EvaluateSimpleString( this->GetApplication(), this->PresetAddCommand)); } return -1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetUpdateCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->PresetUpdateCommand, object, method); this->Update(); // this show/hide the update button } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvokePresetUpdateCommand(int id) { if (this->PresetUpdateCommand && *this->PresetUpdateCommand && this->IsCreated()) { this->Script("%s %d", this->PresetUpdateCommand, id); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetApplyCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->PresetApplyCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvokePresetApplyCommand(int id) { if (this->PresetApplyCommand && *this->PresetApplyCommand && this->IsCreated()) { this->Script("%s %d", this->PresetApplyCommand, id); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetRemoveCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->PresetRemoveCommand, object, method); } //---------------------------------------------------------------------------- int vtkKWPresetSelector::InvokePresetRemoveCommand(int id) { if (this->PresetRemoveCommand && *this->PresetRemoveCommand && this->IsCreated()) { return atoi(this->Script("%s %d", this->PresetRemoveCommand, id)); } return 1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetRemovedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->PresetRemovedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvokePresetRemovedCommand() { this->InvokeObjectMethodCommand(this->PresetRemovedCommand); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetHasChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->PresetHasChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvokePresetHasChangedCommand(int id) { if (this->PresetHasChangedCommand && *this->PresetHasChangedCommand && this->IsCreated()) { this->Script("%s %d", this->PresetHasChangedCommand, id); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetLoadCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->PresetLoadCommand, object, method); this->Update(); // this show/hide the load button } //---------------------------------------------------------------------------- int vtkKWPresetSelector::InvokePresetLoadCommand() { if (this->PresetLoadCommand && *this->PresetLoadCommand && this->IsCreated()) { return atoi(vtkKWTkUtilities::EvaluateSimpleString( this->GetApplication(), this->PresetLoadCommand)); } return -1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetFilteringHasChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->PresetFilteringHasChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvokePresetFilteringHasChangedCommand() { if (this->PresetFilteringHasChangedCommand && *this->PresetFilteringHasChangedCommand && this->IsCreated()) { this->InvokeObjectMethodCommand(this->PresetFilteringHasChangedCommand); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetCreateUserPresetButtonsCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->CreateUserPresetButtonsCommand, object, method); this->InvokeCreateUserPresetButtonsCommand(this->PresetButtons, 1); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvokeCreateUserPresetButtonsCommand( vtkKWToolbar *toolbar, int use_separators) { if (this->CreateUserPresetButtonsCommand && *this->CreateUserPresetButtonsCommand && this->IsCreated()) { this->Script("%s %s %d", this->CreateUserPresetButtonsCommand, toolbar->GetTclName(), use_separators); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetUpdateUserPresetButtonsCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->UpdateUserPresetButtonsCommand, object, method); this->InvokeUpdateUserPresetButtonsCommand(this->PresetButtons); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvokeUpdateUserPresetButtonsCommand( vtkKWToolbar *toolbar) { if (this->UpdateUserPresetButtonsCommand && *this->UpdateUserPresetButtonsCommand && this->IsCreated()) { this->Script("%s %s", this->UpdateUserPresetButtonsCommand, toolbar->GetTclName()); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetSetUserPresetButtonsIconsCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->SetUserPresetButtonsIconsCommand, object, method); this->InvokeSetUserPresetButtonsIconsCommand(this->PresetButtons); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvokeSetUserPresetButtonsIconsCommand( vtkKWToolbar *toolbar) { if (this->SetUserPresetButtonsIconsCommand && *this->SetUserPresetButtonsIconsCommand && this->IsCreated()) { this->Script("%s %s", this->SetUserPresetButtonsIconsCommand, toolbar->GetTclName()); } } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetSetUserPresetButtonsHelpStringsCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->SetUserPresetButtonsHelpStringsCommand, object, method); this->InvokeSetUserPresetButtonsHelpStringsCommand(this->PresetButtons); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvokeSetUserPresetButtonsHelpStringsCommand( vtkKWToolbar *toolbar) { if (this->SetUserPresetButtonsHelpStringsCommand && *this->SetUserPresetButtonsHelpStringsCommand && this->IsCreated()) { this->Script("%s %s", this->SetUserPresetButtonsHelpStringsCommand, toolbar->GetTclName()); } } //---------------------------------------------------------------------------- vtkKWToolbar* vtkKWPresetSelector::GetToolbar() { if (!this->Toolbar) { this->Toolbar = vtkKWToolbar::New(); } return this->Toolbar; } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetSelectPreviousButtonLabel() { return this->Internals->SelectPreviousButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetSelectNextButtonLabel() { return this->Internals->SelectNextButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetAddButtonLabel() { return this->Internals->AddButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetApplyButtonLabel() { return this->Internals->ApplyButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetUpdateButtonLabel() { return this->Internals->UpdateButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetRemoveButtonLabel() { return this->Internals->RemoveButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetRemoveAllButtonLabel() { return this->Internals->RemoveAllButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetLocateButtonLabel() { return this->Internals->LocateButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetEmailButtonLabel() { return this->Internals->EmailButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetLoadButtonLabel() { return this->Internals->LoadButtonLabel.c_str(); } //--------------------------------------------------------------------------- const char* vtkKWPresetSelector::GetFilterButtonLabel() { return this->Internals->FilterButtonLabel.c_str(); } //--------------------------------------------------------------------------- void vtkKWPresetSelector::Update() { this->UpdateEnableState(); this->UpdateToolbarPresetButtons(this->PresetButtons); this->UpdateToolbarPresetButtons(this->Toolbar); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::UpdateEnableState() { this->Superclass::UpdateEnableState(); if (this->PresetList) { this->PresetList->SetEnabled(this->GetEnabled()); } if (this->PresetControlFrame) { this->PresetControlFrame->SetEnabled(this->GetEnabled()); } if (this->PresetButtons) { this->PresetButtons->SetEnabled(this->GetEnabled()); } if (this->HelpLabel) { this->HelpLabel->SetEnabled(this->GetEnabled()); } this->PropagateEnableState(this->Toolbar); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::ColumnSortedCallback() { this->InvalidatePresetIdToRowIndexCache(); this->InvalidateRowIndexToPresetIdCache(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::RowMovedCallback() { this->InvalidatePresetIdToRowIndexCache(); this->InvalidateRowIndexToPresetIdCache(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetPresetIdToRowIndexCacheEntry( int id, int row_index) { this->Internals->PresetIdToRowIndexCache[id] = row_index; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetPresetIdToRowIndexCacheEntry(int id) { vtkKWPresetSelectorInternals::PresetIdToRowIndexCacheTypeIterator it = this->Internals->PresetIdToRowIndexCache.find(id); if (it != this->Internals->PresetIdToRowIndexCache.end()) { return it->second; } return -1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvalidatePresetIdToRowIndexCache() { this->Internals->PresetIdToRowIndexCache.clear(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::SetRowIndexToPresetIdCacheEntry( int row_index, int id) { this->Internals->RowIndexToPresetIdCache[row_index] = id; } //---------------------------------------------------------------------------- int vtkKWPresetSelector::GetRowIndexToPresetIdCacheEntry(int row_index) { vtkKWPresetSelectorInternals::RowIndexToPresetIdCacheTypeIterator it = this->Internals->RowIndexToPresetIdCache.find(row_index); if (it != this->Internals->RowIndexToPresetIdCache.end()) { return it->second; } return -1; } //---------------------------------------------------------------------------- void vtkKWPresetSelector::InvalidateRowIndexToPresetIdCache() { this->Internals->RowIndexToPresetIdCache.clear(); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::ProcessCallbackCommandEvents(vtkObject *caller, unsigned long event, void *calldata) { vtkKWMultiColumnList *list = this->PresetList ? this->PresetList->GetWidget() : NULL; if (caller == list) { switch (event) { case vtkKWMultiColumnList::NumberOfRowsChangedEvent: this->InvalidatePresetIdToRowIndexCache(); this->InvalidateRowIndexToPresetIdCache(); break; } } this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata); } //---------------------------------------------------------------------------- void vtkKWPresetSelector::PrintSelf(ostream& os, vtkIndent indent) { os << indent << "MaximumNumberOfPresets: " << this->MaximumNumberOfPresets << endl; os << indent << "EmailBody: " << (this->EmailBody ? this->EmailBody : "(None)") << endl; os << indent << "FilterButtonSlotName: " << (this->FilterButtonSlotName ? this->FilterButtonSlotName : "(None)") << endl; this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWRadioButton.h0000644000175000017500000000650110424463537020465 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWRadioButton.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWRadioButton - a radio button widget // .SECTION Description // A simple widget representing a radio button. The state can be set or // queried. #ifndef __vtkKWRadioButton_h #define __vtkKWRadioButton_h #include "vtkKWCheckButton.h" class KWWidgets_EXPORT vtkKWRadioButton : public vtkKWCheckButton { public: static vtkKWRadioButton* New(); vtkTypeRevisionMacro(vtkKWRadioButton,vtkKWCheckButton); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the state of the Radio button 0 = off 1 = on vtkBooleanMacro(SelectedState,int); virtual int GetSelectedState(); // Description: // Set/Get the value to store in the button's associated variable // whenever this button is selected. virtual void SetValue(const char *v); virtual void SetValueAsInt(int v); virtual const char* GetValue(); virtual int GetValueAsInt(); // Description: // Specifies a command to associate with the widget. This command is // typically invoked when the button is selected or deselected. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // Note that the selected state is *not* passed as parameter, which is // the case for vtkKWCheckButton for example. In most cases, since the // selected state is shared among many radiobuttons, this command will // likely to perform a task related to the meaning of the button itself. virtual void SetCommand(vtkObject *object, const char *method); // Description: // Events. The SelectedStateChangedEvent is triggered when the button // is selected or deselected. // The following parameters are also passed as client data: // - the current selected state: int // Yes, this is duplicated from vtkKWCheckButton, so that code does not // break when vtkKWRadioButton is not a subclass of vtkKWCheckButton anymore. //BTX enum { SelectedStateChangedEvent = 10000 }; //ETX // Description: // Set/Get the button's associated variable directly to a specific value. virtual void SetVariableValue(const char *v); virtual void SetVariableValueAsInt(int v); virtual const char* GetVariableValue(); virtual int GetVariableValueAsInt(); // Description: // Callbacks. Internal, do not use. virtual void CommandCallback(); protected: vtkKWRadioButton() {}; ~vtkKWRadioButton() {}; // Description: // Create the widget. virtual void CreateWidget(); // Override the superclass (state is ignored) virtual void InvokeCommand(int state); private: vtkKWRadioButton(const vtkKWRadioButton&); // Not implemented void operator=(const vtkKWRadioButton&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWPopupFrame.cxx0000644000175000017500000000622010424463537020662 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWPopupFrame.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWPopupFrame.h" #include "vtkKWFrame.h" #include "vtkKWFrameWithLabel.h" #include "vtkKWPopupButton.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWPopupFrame ); vtkCxxRevisionMacro(vtkKWPopupFrame, "$Revision: 1.14 $"); //---------------------------------------------------------------------------- vtkKWPopupFrame::vtkKWPopupFrame() { // GUI this->PopupMode = 0; this->PopupButton = NULL; this->Frame = vtkKWFrameWithLabel::New(); } //---------------------------------------------------------------------------- vtkKWPopupFrame::~vtkKWPopupFrame() { // GUI if (this->PopupButton) { this->PopupButton->Delete(); this->PopupButton = NULL; } if (this->Frame) { this->Frame->Delete(); this->Frame = NULL; } } //---------------------------------------------------------------------------- void vtkKWPopupFrame::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // -------------------------------------------------------------- // If in popup mode, create the popup button if (this->PopupMode) { if (!this->PopupButton) { this->PopupButton = vtkKWPopupButton::New(); } this->PopupButton->SetParent(this); this->PopupButton->Create(); } // -------------------------------------------------------------- // Create the labeled frame if (this->PopupMode) { this->Frame->AllowFrameToCollapseOff(); this->Frame->SetParent(this->PopupButton->GetPopupFrame()); } else { this->Frame->SetParent(this); } this->Frame->Create(); this->Script("pack %s -side top -anchor nw -fill both -expand y", this->Frame->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWPopupFrame::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->PopupButton); this->PropagateEnableState(this->Frame); } //---------------------------------------------------------------------------- void vtkKWPopupFrame::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Frame: " << this->Frame << endl; os << indent << "PopupMode: " << (this->PopupMode ? "On" : "Off") << endl; os << indent << "PopupButton: " << this->PopupButton << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWScale.h0000644000175000017500000003236210424463540017260 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWScale.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWScale - a scale (slider) widget // .SECTION Description // A widget that repsentes a scale (or slider). // .SECTION See Also // vtkKWScaleWithEntry #ifndef __vtkKWScale_h #define __vtkKWScale_h #include "vtkKWCoreWidget.h" class vtkKWEntry; class vtkKWLabel; class vtkKWPushButton; class vtkKWTopLevel; class KWWidgets_EXPORT vtkKWScale : public vtkKWCoreWidget { public: static vtkKWScale* New(); vtkTypeRevisionMacro(vtkKWScale,vtkKWCoreWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set the range for this scale. virtual void SetRange(double min, double max); virtual void SetRange(const double *range) { this->SetRange(range[0], range[1]); }; vtkGetVector2Macro(Range, double); virtual double GetRangeMin() { return this->GetRange()[0]; }; virtual double GetRangeMax() { return this->GetRange()[1]; }; // Description: // Set/Get the value of the scale. virtual void SetValue(double v); vtkGetMacro(Value, double); // Description: // Set/Get the resolution of the slider. // The range or the value of the scale are not snapped to this resolution. // The range and the value can be any floating point number. // Think of the slider and the resolution as a way to set the value // interactively using nice clean steps (power of 10 for example). // The entry associated to the scale can be used to set the value to // anything within the range, despite the resolution, allowing the user // to enter a precise value that could not be reached given the resolution. virtual void SetResolution(double r); vtkGetMacro(Resolution, double); // Description: // Set/Get the background color of the widget. virtual void GetBackgroundColor(double *r, double *g, double *b); virtual double* GetBackgroundColor(); virtual void SetBackgroundColor(double r, double g, double b); virtual void SetBackgroundColor(double rgb[3]) { this->SetBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the foreground color of the widget. virtual void GetForegroundColor(double *r, double *g, double *b); virtual double* GetForegroundColor(); virtual void SetForegroundColor(double r, double g, double b); virtual void SetForegroundColor(double rgb[3]) { this->SetForegroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the highlight thickness, a non-negative value indicating the // width of the highlight rectangle to draw around the outside of the // widget when it has the input focus. virtual void SetHighlightThickness(int); virtual int GetHighlightThickness(); // Description: // Set/Get the active background color of the widget. An element // (a widget or portion of a widget) is active if the mouse cursor is // positioned over the element and pressing a mouse button will cause some // action to occur. virtual void GetActiveBackgroundColor(double *r, double *g, double *b); virtual double* GetActiveBackgroundColor(); virtual void SetActiveBackgroundColor(double r, double g, double b); virtual void SetActiveBackgroundColor(double rgb[3]) { this->SetActiveBackgroundColor(rgb[0], rgb[1], rgb[2]); }; // Description: // Set/Get the border width, a non-negative value indicating the width of // the 3-D border to draw around the outside of the widget (if such a border // is being drawn; the Relief option typically determines this). virtual void SetBorderWidth(int); virtual int GetBorderWidth(); // Description: // Set/Get the 3-D effect desired for the widget. // The value indicates how the interior of the widget should appear // relative to its exterior. // Valid constants can be found in vtkKWOptions::ReliefType. virtual void SetRelief(int); virtual int GetRelief(); virtual void SetReliefToRaised(); virtual void SetReliefToSunken(); virtual void SetReliefToFlat(); virtual void SetReliefToRidge(); virtual void SetReliefToSolid(); virtual void SetReliefToGroove(); // Description: // Specifies the font to use when drawing text inside the widget. // You can use predefined font names (e.g. 'system'), or you can specify // a set of font attributes with a platform-independent name, for example, // 'times 12 bold'. In this example, the font is specified with a three // element list: the first element is the font family, the second is the // size, the third is a list of style parameters (normal, bold, roman, // italic, underline, overstrike). Example: 'times 12 {bold italic}'. // The Times, Courier and Helvetica font families are guaranteed to exist // and will be matched to the corresponding (closest) font on your system. // If you are familiar with the X font names specification, you can also // describe the font that way (say, '*times-medium-r-*-*-12*'). virtual void SetFont(const char *font); virtual const char* GetFont(); // Description: // Set/Get the orientation type. // For widgets that can lay themselves out with either a horizontal or // vertical orientation, such as scales, this option specifies which // orientation should be used. // Valid constants can be found in vtkKWOptions::OrientationType. virtual void SetOrientation(int); vtkGetMacro(Orientation, int); virtual void SetOrientationToHorizontal(); virtual void SetOrientationToVertical(); // Description: // Set/Get the trough color, i.e. the color to use for the rectangular // trough areas in widgets such as scrollbars and scales. virtual void GetTroughColor(double *r, double *g, double *b); virtual double* GetTroughColor(); virtual void SetTroughColor(double r, double g, double b); virtual void SetTroughColor(double rgb[3]) { this->SetTroughColor(rgb[0], rgb[1], rgb[2]); }; // Description // Set/Get the narrow dimension of scale. For vertical // scales this is the trough's width; for horizontal scales this is the // trough's height. In pixel. virtual void SetWidth(int width); virtual int GetWidth(); // Description // Set/Get the desired long dimension of the scale. // For vertical scales this is the scale's height, for horizontal scales // it is the scale's width. In pixel. virtual void SetLength(int length); virtual int GetLength(); // Description // Set/Get the size of the slider, measured in screen units along // the slider's long dimension. virtual void SetSliderLength(int length); virtual int GetSliderLength(); // Description: // Set/Get the visibility of the value on top of the slider. virtual void SetValueVisibility(int); virtual int GetValueVisibility(); vtkBooleanMacro(ValueVisibility, int); // Description: // Set/Get the tick interval. // Determines the spacing between numerical tick marks displayed below or to // the left of the slider. If 0, no tick marks will be displayed. virtual void SetTickInterval(double val); virtual double GetTickInterval(); // Description // Set/Get the string to display as a label for the scale. // For vertical scales the label is displayed just to the right of the top // end of the scale. For horizontal scales the label is displayed just above // the left end of the scale. If the option is specified as an empty string, // no label is displayed. The position of the label can not be changed. For // more elaborated options, check vtkKWScaleWithEntry virtual void SetLabelText(const char *); virtual const char* GetLabelText(); // Description: // Specifies commands to associate with the widget. // 'Command' is invoked when the widget value is changing (i.e. during // user interaction). // 'StartCommand' is invoked at the beginning of a user interaction with // the widget (when a mouse button is pressed over the widget for example). // 'EndCommand' is invoked at the end of the user interaction with the // widget (when the mouse button is released for example). // The need for a 'Command', 'StartCommand' and 'EndCommand' can be // explained as follows: 'EndCommand' can be used to be notified about any // changes made to this widget *after* the corresponding user interaction has // been performed (say, after releasing the mouse button that was dragging // a slider, or after clicking on a checkbutton). 'Command' can be set // *additionally* to be notified about the intermediate changes that // occur *during* the corresponding user interaction (say, *while* dragging // a slider). While setting 'EndCommand' is enough to be notified about // any changes, setting 'Command' is an application-specific choice that // is likely to depend on how fast you want (or can) answer to rapid changes // occuring during a user interaction, if any. 'StartCommand' is rarely // used but provides an opportunity for the application to modify its // state and prepare itself for user-interaction; in that case, the // 'EndCommand' is usually set in a symmetric fashion to set the application // back to its previous state. // The 'object' argument is the object that will have the method called on // it. The 'method' argument is the name of the method to be called and any // arguments in string form. If the object is NULL, the method is still // evaluated as a simple command. // The following parameters are also passed to the command: // - the current value: int (if Resolution is integer); double otherwise // Note: the 'int' signature is for convenience, so that the command can // be set to a callback accepting 'int'. In doubt, implement the callback // using a 'double' signature that will accept both 'int' and 'double'. virtual void SetCommand(vtkObject *object, const char *method); virtual void SetStartCommand(vtkObject *object, const char *method); virtual void SetEndCommand(vtkObject *object, const char *method); // Description: // Events. The ScaleValueChangingEvent is triggered when the widget value // is changed (i.e., during user interaction on the widget's slider), // the ScaleValueStartChangingEvent is invoked at the beginning of an // interaction with the widget, the ScaleValueChangedEvent is invoked at the // end of an interaction with the widget. They are similar in concept as // the 'Command', 'StartCommand', and 'EndCommand' callbacks but can be // used by multiple listeners/observers at a time. // The following parameters are also passed as client data: // - the current value: double //BTX enum { ScaleValueChangingEvent = 10000, ScaleValueChangedEvent, ScaleValueStartChangingEvent }; //ETX // Description: // Set/Get whether the above commands should be called or not. // This make it easier to disable the commands while setting the scale // value for example. vtkSetMacro(DisableCommands, int); vtkGetMacro(DisableCommands, int); vtkBooleanMacro(DisableCommands, int); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); // Description: // Turn on/off the automatic clamping of the end values when the // user types a value beyond the range. Default is on. vtkSetMacro(ClampValue, int); vtkGetMacro(ClampValue, int); vtkBooleanMacro(ClampValue, int); // Description: // Callbacks. Internal, do not use. vtkGetMacro(DisableScaleValueCallback, int); vtkSetMacro(DisableScaleValueCallback, int); vtkBooleanMacro(DisableScaleValueCallback, int); virtual void ScaleValueCallback(double num); virtual void ButtonPressCallback(); virtual void ButtonReleaseCallback(); protected: vtkKWScale(); ~vtkKWScale(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Bind/Unbind all components so that values can be changed, but // no command will be called. void Bind(); void UnBind(); int DisableScaleValueCallback; int ClampValue; double Value; double Resolution; double Range[2]; int Orientation; // Description: // Update internal widgets value virtual void UpdateRange(); virtual void UpdateResolution(); virtual void UpdateValue(); virtual void UpdateOrientation(); //BTX friend class vtkKWScaleWithEntry; //ETX int DisableCommands; char *Command; char *StartCommand; char *EndCommand; virtual void InvokeScaleCommand(const char *command, double value); virtual void InvokeCommand(double value); virtual void InvokeStartCommand(double value); virtual void InvokeEndCommand(double value); private: vtkKWScale(const vtkKWScale&); // Not implemented void operator=(const vtkKWScale&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWSurfaceMaterialPropertyWidget.cxx0000644000175000017500000001030510344064064024554 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWSurfaceMaterialPropertyWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWSurfaceMaterialPropertyWidget.h" #include "vtkKWEvent.h" #include "vtkKWScaleWithEntry.h" #include "vtkProperty.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWSurfaceMaterialPropertyWidget); vtkCxxRevisionMacro(vtkKWSurfaceMaterialPropertyWidget, "$Revision: 1.2 $"); //---------------------------------------------------------------------------- vtkKWSurfaceMaterialPropertyWidget::vtkKWSurfaceMaterialPropertyWidget() { this->PropertyChangedEvent = vtkKWEvent::SurfacePropertyChangedEvent; this->PropertyChangingEvent = vtkKWEvent::SurfacePropertyChangingEvent; this->Property = NULL; } //---------------------------------------------------------------------------- vtkKWSurfaceMaterialPropertyWidget::~vtkKWSurfaceMaterialPropertyWidget() { this->SetProperty(NULL); } //---------------------------------------------------------------------------- void vtkKWSurfaceMaterialPropertyWidget::SetProperty(vtkProperty *arg) { if (this->Property == arg) { return; } if (this->Property) { this->Property->UnRegister(this); } this->Property = arg; if (this->Property) { this->Property->Register(this); } this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWSurfaceMaterialPropertyWidget::Update() { // Call superclass this->Superclass::Update(); if (!this->IsCreated()) { return; } // Color if (this->Property) { this->SetMaterialColor(this->Property->GetColor()); } // Parameters if (this->Property) { double ambient = this->Property->GetAmbient() * 100.0; double diffuse = this->Property->GetDiffuse() * 100.0; double specular = this->Property->GetSpecular() * 100.0; double specular_power = this->Property->GetSpecularPower(); this->UpdateScales(ambient, diffuse, specular, specular_power); } // Update the image this->UpdatePreview(); } //---------------------------------------------------------------------------- int vtkKWSurfaceMaterialPropertyWidget::UpdatePropertyFromInterface() { if (!this->Property || !this->IsCreated()) { return 0; } unsigned long mtime = this->Property->GetMTime(); this->Property->SetAmbient(this->AmbientScale->GetValue() / 100.0); this->Property->SetDiffuse(this->DiffuseScale->GetValue() / 100.0); this->Property->SetSpecular(this->SpecularScale->GetValue() / 100.0); this->Property->SetSpecularPower(this->SpecularPowerScale->GetValue()); return (this->Property->GetMTime() > mtime); } //---------------------------------------------------------------------------- int vtkKWSurfaceMaterialPropertyWidget::UpdatePropertyFromPreset( const Preset *preset) { if (!this->Property || !preset) { return 0; } unsigned long mtime = this->Property->GetMTime(); this->Property->SetAmbient(preset->Ambient); this->Property->SetDiffuse(preset->Diffuse); this->Property->SetSpecular(preset->Specular); this->Property->SetSpecularPower(preset->SpecularPower); return (this->Property->GetMTime() > mtime); } //---------------------------------------------------------------------------- void vtkKWSurfaceMaterialPropertyWidget::SendStateEvent(int event) { if (!this->Property) { return; } this->InvokeEvent(event, NULL); } //---------------------------------------------------------------------------- void vtkKWSurfaceMaterialPropertyWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Property: " << this->Property << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWThumbWheel.cxx0000644000175000017500000012716011012075636020650 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWThumbWheel.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWThumbWheel.h" #include "vtkKWEntry.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWPushButton.h" #include "vtkKWTkUtilities.h" #include "vtkKWTopLevel.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkKWApplication.h" #include #include #define VTK_KW_TW_BORDER_SIZE 2 #define VTK_KW_TW_MIN_SIZE_NOTCHES 2 #define VTK_KW_TW_MIN_WIDTH 7 #define VTK_KW_TW_MIN_HEIGHT 7 #define VTK_KW_TW_NL_REFRESH_RATE 50 #define VTK_KW_TW_INDICATOR_SIZE 5 #define VTK_KW_TW_CLAMP_UCHAR_MACRO(var) if (var < 0) {var = 0;} else if (var > 255) {var = 255;} // --------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWThumbWheel ); vtkCxxRevisionMacro(vtkKWThumbWheel, "$Revision: 1.57 $"); // --------------------------------------------------------------------------- /* * This part was generated by ImageConvert from image: * arrow.png (zlib, base64) */ #define image_arrow_width 4 #define image_arrow_height 7 #define image_arrow_pixel_size 4 #define image_arrow_length 40 static unsigned char image_arrow[] = "eNpjYGD4z4AK/jOgiv1HE/uPB+PSDwcAlQUP8Q=="; // --------------------------------------------------------------------------- vtkKWThumbWheel::vtkKWThumbWheel() { this->Value = 0; this->Resolution = 1; this->ClampResolution = 0; this->NonLinearMaximumMultiplier = 20; this->ThumbWheelWidth = 80; this->ThumbWheelHeight = 16; this->ResizeThumbWheel = 1; this->SizeOfNotches = 4; this->LinearThreshold = 0.05; this->MinimumValue = 0.0; this->ClampMinimumValue = 0; this->MaximumValue = 0.0; this->ClampMaximumValue = 0; this->InteractionModes[0] = vtkKWThumbWheel::InteractionModeLinearMotion; this->InteractionModes[1] = vtkKWThumbWheel::InteractionModeNonLinearMotion; this->InteractionModes[2] = vtkKWThumbWheel::InteractionModeToggleCenterIndicator; this->ThumbWheelPositionIndicatorColor[0] = 0.91; this->ThumbWheelPositionIndicatorColor[1] = 0.41; this->ThumbWheelPositionIndicatorColor[2] = 0.22; this->DisplayLabel = 0; this->DisplayEntry = 0; this->DisplayEntryAndLabelOnTop = 1; this->DisplayThumbWheelPositionIndicator = 1; this->DisplayThumbWheelCenterIndicator = 0; this->PopupMode = 0; this->ExpandEntry = 0; this->Command = NULL; this->StartCommand = NULL; this->EndCommand = NULL; this->EntryCommand = NULL; this->ThumbWheel = vtkKWLabel::New(); this->Entry = NULL; this->Label = NULL; this->TopLevel = NULL; this->PopupPushButton = NULL; this->State = vtkKWThumbWheel::Idle; this->ThumbWheelShift = 0.0; this->InInvokeCommand = 0; } // --------------------------------------------------------------------------- vtkKWThumbWheel::~vtkKWThumbWheel() { if (this->Command) { delete [] this->Command; this->Command = NULL; } if (this->StartCommand) { delete [] this->StartCommand; this->StartCommand = NULL; } if (this->EndCommand) { delete [] this->EndCommand; this->EndCommand = NULL; } if (this->EntryCommand) { delete [] this->EntryCommand; this->EntryCommand = NULL; } if (this->ThumbWheel) { this->ThumbWheel->Delete(); this->ThumbWheel = NULL; } if (this->Entry) { this->Entry->Delete(); this->Entry = NULL; } if (this->Label) { this->Label->Delete(); this->Label = NULL; } if (this->TopLevel) { this->TopLevel->Delete(); this->TopLevel = NULL; } if (this->PopupPushButton) { this->PopupPushButton->Delete(); this->PopupPushButton = NULL; } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // If we need the scale to popup, create the top level window accordingly // and its push button if (this->PopupMode) { this->TopLevel = vtkKWTopLevel::New(); this->TopLevel->SetApplication(this->GetApplication()); this->TopLevel->Create(); this->TopLevel->SetBackgroundColor(0.0, 0.0, 0.0); this->TopLevel->SetBorderWidth(2); this->TopLevel->SetReliefToFlat(); this->TopLevel->HideDecorationOn(); this->TopLevel->Withdraw(); this->TopLevel->SetMasterWindow(this); this->PopupPushButton = vtkKWPushButton::New(); this->PopupPushButton->SetParent(this); this->PopupPushButton->Create(); this->PopupPushButton->SetPadX(0); this->PopupPushButton->SetPadY(0); this->PopupPushButton->SetImageToPixels(image_arrow, image_arrow_width, image_arrow_height, image_arrow_pixel_size, image_arrow_length); this->ThumbWheel->SetParent(this->TopLevel); } else { this->ThumbWheel->SetParent(this); } // Create the scale this->ThumbWheel->Create(); this->ThumbWheel->SetBorderWidth(VTK_KW_TW_BORDER_SIZE); this->ThumbWheel->SetHighlightThickness(0); this->ThumbWheel->SetReliefToSunken(); this->UpdateThumbWheelImage(); this->Bind(); this->PackWidget(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetValue(double arg) { if (this->ClampMinimumValue && arg < this->MinimumValue) { arg = this->MinimumValue; } if (this->ClampMaximumValue && arg > this->MaximumValue) { arg = this->MaximumValue; } if (this->ClampResolution && this->Resolution != 0.0) { double offset = arg - this->MinimumValue; double frac = offset / this->Resolution; int steps = (int)frac; arg = this->MinimumValue + steps * this->Resolution; } if (this->Value == arg) { // Pass the value to the entry to keep it in sync with the thumb wheel this->RefreshValue(); return; } this->Value = arg; this->Modified(); this->RefreshValue(); this->InvokeCommand(this->GetValue()); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::RefreshValue() { if (this->Entry && this->Entry->IsCreated()) { this->Entry->SetValueAsDouble(this->Value); } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetResolution(double arg) { if (this->Resolution == arg) { return; } this->Resolution = arg; this->Modified(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetThumbWheelWidth(int arg) { if (this->ThumbWheelWidth == arg) { return; } this->ThumbWheelWidth = (arg < VTK_KW_TW_MIN_WIDTH ? VTK_KW_TW_MIN_WIDTH : arg); this->Modified(); this->UpdateThumbWheelImage(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetThumbWheelHeight(int arg) { if (this->ThumbWheelHeight == arg) { return; } this->ThumbWheelHeight = (arg < VTK_KW_TW_MIN_HEIGHT ? VTK_KW_TW_MIN_HEIGHT : arg); this->Modified(); this->UpdateThumbWheelImage(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetResizeThumbWheel(int arg) { if (this->ResizeThumbWheel == arg) { return; } this->ResizeThumbWheel = arg; this->Modified(); this->Bind(); this->PackWidget(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetDisplayThumbWheelCenterIndicator(int arg) { if (this->DisplayThumbWheelCenterIndicator == arg) { return; } this->DisplayThumbWheelCenterIndicator = arg; this->Modified(); this->UpdateThumbWheelImage(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::ToggleDisplayThumbWheelCenterIndicator() { if (this->DisplayThumbWheelCenterIndicator) { this->DisplayThumbWheelCenterIndicatorOff(); } else { this->DisplayThumbWheelCenterIndicatorOn(); } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::ResizeThumbWheelCallback() { int tw, th; vtkKWTkUtilities::GetWidgetSize(this->ThumbWheel, &tw, &th); // Remove the border size (-bd) tw -= VTK_KW_TW_BORDER_SIZE * 2; th -= VTK_KW_TW_BORDER_SIZE * 2; if (this->ThumbWheelWidth == tw && this->ThumbWheelHeight == th) { return; } this->ThumbWheelWidth = (tw < VTK_KW_TW_MIN_WIDTH ? VTK_KW_TW_MIN_WIDTH : tw); this->ThumbWheelHeight = (th < VTK_KW_TW_MIN_HEIGHT ? VTK_KW_TW_MIN_HEIGHT : th); this->UpdateThumbWheelImage(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetSizeOfNotches(double arg) { if (this->SizeOfNotches == arg) { return; } this->SizeOfNotches = (arg < VTK_KW_TW_MIN_SIZE_NOTCHES ? VTK_KW_TW_MIN_SIZE_NOTCHES : arg); this->Modified(); this->UpdateThumbWheelImage(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::CreateEntry() { if (this->Entry && this->Entry->IsCreated()) { return; } this->Entry = vtkKWEntry::New(); this->Entry->SetParent(this); this->Entry->Create(); this->Entry->SetWidth(7); this->PropagateEnableState(this->Entry); this->Entry->SetValueAsDouble(this->GetValue()); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetDisplayEntry(int arg) { if (this->DisplayEntry == arg) { return; } this->DisplayEntry = arg; this->Modified(); if (this->DisplayEntry && !this->Entry) { this->CreateEntry(); } this->Bind(); this->PackWidget(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::CreateLabel() { if (this->Label && this->Label->IsCreated()) { return; } this->Label = vtkKWLabel::New(); this->Label->SetParent(this); this->Label->Create(); this->PropagateEnableState(this->Label); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetDisplayLabel(int arg) { if (this->DisplayLabel == arg) { return; } this->DisplayLabel = arg; this->Modified(); if (this->DisplayLabel && !this->Label) { this->CreateLabel(); } this->Bind(); this->PackWidget(); } // --------------------------------------------------------------------------- vtkKWLabel* vtkKWThumbWheel::GetLabel() { if (!this->Label) { this->CreateLabel(); } return this->Label; } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetDisplayEntryAndLabelOnTop(int arg) { if (this->DisplayEntryAndLabelOnTop == arg) { return; } this->DisplayEntryAndLabelOnTop = arg; this->Modified(); this->PackWidget(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetExpandEntry(int arg) { if (this->ExpandEntry == arg) { return; } this->ExpandEntry = arg; this->Modified(); this->PackWidget(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetInteractionMode(int mode, int arg) { if (mode < 0 || mode > 2 || this->InteractionModes[mode] == arg) { return; } this->InteractionModes[mode] = arg; if (this->InteractionModes[mode] < vtkKWThumbWheel::InteractionModeNone) { this->InteractionModes[mode] = vtkKWThumbWheel::InteractionModeNone; } else if (this->InteractionModes[mode] > vtkKWThumbWheel::InteractionModeToggleCenterIndicator) { this->InteractionModes[mode] = vtkKWThumbWheel::InteractionModeToggleCenterIndicator; } this->Modified(); this->Bind(); } // --------------------------------------------------------------------------- int vtkKWThumbWheel::GetInteractionMode(int mode) { if (mode < 0 || mode > 2) { return vtkKWThumbWheel::InteractionModeNone; } return InteractionModes[mode]; } //---------------------------------------------------------------------------- char *vtkKWThumbWheel::GetInteractionModeAsString(int mode) { if (mode < 0 || mode > 2) { return NULL; } switch (this->InteractionModes[mode]) { case vtkKWThumbWheel::InteractionModeNone: return (char *)"None"; case vtkKWThumbWheel::InteractionModeLinearMotion: return (char *)"Linear"; case vtkKWThumbWheel::InteractionModeNonLinearMotion: return (char *)"NonLinear"; case vtkKWThumbWheel::InteractionModeToggleCenterIndicator: return (char *)"ToggleCenterIndicator"; default: return (char *)"Unknown"; } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::PackWidget() { if (this->ThumbWheel && this->ThumbWheel->IsCreated()) { if (this->DisplayEntryAndLabelOnTop && !this->PopupMode) { this->Script("pack %s -side bottom -fill x -expand %d -pady 0 -padx 0", this->ThumbWheel->GetWidgetName(), this->ResizeThumbWheel); } else { this->Script("pack %s -side left -fill x -expand %d -pady 0 -padx 0", this->ThumbWheel->GetWidgetName(), this->ResizeThumbWheel); } } if (this->Label && this->Label->IsCreated()) { this->Script("pack forget %s", this->Label->GetWidgetName()); if (this->DisplayLabel) { if (this->DisplayEntryAndLabelOnTop || this->PopupMode) { this->Script("pack %s -side left -padx 0 -fill y", this->Label->GetWidgetName()); } else { this->Script("pack %s -side left -padx 0 -fill y -before %s", this->Label->GetWidgetName(), this->ThumbWheel->GetWidgetName()); } } } if (this->Entry && this->Entry->IsCreated()) { this->Script("pack forget %s", this->Entry->GetWidgetName()); if (this->DisplayEntry) { if (this->PopupMode) { this->Script("pack %s -side left -padx 0 %s", this->Entry->GetWidgetName(), (this->ExpandEntry ? "-fill both -expand t" : "-fill y")); } else { if (this->DisplayEntryAndLabelOnTop) { this->Script("pack %s -side right -padx 0 -fill y", this->Entry->GetWidgetName()); } else { this->Script("pack %s -side right -padx 0 -fill y -after %s", this->Entry->GetWidgetName(), this->ThumbWheel->GetWidgetName()); } } } } if (this->PopupMode && this->PopupPushButton && this->PopupPushButton->IsCreated()) { this->Script("pack forget %s", this->PopupPushButton->GetWidgetName()); if (this->DisplayLabel || this->DisplayEntry) { this->Script("pack %s -side left -padx 1 -fill y -ipadx 1 -after %s", this->PopupPushButton->GetWidgetName(), (this->Entry ? this->Entry->GetWidgetName() : this->Label->GetWidgetName())); } else { this->Script("pack %s -side left -padx 1 -fill y -ipadx 1", this->PopupPushButton->GetWidgetName()); } } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::Bind() { if (this->ThumbWheel && this->ThumbWheel->IsCreated()) { this->ThumbWheel->SetBinding( "", this, "StopMotionCallback"); // Interaction modes char button_event[20], motion_event[20]; int i; for (i = 0 ; i < 3; i++) { int b = i + 1; sprintf(button_event, "", b); sprintf(motion_event, "", b); switch (this->InteractionModes[i]) { case vtkKWThumbWheel::InteractionModeLinearMotion: this->ThumbWheel->SetBinding( button_event, this, "StartLinearMotionCallback"); this->ThumbWheel->SetBinding( motion_event, this, "PerformLinearMotionCallback"); break; case vtkKWThumbWheel::InteractionModeNonLinearMotion: this->ThumbWheel->SetBinding( button_event, this, "StartNonLinearMotionCallback"); this->ThumbWheel->RemoveBinding( motion_event); break; case vtkKWThumbWheel::InteractionModeToggleCenterIndicator: this->ThumbWheel->SetBinding( button_event, this, "ToggleDisplayThumbWheelCenterIndicator"); this->ThumbWheel->RemoveBinding( motion_event); break; default: this->ThumbWheel->RemoveBinding( button_event); this->ThumbWheel->RemoveBinding( motion_event); } } // Auto resize if (this->ResizeThumbWheel) { this->ThumbWheel->SetBinding( "", this, "ResizeThumbWheelCallback"); } else { this->ThumbWheel->RemoveBinding(""); } // If in popup mode and the mouse is leaving the top level window, // then withdraw it, unless the user is interacting with the wheel. if (this->PopupMode && this->TopLevel && this->TopLevel->IsCreated()) { this->TopLevel->SetBinding("", this, "WithdrawPopupCallback"); vtksys_stl::string callback; int j; for (j = 0 ; j < 3; j++) { sprintf(button_event, "", j + 1); this->ThumbWheel->AddBinding( button_event, this->TopLevel, "RemoveBinding "); } callback = "SetBinding "; callback += " "; callback += this->GetTclName(); callback += " WithdrawPopupCallback"; this->ThumbWheel->AddBinding( "", this->TopLevel, callback.c_str()); } } if (this->Entry && this->Entry->IsCreated()) { this->Entry->SetCommand(this, "EntryValueCallback"); } if (this->PopupMode && this->PopupPushButton && this->PopupPushButton->IsCreated()) { this->PopupPushButton->SetBinding( "", this, "DisplayPopupCallback"); } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::UnBind() { if (this->ThumbWheel && this->ThumbWheel->IsCreated()) { this->ThumbWheel->RemoveBinding(""); this->ThumbWheel->RemoveBinding(""); char button_event[20], motion_event[20]; int i; for (i = 0 ; i < 3; i++) { sprintf(button_event, "", i + 1); sprintf(motion_event, "", i + 1); this->ThumbWheel->RemoveBinding(button_event); this->ThumbWheel->RemoveBinding(motion_event); } this->ThumbWheel->RemoveBinding(""); } if (this->Entry && this->Entry->IsCreated()) { this->Entry->SetCommand(NULL, NULL); } if (this->PopupMode && this->PopupPushButton && this->PopupPushButton->IsCreated()) { this->PopupPushButton->RemoveBinding(""); } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::DisplayPopupCallback() { if (!this->PopupMode || !this->PopupPushButton || !this->PopupPushButton->IsCreated() || !this->TopLevel || !this->TopLevel->IsCreated() || !this->ThumbWheel || !this->ThumbWheel->IsCreated()) { return; } // Get the position of the mouse, the position and size of the push button, // the size of the scale. int x, y, py, ph, tw, th; vtkKWTkUtilities::GetMousePointerCoordinates(this, &x, &y); vtkKWTkUtilities::GetWidgetCoordinates(this->PopupPushButton, NULL, &py); vtkKWTkUtilities::GetWidgetSize(this->PopupPushButton, NULL, &ph); vtkKWTkUtilities::GetWidgetSize(this->ThumbWheel, &tw, &th); // Place the scale so that the slider is coincident with the x mouse position // and just below the push button x -= tw / 2; if (py <= y && y <= (py + ph -1)) { y = py + ph - 3; } else { y -= th / 2; } this->TopLevel->SetPosition(x, y); this->GetApplication()->ProcessPendingEvents(); this->TopLevel->DeIconify(); this->TopLevel->Raise(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::WithdrawPopupCallback() { if (!this->PopupMode || !this->TopLevel || !this->TopLevel->IsCreated() || !this->ThumbWheel || !this->ThumbWheel->IsCreated()) { return; } // Withdraw the popup this->TopLevel->Withdraw(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::EntryValueCallback(const char *) { double value = this->Entry->GetValueAsDouble(); double old_value = this->GetValue(); this->SetValue(value); if (value != old_value) { this->InvokeEntryCommand(this->GetValue()); } } // --------------------------------------------------------------------------- // Return normalized mouse position relative to the thumbwheel. // i.e. if the mouse is "inside" the thumbwheel, the range is [0.0, 1.0] // (< 0.0 if position < lower limit , > 1.0 if position > upper limit) double vtkKWThumbWheel::GetMousePositionInThumbWheel() { int x, tx; vtkKWTkUtilities::GetMousePointerCoordinates(this, &x, NULL); vtkKWTkUtilities::GetWidgetCoordinates(this->ThumbWheel, &tx, NULL); return (double)(x - tx - VTK_KW_TW_BORDER_SIZE) / (double)(this->ThumbWheelWidth - 1); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::StartLinearMotionCallback() { if (this->State == vtkKWThumbWheel::InMotion) { this->StopMotionCallback(); } this->State = vtkKWThumbWheel::InMotion; // Save current state (mouse position, thumbwheel shift, value) this->StartLinearMotionState.MousePosition = this->GetMousePositionInThumbWheel(); this->StartLinearMotionState.ThumbWheelShift = this->ThumbWheelShift; this->StartLinearMotionState.Value = this->Value; this->StartLinearMotionState.InPerform = 0; // If the position indicator has to be shown, drawing the wheel if (this->DisplayThumbWheelPositionIndicator) { this->UpdateThumbWheelImage(this->StartLinearMotionState.MousePosition); } this->InvokeStartCommand(this->GetValue()); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::PerformLinearMotionCallback() { if (this->State != vtkKWThumbWheel::InMotion || this->StartLinearMotionState.InPerform) { return; } this->StartLinearMotionState.InPerform = 1; // pos: mouse position relative to the wheel range [0.0, 1.0] // distance: distance between current pos and starting pos double pos = this->GetMousePositionInThumbWheel(); double distance = pos - this->StartLinearMotionState.MousePosition; double linear_threshold = this->LinearThreshold; if (linear_threshold <= 0) { linear_threshold = 1.0 / ((this->MaximumValue - this->MinimumValue) / this->Resolution + 1); } double new_value = this->StartLinearMotionState.Value + (distance / linear_threshold) * this->Resolution; // Update thumbwheel aspect this->ThumbWheelShift = this->StartLinearMotionState.ThumbWheelShift + distance; this->UpdateThumbWheelImage(pos); // If the resolution implies an integer, round the value if (!this->ClampResolution && (double)((int)this->Resolution) == this->Resolution) { this->SetValue((int)(new_value)); } else { this->SetValue(new_value); } this->StartLinearMotionState.InPerform = 0; } // --------------------------------------------------------------------------- void vtkKWThumbWheel::StartNonLinearMotionCallback() { if (this->State == vtkKWThumbWheel::InMotion) { this->StopMotionCallback(); } this->State = vtkKWThumbWheel::InMotion; // Save current state (value) this->StartNonLinearMotionState.Value = this->Value; this->StartNonLinearMotionState.Increment = 0.0; this->StartNonLinearMotionState.InPerform = 0; this->InvokeStartCommand(this->GetValue()); // Now perform the motion immediately this->PerformNonLinearMotionCallback(); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::PerformNonLinearMotionCallback() { if (this->State != vtkKWThumbWheel::InMotion || this->StartNonLinearMotionState.InPerform) { return; } this->StartNonLinearMotionState.InPerform = 1; // Get current mouse position, compute "speed", update increment // pos: mouse position relative to the wheel range [0.0, 1.0], clamped // xn: mouse position value mapped to [-1.0, 1.0], i.e. cos() // angle: angle corresponding to that xn // yn: sin(angle), i.e. [0.0, 1.0] double pos = this->GetMousePositionInThumbWheel(); if (pos < 0.0) { pos = 0.0; } else if (pos > 1.0) { pos = 1.0; } double xn = pos * 2.0 - 1.0; double yn = sin(acos(xn)); double direction = (xn < 0.0 ? -1.0 : 1.0); // Compute the non-linear increment corresponding to that position, and // add it to the increment buffer which will be added to the value (can // not update value directly since it can be rounded/clamped by SetValue) double inc = ((1.0 - yn) * (this->NonLinearMaximumMultiplier - 0.0) + 0.0) * this->Resolution; this->StartNonLinearMotionState.Increment += inc * direction; double new_value = this->StartNonLinearMotionState.Value + this->StartNonLinearMotionState.Increment; // Update thumbwheel aspect (accelerates depending on the position) double shift = (0.0704321 + (1.0 - yn) * 0.00543) * direction; this->ThumbWheelShift += shift; this->UpdateThumbWheelImage(pos); // If the resolution implies an integer, round the value if ((double)((int)this->Resolution) == this->Resolution) { this->SetValue((int)(new_value)); } else { this->SetValue(new_value); } // Check if we are still in motion later (asynchronously) this->Script("after %d {catch {%s PerformNonLinearMotionCallback}}", VTK_KW_TW_NL_REFRESH_RATE, this->GetTclName()); this->StartNonLinearMotionState.InPerform = 0; } // --------------------------------------------------------------------------- void vtkKWThumbWheel::StopMotionCallback() { this->State = vtkKWThumbWheel::Idle; // If the position indicator was shown, hide it by redrawing the wheel if (this->DisplayThumbWheelPositionIndicator) { this->UpdateThumbWheelImage(); } this->InvokeEndCommand(this->GetValue()); } //---------------------------------------------------------------------------- void vtkKWThumbWheel::InvokeThumbWheelCommand( const char *command, double value) { if (command && *command && this->GetApplication()) { // As a convenience, try to detect if we are manipulating integers, and // invoke the callback with the approriate type. if ((double)((long int)this->Resolution) == this->Resolution) { this->Script("%s %ld", command, (long int)value); } else { this->Script("%s %lf", command, value); } } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetCommand(vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->Command, object, method); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::InvokeCommand(double value) { if (this->InInvokeCommand) { return; } this->InInvokeCommand = 1; this->InvokeThumbWheelCommand(this->Command, value); this->InvokeEvent(vtkKWThumbWheel::ThumbWheelValueChangingEvent, &value); this->InInvokeCommand = 0; } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetStartCommand(vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->StartCommand, object, method); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::InvokeStartCommand(double value) { this->InvokeThumbWheelCommand(this->StartCommand, value); this->InvokeEvent( vtkKWThumbWheel::ThumbWheelValueStartChangingEvent, &value); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetEndCommand(vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->EndCommand, object, method); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::InvokeEndCommand(double value) { this->InvokeThumbWheelCommand(this->EndCommand, value); this->InvokeEvent( vtkKWThumbWheel::ThumbWheelValueChangedEvent, &value); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetEntryCommand(vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->EntryCommand, object, method); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::InvokeEntryCommand(double value) { this->InvokeThumbWheelCommand(this->EntryCommand, value); this->InvokeEvent(vtkKWThumbWheel::ThumbWheelValueChangedEvent, &value); } // --------------------------------------------------------------------------- void vtkKWThumbWheel::SetBalloonHelpString(const char *string) { // Interaction modes if (string) { vtksys_ios::ostringstream modes; modes << string << " ("; int i; for (i = 0 ; i < 3; i++) { if (this->InteractionModes[i] == vtkKWThumbWheel::InteractionModeNone) { continue; } switch (i) { case 0: modes << "left"; break; case 1: modes << "middle"; break; case 2: modes << "right"; break; } modes << " button: "; switch (this->InteractionModes[i]) { case vtkKWThumbWheel::InteractionModeLinearMotion: modes << "linear"; break; case vtkKWThumbWheel::InteractionModeNonLinearMotion: modes << "non-linear"; break; case vtkKWThumbWheel::InteractionModeToggleCenterIndicator: modes << "toggle center indicator"; break; default: modes << "unknown"; } if ((i == 0 && (this->InteractionModes[1] != vtkKWThumbWheel::InteractionModeNone || this->InteractionModes[2] != vtkKWThumbWheel::InteractionModeNone)) || (i == 1 && this->InteractionModes[2] != vtkKWThumbWheel::InteractionModeNone)) { modes << ", "; } } modes << ")"; this->ThumbWheel->SetBalloonHelpString(modes.str().c_str()); } else { this->ThumbWheel->SetBalloonHelpString(string); } if (this->Entry) { this->Entry->SetBalloonHelpString(string); } if (this->Label) { this->Label->SetBalloonHelpString(string); } if (this->PopupMode && this->PopupPushButton) { if (string) { vtksys_ios::ostringstream temp; temp << string << " " << ks_("Popup ThumbWheel|(press this button to display a thumbwheel)"); this->PopupPushButton->SetBalloonHelpString(temp.str().c_str()); } else { this->PopupPushButton->SetBalloonHelpString(string); } } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->Entry); this->PropagateEnableState(this->Label); this->PropagateEnableState(this->ThumbWheel); this->PropagateEnableState(this->TopLevel); this->PropagateEnableState(this->PopupPushButton); if (this->GetEnabled()) { this->Bind(); } else { this->UnBind(); } } // --------------------------------------------------------------------------- void vtkKWThumbWheel::UpdateThumbWheelImage(double pos) { // Show position indicator ? Compute range int posx_start = 0, posx_end = 0; double indicator_hsv[3], bg_hsv[3]; if (this->DisplayThumbWheelPositionIndicator && this->State == vtkKWThumbWheel::InMotion) { int posx = (int)(pos * (double)(this->ThumbWheelWidth - 1)); posx_start = posx - (int)floor((double)(VTK_KW_TW_INDICATOR_SIZE - 1) * 0.5); posx_end = posx + (int)floor((double)(VTK_KW_TW_INDICATOR_SIZE) * 0.5); if (posx_start < 0) { posx_end -= posx_start; posx_start = 0; } if (posx_end > (this->ThumbWheelWidth - 1)) { posx_start -= (posx_end - (this->ThumbWheelWidth - 1)); posx_end = this->ThumbWheelWidth - 1; } vtkMath::RGBToHSV(this->ThumbWheelPositionIndicatorColor, indicator_hsv); } vtkMath::RGBToHSV(this->GetBackgroundColor(), bg_hsv); double width2 = 0.5 * (double)(this->ThumbWheelWidth - 1); // gray_global_shift: added to gray values (used to darken or lighten aspect) // gray_relief_shift: added to gray values to provide the "notch" relief/shadow int gray_global_shift = -20; int gray_relief_shift = 35; int img_pixel_size = 3; int img_row_size = img_pixel_size * this->ThumbWheelWidth; int img_buffer_size = img_row_size * this->ThumbWheelHeight; // notch_size: size of a notch given the number of notches in a half-wheel double notch_size = 1.0 / ((double)this->ThumbWheelWidth / (double)this->SizeOfNotches); int last_notch = 0; int relief_flag = 0; // Allocate buffer for the whole wheel unsigned char *img_buffer = new unsigned char[img_buffer_size]; // img_ptr_s0: 1st row = gray - shadow * 2 (i.e. dark shadow) // img_ptr_s1: 2nd row = gray - shadow (i.e. ligh shadow) // img_ptr: 3rd row = gray (i.e. normal aspect) unsigned char *img_ptr_s0 = img_buffer; unsigned char *img_ptr_s1 = img_ptr_s0 + img_row_size; unsigned char *img_ptr = img_ptr_s1 + img_row_size; double r, g, b; int x; for (x = 0; x < this->ThumbWheelWidth; x++) { // xn: x value mapped to [-1.0, 1.0], i.e. cos() // angle: angle corresponding to that xn // yn: sin(angle), i.e. [0.0, 1.0] // anglen: normalized angle (+ shift), i.e. mapped to [0.0, 1.0] // notch: index of the current notch given the current angle double xn = -1.0 + (double)x / width2; double angle = acos(xn); double yn = sin(angle); double anglen = fmod(angle / 3.14159265358979 + this->ThumbWheelShift, 1.0); int notch = (int)(floor(anglen / notch_size)); // gray: the gray value for the current pixel in the notch // gray_s0: gray + dark shadow // gray_s1: gray + light shadow int gray = (int)(255.0 * yn + gray_global_shift); // If the current x position is a transition from one notch to // the other, add some "relief" by first (relief_flag == 0) casting // a shadow (i.e. gray - gray_relief_shift), then (relief_flag == 1) // casting a highlight (i.e. gray + gray_relief_shift) if (x == 0) { last_notch = notch; } else if (notch != last_notch) { if (relief_flag == 0) { gray -= gray_relief_shift; relief_flag = 1; } else { gray += gray_relief_shift; relief_flag = 0; last_notch = notch; } } // Now the dark and light shadow for the first and second rows of the wheel int gray_s0 = gray - gray_relief_shift * 2; int gray_s1 = gray - gray_relief_shift; // Clamp and assign VTK_KW_TW_CLAMP_UCHAR_MACRO(gray); VTK_KW_TW_CLAMP_UCHAR_MACRO(gray_s0); VTK_KW_TW_CLAMP_UCHAR_MACRO(gray_s1); if (this->DisplayThumbWheelPositionIndicator && this->State == vtkKWThumbWheel::InMotion && x >= posx_start && x <= posx_end) { vtkMath::HSVToRGB( indicator_hsv[0], indicator_hsv[1], (double)gray / 255.0, &r, &g, &b); *img_ptr++ = (int)(r * 255.0); *img_ptr++ = (int)(g * 255.0); *img_ptr++ = (int)(b * 255.0); vtkMath::HSVToRGB( indicator_hsv[0], indicator_hsv[1], (double)gray_s0/255.0, &r, &g, &b); *img_ptr_s0++ = (int)(r * 255.0); *img_ptr_s0++ = (int)(g * 255.0); *img_ptr_s0++ = (int)(b * 255.0); vtkMath::HSVToRGB( indicator_hsv[0], indicator_hsv[1], (double)gray_s1/255.0, &r, &g, &b); *img_ptr_s1++ = (int)(r * 255.0); *img_ptr_s1++ = (int)(g * 255.0); *img_ptr_s1++ = (int)(b * 255.0); } else { vtkMath::HSVToRGB( bg_hsv[0], bg_hsv[1], (double)gray / 255.0, &r, &g, &b); *img_ptr++ = (int)(r * 255.0); *img_ptr++ = (int)(g * 255.0); *img_ptr++ = (int)(b * 255.0); vtkMath::HSVToRGB( bg_hsv[0], bg_hsv[1], (double)gray_s0/255.0, &r, &g, &b); *img_ptr_s0++ = (int)(r * 255.0); *img_ptr_s0++ = (int)(g * 255.0); *img_ptr_s0++ = (int)(b * 255.0); vtkMath::HSVToRGB( bg_hsv[0], bg_hsv[1], (double)gray_s1/255.0, &r, &g, &b); *img_ptr_s1++ = (int)(r * 255.0); *img_ptr_s1++ = (int)(g * 255.0); *img_ptr_s1++ = (int)(b * 255.0); } } // Copy the 1st row to the last row, then 2nd row to last-1 row, so // that we got symetrical vertical shadow memcpy(img_buffer + img_buffer_size - img_row_size, img_ptr_s0 - img_row_size, img_row_size); memcpy(img_buffer + img_buffer_size - img_row_size * 2, img_ptr_s1 - img_row_size, img_row_size); // Copy the 3rd row to the remaining rows (the body of the wheel) int y; for (y = 3; y < this->ThumbWheelHeight - 2; y++) { memcpy(img_ptr, img_ptr_s1, img_row_size); img_ptr += img_row_size; } // Now add a center indicator #define VTK_KW_TW_INDICATOR_WIDTH 7 #define VTK_KW_TW_INDICATOR_HEIGHT 6 static int indicator[VTK_KW_TW_INDICATOR_WIDTH*VTK_KW_TW_INDICATOR_HEIGHT] = { -1, -1, -1, 0, -1, -1, -1, -1, -1, 0, 3, 0, -1, -1, -1, 0, 3, 2, 1, 0, -1, 0, 3, 2, 2, 2, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; if (this->DisplayThumbWheelCenterIndicator) { int gray[4]; gray[2] = 240 + gray_global_shift; gray[3] = (int)(gray[2] + 1.7 * gray_relief_shift); gray[1] = (int)(gray[2] - 1.7 * gray_relief_shift); gray[0] = (int)(gray[2] - 3.4 * gray_relief_shift); VTK_KW_TW_CLAMP_UCHAR_MACRO(gray[0]); VTK_KW_TW_CLAMP_UCHAR_MACRO(gray[1]); VTK_KW_TW_CLAMP_UCHAR_MACRO(gray[2]); VTK_KW_TW_CLAMP_UCHAR_MACRO(gray[3]); int show_up_indicator = (this->ThumbWheelHeight >= VTK_KW_TW_INDICATOR_HEIGHT * 2 + 2); int distance_to_indicator = (int)floor( 0.5 * (this->ThumbWheelWidth-1-VTK_KW_TW_INDICATOR_WIDTH))*img_pixel_size; img_ptr = img_buffer + img_buffer_size - img_row_size * VTK_KW_TW_INDICATOR_HEIGHT + distance_to_indicator; int *indicator_ptr = indicator; unsigned char *img_ptr2 = 0; if (show_up_indicator) { img_ptr2 = img_buffer + img_row_size * (VTK_KW_TW_INDICATOR_HEIGHT-1) + distance_to_indicator; } for (y = 0; y < VTK_KW_TW_INDICATOR_HEIGHT; y++) { if (show_up_indicator) { for (x = 0; x < VTK_KW_TW_INDICATOR_WIDTH; x++) { if (*indicator_ptr >= 0) { img_ptr[0] = img_ptr[1] = img_ptr[2] = img_ptr2[0] = img_ptr2[1] = img_ptr2[2] = gray[*indicator_ptr]; } img_ptr += img_pixel_size; img_ptr2 += img_pixel_size; indicator_ptr++; } img_ptr += img_row_size - VTK_KW_TW_INDICATOR_WIDTH * img_pixel_size; img_ptr2 += -img_row_size - VTK_KW_TW_INDICATOR_WIDTH * img_pixel_size; } else { for (x = 0; x < VTK_KW_TW_INDICATOR_WIDTH; x++) { if (*indicator_ptr >= 0) { img_ptr[0] = img_ptr[1] = img_ptr[2] = gray[*indicator_ptr]; } img_ptr += img_pixel_size; indicator_ptr++; } img_ptr += img_row_size - VTK_KW_TW_INDICATOR_WIDTH * img_pixel_size; } } } // Update the Tk photo this->ThumbWheel->SetImageToPixels(img_buffer, this->ThumbWheelWidth, this->ThumbWheelHeight, img_pixel_size); delete [] img_buffer; } //---------------------------------------------------------------------------- void vtkKWThumbWheel::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Value: " << this->Value << endl; os << indent << "MinimumValue: " << this->MinimumValue << endl; os << indent << "MaximumValue: " << this->MaximumValue << endl; os << indent << "ClampMinimumValue: " << (this->ClampMinimumValue ? "On" : "Off") << endl; os << indent << "ClampMaximumValue: " << (this->ClampMaximumValue ? "On" : "Off") << endl; os << indent << "Resolution: " << this->Resolution << endl; os << indent << "NonLinearMaximumMultiplier: " << this->NonLinearMaximumMultiplier << endl; os << indent << "ThumbWheelWidth: " << this->ThumbWheelWidth << endl; os << indent << "ThumbWheelHeight: " << this->ThumbWheelHeight << endl; os << indent << "SizeOfNotches: " << this->SizeOfNotches << endl; os << indent << "LinearThreshold: " << this->LinearThreshold << endl; os << indent << "ThumbWheelPositionIndicatorColor: (" << this->ThumbWheelPositionIndicatorColor[0] << ", " << this->ThumbWheelPositionIndicatorColor[1] << ", " << this->ThumbWheelPositionIndicatorColor[2] << ")\n"; os << indent << "ResizeThumbWheel: " << (this->ResizeThumbWheel ? "On" : "Off") << endl; int i; for (i = 0; i < 3; i++) { os << indent << "InteractionMode[" << i << "]: " << this->GetInteractionModeAsString(i) << endl; } os << indent << "DisplayLabel: " << (this->DisplayLabel ? "On" : "Off") << endl; os << indent << "DisplayEntry: " << (this->DisplayEntry ? "On" : "Off") << endl; os << indent << "DisplayEntryAndLabelOnTop: " << (this->DisplayEntryAndLabelOnTop ? "On" : "Off") << endl; os << indent << "DisplayThumbWheelPositionIndicator: " << (this->DisplayThumbWheelPositionIndicator ? "On" : "Off") << endl; os << indent << "DisplayThumbWheelCenterIndicator: " << (this->DisplayThumbWheelCenterIndicator ? "On" : "Off") << endl; os << indent << "PupupMode: " << (this->PopupMode ? "On" : "Off") << endl; os << indent << "ExpandEntry: " << (this->ExpandEntry ? "On" : "Off") << endl; os << indent << "Label: " << this->Label << endl; os << indent << "Entry: " << this->Entry << endl; os << indent << "PopupPushButton: " << this->PopupPushButton << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWDialog.h0000644000175000017500000000604511105126610017416 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWDialog.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWDialog - dialog box superclass // .SECTION Description // A generic superclass for dialog boxes. // This is a toplevel that is modal by default, and centered in its // master window (or on screen) #ifndef __vtkKWDialog_h #define __vtkKWDialog_h #include "vtkKWTopLevel.h" class KWWidgets_EXPORT vtkKWDialog : public vtkKWTopLevel { public: static vtkKWDialog* New(); vtkTypeRevisionMacro(vtkKWDialog,vtkKWTopLevel); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Invoke the dialog, display it and enter an event loop until the user // confirms or cancels the dialog. // Create() will be called automatically by PreInvoke() if the dialog // has not been Create'd() yet. // Note that a dialog is a modal toplevel by default. // This method returns 0 if the dialog was killed or // canceled, 1 otherwise. The status can be further refined // by querying GetStatus(). virtual int Invoke(); // Description: // Display the dialog. // Create() will be called automatically if the dialog // has not been Create'd() yet. // Note that a dialog is a modal toplevel by default. virtual void Display(); // Description: // Status of the dialog (active e.g. displayed, canceled, OK'ed) //BTX enum { StatusActive = 0, StatusCanceled = 1, StatusOK = 2 }; //ETX int GetStatus() { return this->Done; }; // Description: // Return frame to pack into. vtkKWWidget* GetFrame() { return this; } // Description: // Play beep when the dialog is displayed vtkSetClampMacro(Beep, int, 0, 1); vtkBooleanMacro(Beep, int); vtkGetMacro(Beep, int); // Description: // Callback. Cancel the action and close this dialog virtual void Cancel(); // Description: // Callback. Confirm the action and close this dialog virtual void OK(); // Description: // Dialog can be also used by performing individual steps of Invoke. These // steps are initialize: PreInvoke(), finalize: PostInvoke(), and check if // user responded IsUserDoneWithDialog(). Use this method only if you // want to bypass the event loop used in Invoke() by creating your own // and checking for IsUserDoneWithDialog(). virtual int PreInvoke(); virtual void PostInvoke(); virtual int IsUserDoneWithDialog(); protected: vtkKWDialog(); ~vtkKWDialog() {}; // Description: // Create the widget. virtual void CreateWidget(); int Done; int Beep; private: vtkKWDialog(const vtkKWDialog&); // Not implemented void operator=(const vtkKWDialog&); // Not Implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWUserInterfaceManager.h0000644000175000017500000002266111075261666022274 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWUserInterfaceManager.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWUserInterfaceManager - a user interface manager. // .SECTION Description // This class is used to abstract the way a set of interface "panels" // (vtkKWUserInterfacePanel) can be grouped inside a widget. // For example, if a concrete implementation of that class // uses a notebook as its underlying widget, then it will deliver a notebook's // page when one of its managed panels request a "page" (i.e. a section // within a panel). If another concrete implementation chooses for // a flat GUI for example, then it will likely return frames as pages and // pack them on top of each other. // This class is not a widget. Concrete implementation of this class will // provide an access point to a widget into which the manager will organize // its panels (a notebook, a frame, etc.). // Besides packing this widget, you will just have to set each panel's // UserInterfaceManager ivar to point to this manager, and the rest should // be taken care of (i.e. you do not need to manually add a panel to a manager, // or manually request a page from the manager, it should be done through the // panel's API). // .SECTION See Also // vtkKWUserInterfaceManagerNotebook vtkKWUserInterfacePanel #ifndef __vtkKWUserInterfaceManager_h #define __vtkKWUserInterfaceManager_h #include "vtkKWObject.h" class vtkKWIcon; class vtkKWWidget; class vtkKWUserInterfacePanel; class vtkKWUserInterfaceManagerInternals; class KWWidgets_EXPORT vtkKWUserInterfaceManager : public vtkKWObject { public: vtkTypeRevisionMacro(vtkKWUserInterfaceManager,vtkKWObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Create the manager widget (i.e. the widget that will group and display // all user interface panels). virtual void Create(); virtual int IsCreated(); // Description: // Enable/Disable this interface. This propagates SetEnabled() calls to all // panels. virtual void SetEnabled(int); virtual void UpdateEnableState(); // Description: // Iterate over all panels and call Update() for each one. This will refresh // the panels (provided that Update() has been reimplemented). virtual void Update(); // Description: // Add a panel to the manager. // Note that you most probably do not need to call this method, since setting // a panel's UserInterfaceManager ivar will add the panel automatically // (see vtkKWUserInterfacePanel::SetUserInterfaceManager()). // Return a unique positive ID corresponding to that panel, or < 0 on error. virtual int AddPanel(vtkKWUserInterfacePanel *panel); virtual int HasPanel(vtkKWUserInterfacePanel *panel); // Description: // Get the number of panel virtual int GetNumberOfPanels(); // Description: // Get the panel from its name or ID, from a page ID (return the ID of the // panel that holds that page), or the nth panel. virtual vtkKWUserInterfacePanel* GetPanel(const char *panel_name); virtual vtkKWUserInterfacePanel* GetPanel(int id); virtual vtkKWUserInterfacePanel* GetPanelFromPageId(int id) = 0; virtual vtkKWUserInterfacePanel* GetNthPanel(int rank); // Description: // Remove a panel (or all) from the manager. // Note that you most probably do not need to call this method, since setting // a panel's UserInterfaceManager ivar to NULL will remove the panel // automatically (this is done in the panel's destructor). // Return 1 on success, 0 on error. virtual int RemovePanel(vtkKWUserInterfacePanel *panel); virtual void RemoveAllPanels(); // Description: // Instruct the manager to reserve or remove a page for a given panel. // Note that you should use the panel's own API to add a page to a panel: // this will automatically call this method with the proper panel parameter // (see vtkKWUserInterfacePanel::AddPage() and // vtkKWUserInterfacePanel::RemovePage()). // Return a unique positive ID for the page that was reserved/removed, // or < 0 on error. virtual int AddPage(vtkKWUserInterfacePanel *panel, const char *title, const char *balloon = 0, vtkKWIcon *icon = 0) = 0; virtual int RemovePage(vtkKWUserInterfacePanel *panel, const char *title) = 0; // Description: // Set a page's title, balloon help and icon. virtual void SetPageTitle(int id, const char *title) = 0; virtual void SetPageBalloonHelpString(int id, const char *str) = 0; virtual void SetPageIcon(int id, vtkKWIcon *icon) = 0; virtual void SetPageIconToPredefinedIcon(int id, int icon_index) = 0; // Description: // Retrieve the widget corresponding to a given page reserved by the manager. // This can be done through the unique page ID, or using a panel and the // page title. The user UI components should be inserted into this widget. // Note that you should use the panel's own API to get a page widget: this // will automatically call this method with the proper ID or panel parameter // (see vtkKWUserInterfacePanel::GetPageWidget()). // Return NULL on error. virtual vtkKWWidget* GetPageWidget(int id) = 0; virtual vtkKWWidget* GetPageWidget(vtkKWUserInterfacePanel *panel, const char *title) = 0; // Description: // Retrieve the parent widget of the pages associated to a panel. It is // the unique widget that is common to all pages in the chain of parents. // Note that you should use the panel's own API to get the page parent: this // will automatically call this method with the proper panel parameter // (see vtkKWUserInterfacePanel::GetPagesParentWidget()). virtual vtkKWWidget *GetPagesParentWidget(vtkKWUserInterfacePanel *panel)= 0; // Description: // Raise a page reserved by the manager. This can be done through the unique // page ID, or using a panel and the page title. // Note that you should use the panel's own API to raise a page: this // will automatically call this method with the proper ID or panel parameter // (see vtkKWUserInterfacePanel::RaisePage()). virtual void RaisePage(int id) = 0; virtual void RaisePage(vtkKWUserInterfacePanel *panel, const char *title) = 0; // Description: // Show/Hide a panel. It will make sure the pages reserved by the manager // for this panel are shown/hidden. // RaisePanel() behaves like ShowPanel(), but it will also try to bring // up the first page of the panel to the front (i.e., "select" it). // IsPanelVisible() checks if the pages of the panel are visible/shown. // Note that you should use the panel's own API to show/raise a panel: this // will automatically call this method with the proper panel parameter // (see vtkKWUserInterfacePanel::Show/Raise()). // Return 1 on success, 0 on error. virtual int ShowPanel(vtkKWUserInterfacePanel *panel) = 0; virtual int HidePanel(vtkKWUserInterfacePanel *panel) = 0; virtual int IsPanelVisible(vtkKWUserInterfacePanel *panel) = 0; virtual int RaisePanel(vtkKWUserInterfacePanel *panel) { return this->ShowPanel(panel); }; // Description: // Show/hide all panels. virtual void ShowAllPanels(); virtual void HideAllPanels(); // Description: // Update a panel according to the manager settings (i.e., it just performs // manager-specific changes on the panel). Note that it does not call the // panel's Update() method, on the opposite the panel's Update() will call // this method if the panel has a UIM set. virtual void UpdatePanel(vtkKWUserInterfacePanel *) {}; protected: vtkKWUserInterfaceManager(); ~vtkKWUserInterfaceManager(); // Description: // Remove the widgets of all pages belonging to a panel. It is called // by RemovePanel() and should be overloaded if the concrete implementation // of the manager needs to unmap/unpack widgets before everything is deleted. // Return 1 on success, 0 on error. virtual int RemovePageWidgets(vtkKWUserInterfacePanel *) { return 1; }; int IdCounter; //BTX // A panel slot associate a panel to a unique Id class PanelSlot { public: int Id; vtkKWUserInterfacePanel *Panel; }; // PIMPL Encapsulation for STL containers vtkKWUserInterfaceManagerInternals *Internals; friend class vtkKWUserInterfaceManagerInternals; // Helper methods // Get a panel slot given a panel or an id, check if the manager has a given // panel, get a panel id given a panel, etc. PanelSlot* GetPanelSlot(vtkKWUserInterfacePanel *panel); PanelSlot* GetPanelSlot(int id); PanelSlot* GetPanelSlot(const char *panel_name); PanelSlot* GetNthPanelSlot(int rank); int GetPanelId(vtkKWUserInterfacePanel *panel); //ETX // Description: // This method is (and should be) called each time the number of panels // changes (for example, after AddPanel() / RemovePanel()) virtual void NumberOfPanelsChanged() {}; private: int ManagerIsCreated; vtkKWUserInterfaceManager(const vtkKWUserInterfaceManager&); // Not implemented void operator=(const vtkKWUserInterfaceManager&); // Not Implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWOptions.h0000644000175000017500000001173210464737265017676 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWOptions.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWOptions - set of common options. // .SECTION Description // This class also provides some conversion betweek vtkKWWidget constants // and the corresponding Tk options. #ifndef __vtkKWOptions_h #define __vtkKWOptions_h #include "vtkObject.h" #include "vtkKWWidgets.h" // Needed for export symbols directives class KWWidgets_EXPORT vtkKWOptions : public vtkObject { public: static vtkKWOptions* New(); vtkTypeRevisionMacro(vtkKWOptions,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Specifies how the information in a widget (e.g. text or a bitmap) is to // be displayed in the widget. //BTX enum AnchorType { AnchorNorth = 0, AnchorNorthEast, AnchorEast, AnchorSouthEast, AnchorSouth, AnchorSouthWest, AnchorWest, AnchorNorthWest, AnchorCenter, AnchorUnknown }; //ETX // Description: // Specifies the 3-D effect desired for the widget. The value indicates how // the interior of the widget should appear relative to its exterior. //BTX enum ReliefType { ReliefRaised = 0, ReliefSunken, ReliefFlat, ReliefRidge, ReliefSolid, ReliefGroove, ReliefUnknown }; //ETX // Description: // When there are multiple lines of text displayed in a widget, // determines how the lines line up with each other. //BTX enum JustificationType { JustificationLeft = 0, JustificationCenter, JustificationRight, JustificationUnknown }; //ETX // Description: // Specifies one of several styles for manipulating the selection. //BTX enum SelectionModeType { SelectionModeSingle = 0, SelectionModeBrowse, SelectionModeMultiple, SelectionModeExtended, SelectionModeUnknown }; //ETX // Description: // For widgets that can lay themselves out with either a horizontal or // vertical orientation, such as scales or scrollbars, specifies which // orientation should be used. //BTX enum OrientationType { OrientationHorizontal = 0, OrientationVertical, OrientationUnknown }; //ETX // Description: // Specifies the state of a widget. //BTX enum StateType { StateDisabled = 0, StateNormal = 1, StateActive = 2, StateReadOnly = 3, StateUnknown }; //ETX // Description: // Specifies if the widget should display text and bitmaps/images at the // same time, and if so, where the bitmap/image should be placed relative // to the text. //BTX enum CompoundModeType { CompoundModeNone = 0, CompoundModeLeft, CompoundModeCenter, CompoundModeRight, CompoundModeTop, CompoundModeBottom, CompoundModeUnknown }; //ETX // Description: // Return the Tcl value for a given encoding constant // Check vtkSystemIncludes for a list of valid encodings. static const char* GetCharacterEncodingAsTclOptionValue(int); // Description: // Return the Tk value for a given anchor constant, and vice-versa static const char* GetAnchorAsTkOptionValue(int); static int GetAnchorFromTkOptionValue(const char *); // Description: // Return the Tk value for a given relief constant, and vice-versa static const char* GetReliefAsTkOptionValue(int); static int GetReliefFromTkOptionValue(const char *); // Description: // Return the Tk value for a given justification constant, and vice-versa. static const char* GetJustificationAsTkOptionValue(int); static int GetJustificationFromTkOptionValue(const char *); // Description: // Return the Tk value for a given selection mode constant, and vice-versa. static const char* GetSelectionModeAsTkOptionValue(int); static int GetSelectionModeFromTkOptionValue(const char *); // Description: // Return the Tk value for a given orientation constant, and vice-versa. static const char* GetOrientationAsTkOptionValue(int); static int GetOrientationFromTkOptionValue(const char *); // Description: // Return the Tk value for a given state constant, and vice-versa. static const char* GetStateAsTkOptionValue(int); static int GetStateFromTkOptionValue(const char *); // Description: // Return the Tk value for a given compound constant, and vice-versa. static const char* GetCompoundModeAsTkOptionValue(int); static int GetCompoundModeFromTkOptionValue(const char *); protected: vtkKWOptions() {}; ~vtkKWOptions() {}; private: vtkKWOptions(const vtkKWOptions&); // Not implemented void operator=(const vtkKWOptions&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWToolbar.cxx0000644000175000017500000007675111111321026020202 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWToolbar.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWToolbar.h" #include "vtkKWCheckButton.h" #include "vtkKWFrame.h" #include "vtkKWPushButton.h" #include "vtkKWRadioButton.h" #include "vtkKWTkUtilities.h" #include "vtkObjectFactory.h" #include "vtkKWPushButtonWithMenu.h" #include "vtkKWLabel.h" #include "vtkKWMenuButton.h" #include "vtkKWSeparator.h" #include "vtkKWWidgetWithLabel.h" #include #include #include static int vtkKWToolbarGlobalToolbarAspect = vtkKWToolbar::ToolbarAspectFlat; static int vtkKWToolbarGlobalWidgetsAspect = vtkKWToolbar::WidgetsAspectFlat; const char *vtkKWToolbar::ToolbarAspectRegKey = "ToolbarFlatFrame"; const char *vtkKWToolbar::WidgetsAspectRegKey = "ToolbarFlatButtons"; //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWToolbar ); vtkCxxRevisionMacro(vtkKWToolbar, "$Revision: 1.77 $"); //---------------------------------------------------------------------------- class vtkKWToolbarInternals { public: class WidgetNode { public: vtkKWWidget *Widget; int Visibility; }; typedef vtksys_stl::list WidgetsContainer; typedef vtksys_stl::list::iterator WidgetsContainerIterator; WidgetsContainer Widgets; }; //---------------------------------------------------------------------------- vtkKWToolbar::vtkKWToolbar() { this->Frame = vtkKWFrame::New(); this->Handle = vtkKWFrame::New(); this->ToolbarAspect = vtkKWToolbar::GetGlobalToolbarAspect(); this->WidgetsAspect = vtkKWToolbar::GetGlobalWidgetsAspect(); this->Resizable = 0; this->Expanding = 0; this->WidgetsFlatAdditionalPadX = 0; this->WidgetsFlatAdditionalPadY = 0; this->WidgetsPadX = 1; this->WidgetsPadY = 1; this->WidgetsInternalPadX = 1; this->WidgetsInternalPadY = 1; this->WidgetsFlatAdditionalInternalPadX = 0; this->WidgetsFlatAdditionalInternalPadY = 0; // This widget is used to keep track of default options this->DefaultOptionsWidget = vtkKWRadioButton::New(); // Internal structs this->Internals = new vtkKWToolbarInternals; this->Name = NULL; } //---------------------------------------------------------------------------- vtkKWToolbar::~vtkKWToolbar() { if (this->IsAlive()) { this->UnBind(); } if (this->Frame) { this->Frame->Delete(); this->Frame = 0; } if (this->Handle) { this->Handle->Delete(); this->Handle = 0; } if (this->DefaultOptionsWidget) { this->DefaultOptionsWidget->Delete(); this->DefaultOptionsWidget = NULL; } this->RemoveAllWidgets(); if (this->Internals) { delete this->Internals; } this->SetName(NULL); } //---------------------------------------------------------------------------- void vtkKWToolbar::Bind() { this->SetBinding("", this, "ScheduleResize"); } //---------------------------------------------------------------------------- void vtkKWToolbar::UnBind() { this->RemoveBinding(""); } //---------------------------------------------------------------------------- void vtkKWToolbar::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); this->Bind(); // Create the widgets container itself this->Frame->SetParent(this); this->Frame->Create(); // Create a "toolbar handle" this->Handle->SetParent(this); this->Handle->Create(); this->Handle->SetBorderWidth(2); this->Handle->SetReliefToRaised(); // Create the default options repository (never packed, just a way // to keep track of default options) this->DefaultOptionsWidget->SetParent(this); this->DefaultOptionsWidget->Create(); // Update aspect this->Update(); } //---------------------------------------------------------------------------- void vtkKWToolbar::AddWidget(vtkKWWidget *widget) { if (!widget || !this->Internals) { return; } vtkKWToolbarInternals::WidgetNode node; node.Widget = widget; node.Visibility = 1; this->Internals->Widgets.push_back(node); widget->Register(this); this->PropagateEnableState(widget); this->UpdateWidgets(); } //---------------------------------------------------------------------------- void vtkKWToolbar::InsertWidget(vtkKWWidget *location, vtkKWWidget *widget) { if (!widget || !this->Internals) { return; } vtkKWToolbarInternals::WidgetNode node; node.Widget = widget; node.Visibility = 1; if (!location) { this->Internals->Widgets.push_front(node); } else { vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { if ((*it).Widget == location) { break; } } if (it == this->Internals->Widgets.end()) { this->Internals->Widgets.push_front(node); } else { this->Internals->Widgets.insert(it, node); } } widget->Register(this); this->PropagateEnableState(widget); this->UpdateWidgets(); } //---------------------------------------------------------------------------- void vtkKWToolbar::AddSeparator() { vtkKWSeparator *sep = vtkKWSeparator::New(); sep->SetOrientationToVertical(); sep->SetParent(this->GetFrame()); sep->Create(); this->AddWidget(sep); sep->Delete(); } //---------------------------------------------------------------------------- void vtkKWToolbar::InsertSeparator(vtkKWWidget* location) { vtkKWSeparator *sep = vtkKWSeparator::New(); sep->SetOrientationToVertical(); sep->SetParent(this->GetFrame()); sep->Create(); this->InsertWidget(location, sep); sep->Delete(); } //---------------------------------------------------------------------------- int vtkKWToolbar::HasWidget(vtkKWWidget *widget) { if (!widget || !this->Internals) { return 0; } vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { if ((*it).Widget == widget) { return 1; } } return 0; } //---------------------------------------------------------------------------- int vtkKWToolbar::GetWidgetVisibility(vtkKWWidget *widget) { if (!widget || !this->Internals) { return 0; } vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { if ((*it).Widget == widget) { return (*it).Visibility; } } return 0; } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetVisibility(vtkKWWidget *widget, int val) { if (!widget || !this->Internals) { return; } vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { if ((*it).Widget == widget) { (*it).Visibility = val; this->UpdateWidgets(); break; } } } //---------------------------------------------------------------------------- int vtkKWToolbar::GetNumberOfWidgets() { if (this->Internals) { return (int)this->Internals->Widgets.size(); } return 0; } //---------------------------------------------------------------------------- void vtkKWToolbar::RemoveWidget(vtkKWWidget *widget) { if (!widget || !this->Internals) { return; } vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { if ((*it).Widget == widget) { break; } } if (it == this->Internals->Widgets.end()) { vtkErrorMacro("Unable to remove widget from toolbar"); return; } (*it).Widget->UnRegister(this); this->Internals->Widgets.erase(it); this->UpdateWidgets(); } //---------------------------------------------------------------------------- void vtkKWToolbar::RemoveAllWidgets() { if (!this->Internals) { return; } vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { (*it).Widget->UnRegister(this); } this->Internals->Widgets.clear(); this->UpdateWidgets(); } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWToolbar::GetWidget(const char *name) { if (name && this->Internals) { const char *options[4] = { "-label", "-text", "-image", "-selectimage" }; vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { vtkKWCoreWidget *core = vtkKWCoreWidget::SafeDownCast((*it).Widget); if (core && core->IsCreated()) { for (int i = 0; i < 4; i++) { if (core->HasConfigurationOption(options[i])) { const char *option = core->GetConfigurationOption(options[i]); if (!strcmp(name, option)) { return core; } } } vtkKWWidgetWithLabel *wwl = vtkKWWidgetWithLabel::SafeDownCast((*it).Widget); if (wwl) { core = wwl->GetLabel(); for (int i = 0; i < 4; i++) { if (core->HasConfigurationOption(options[i])) { const char *option = core->GetConfigurationOption(options[i]); if (!strcmp(name, option)) { return wwl; } } } } } } } return NULL; } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWToolbar::GetNthWidget(int rank) { if (this->Internals) { vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end && rank >= 0; ++it, --rank) { if (rank == 0) { return (*it).Widget; } } } return NULL; } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWToolbar::AddRadioButtonImage(int value, const char *image_name, const char *select_image_name, const char *variable_name, vtkObject *object, const char *method, const char *help) { if (!this->IsCreated()) { return 0; } vtkKWRadioButton *rb = vtkKWRadioButton::New(); rb->SetParent(this->GetFrame()); rb->Create(); rb->IndicatorVisibilityOff(); rb->SetValueAsInt(value); if (image_name) { rb->SetHighlightThickness(0); rb->SetConfigurationOption("-image", image_name); rb->SetConfigurationOption( "-selectimage", (select_image_name ? select_image_name : image_name)); } if (object && method) { rb->SetCommand(object, method); } if (variable_name) { rb->SetVariableName(variable_name); } if (help) { rb->SetBalloonHelpString(help); } this->AddWidget(rb); rb->Delete(); return rb; } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWToolbar::AddCheckButtonImage(const char *image_name, const char *select_image_name, const char *variable_name, vtkObject *object, const char *method, const char *help) { if (!this->IsCreated()) { return 0; } vtkKWCheckButton *cb = vtkKWCheckButton::New(); cb->SetParent(this->GetFrame()); cb->Create(); cb->IndicatorVisibilityOff(); if (image_name) { cb->SetHighlightThickness(0); cb->SetConfigurationOption("-image", image_name); cb->SetConfigurationOption( "-selectimage", (select_image_name ? select_image_name : image_name)); } if (object && method) { cb->SetCommand(object, method); } if (variable_name) { cb->SetVariableName(variable_name); } if (help) { cb->SetBalloonHelpString(help); } this->AddWidget(cb); cb->Delete(); return cb; } //---------------------------------------------------------------------------- void vtkKWToolbar::ScheduleResize() { if (this->Expanding || !this->IsCreated()) { return; } this->Expanding = 1; this->Script("after idle {catch {%s Resize}}", this->GetTclName()); } //---------------------------------------------------------------------------- void vtkKWToolbar::Resize() { this->UpdateWidgets(); this->Expanding = 0; } //---------------------------------------------------------------------------- void vtkKWToolbar::UpdateWidgetsAspect() { if (!this->IsCreated() || !this->Internals || this->Internals->Widgets.size() <= 0) { return; } vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { vtkKWPushButton *pb = vtkKWPushButton::SafeDownCast((*it).Widget); vtkKWCheckButton *cb = vtkKWCheckButton::SafeDownCast((*it).Widget); vtkKWRadioButton *rb = vtkKWRadioButton::SafeDownCast((*it).Widget); vtkKWPushButtonWithMenu *pbwm = vtkKWPushButtonWithMenu::SafeDownCast((*it).Widget); vtkKWMenuButton *mb = vtkKWMenuButton::SafeDownCast((*it).Widget); if (pb) { if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat) { pb->SetReliefToFlat(); pb->SetOverReliefToSolid(); pb->SetBorderWidth(1); } else if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectRelief) { pb->SetReliefToRaised(); pb->SetOverReliefToNone(); pb->SetBorderWidth(1); } } else if (mb) { if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat) { mb->SetReliefToFlat(); mb->SetBorderWidth(1); } else if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectRelief) { mb->SetReliefToRaised(); mb->SetBorderWidth(1); } } else if (pbwm) { mb = pbwm->GetMenuButton(); pb = pbwm->GetPushButton(); if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat) { pb->SetReliefToFlat(); pb->SetOverReliefToSolid(); pb->SetBorderWidth(1); mb->SetReliefToFlat(); mb->SetBorderWidth(1); } else if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectRelief) { pb->SetReliefToRaised(); pb->SetOverReliefToNone(); pb->SetBorderWidth(1); mb->SetReliefToRaised(); mb->SetBorderWidth(1); } } else if (cb) { if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat) { cb->SetReliefToFlat(); cb->SetOffReliefToFlat(); cb->SetOverReliefToSolid(); cb->SetBorderWidth(1); } else if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectRelief) { cb->SetReliefToFlat(); cb->SetOffReliefToRaised(); cb->SetOverReliefToNone(); cb->SetBorderWidth(1); } } else if (rb) { if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat) { rb->SetReliefToFlat(); rb->SetOffReliefToFlat(); rb->SetOverReliefToSolid(); rb->SetBorderWidth(1); } else if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectRelief) { rb->SetReliefToFlat(); rb->SetOffReliefToRaised(); rb->SetOverReliefToNone(); rb->SetBorderWidth(1); } } } } //---------------------------------------------------------------------------- void vtkKWToolbar::ConstrainWidgetsLayout() { if (!this->IsCreated() || !this->Internals || this->Internals->Widgets.size() <= 0) { return; } int totReqWidth = 0; vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { int reqw = 0; vtkKWTkUtilities::GetWidgetRequestedSize((*it).Widget, &reqw, NULL); totReqWidth += this->WidgetsPadX + this->WidgetsInternalPadX + reqw; if (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat) { totReqWidth += this->WidgetsFlatAdditionalPadX + this->WidgetsFlatAdditionalInternalPadX; } } int width = 0; vtkKWTkUtilities::GetWidgetSize(this, &width, NULL); int widthWidget = totReqWidth / (int)this->Internals->Widgets.size(); int numPerRow = width / widthWidget; if ( numPerRow > 0 ) { int row = 0, num = 0; vtksys_ios::ostringstream grid_tk; it = this->Internals->Widgets.begin(); for (; it != end; ++it) { if ((*it).Visibility) { grid_tk << "grid " << (*it).Widget->GetWidgetName() << " -row " << row << " -column " << num << " -sticky news " << " -in " << this->GetFrame()->GetWidgetName() << " -padx " << (this->WidgetsPadX + (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat ? this->WidgetsFlatAdditionalPadX : 0)) << " -pady " << (this->WidgetsPadY + (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat ? this->WidgetsFlatAdditionalPadY : 0)); if (!vtkKWSeparator::SafeDownCast((*it).Widget)) { grid_tk << " -ipadx " << (this->WidgetsInternalPadX + (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat ? this->WidgetsFlatAdditionalInternalPadX : 0)) << " -ipady " << (this->WidgetsInternalPadY + (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat ? this->WidgetsFlatAdditionalInternalPadY : 0)); } grid_tk << endl; num++; if (num == numPerRow) { row++; num = 0; } } else { grid_tk << "grid forget " << (*it).Widget->GetWidgetName() << endl; } } while (row >= 0) { grid_tk << "grid rowconfigure " << this->GetFrame()->GetWidgetName() << " "<< row << " -weight 1 " << endl; --row; } this->Script(grid_tk.str().c_str()); } } //---------------------------------------------------------------------------- void vtkKWToolbar::UpdateWidgetsLayout() { if (!this->IsCreated() || !this->Internals || this->Internals->Widgets.size() <= 0) { return; } this->GetFrame()->UnpackChildren(); // If this toolbar is resizable, then constrain it to the current size if (this->Resizable) { this->ConstrainWidgetsLayout(); return; } vtkKWToolbarInternals::WidgetsContainerIterator it; vtkKWToolbarInternals::WidgetsContainerIterator begin = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); // Factorize the separators vtkKWToolbarInternals::WidgetsContainerIterator previous_sep_it = end; vtkKWToolbarInternals::WidgetsContainerIterator previous_widget_it = end; for (it = begin; it != end; ++it) { vtkKWSeparator *sep = vtkKWSeparator::SafeDownCast((*it).Widget); if (sep) { if (previous_widget_it == end) { (*it).Visibility = 0; // no widgets before sep } else { previous_sep_it = it; previous_widget_it = end; } } else { if ((*it).Visibility) { previous_widget_it = it; if (previous_sep_it != end) { (*previous_sep_it).Visibility = 1; // show the separator previous_sep_it = end; } } } } if (previous_sep_it != end) { (*previous_sep_it).Visibility = 0; // orphan at the end } // Pack vtksys_ios::ostringstream grid_tk, grid_forget_tk; grid_forget_tk << "grid forget "; size_t nb_in_grid = 0; for (it = begin; it != end; ++it) { if ((*it).Visibility) { grid_tk << "grid " << (*it).Widget->GetWidgetName() << " -sticky news -row 0 -column " << nb_in_grid << " -in " << this->GetFrame()->GetWidgetName() << " -padx " << (this->WidgetsPadX + (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat ? this->WidgetsFlatAdditionalPadX : 0)) << " -pady " << (this->WidgetsPadY + (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat ? this->WidgetsFlatAdditionalPadY : 0)); if (!vtkKWSeparator::SafeDownCast((*it).Widget)) { grid_tk << " -ipadx " << (this->WidgetsInternalPadX + (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat ? this->WidgetsFlatAdditionalInternalPadX : 0)) << " -ipady " << (this->WidgetsInternalPadY + (this->WidgetsAspect == vtkKWToolbar::WidgetsAspectFlat ? this->WidgetsFlatAdditionalInternalPadY : 0)); } grid_tk << endl; ++nb_in_grid; } else { grid_forget_tk << " " << (*it).Widget->GetWidgetName(); } } if (nb_in_grid) { this->Script(grid_tk.str().c_str()); } if (nb_in_grid != this->Internals->Widgets.size()) { this->Script(grid_forget_tk.str().c_str()); } this->Script("grid rowconfigure %s 0 -weight 1", this->GetFrame()->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWToolbar::UpdateWidgets() { this->UpdateWidgetsAspect(); this->UpdateWidgetsLayout(); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetsPadX(int arg) { if (arg == this->WidgetsPadX) { return; } this->WidgetsPadX = arg; this->Modified(); this->UpdateWidgetsLayout(); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetsPadY(int arg) { if (arg == this->WidgetsPadY) { return; } this->WidgetsPadY = arg; this->Modified(); this->UpdateWidgetsLayout(); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetsFlatAdditionalPadX(int arg) { if (arg == this->WidgetsFlatAdditionalPadX) { return; } this->WidgetsFlatAdditionalPadX = arg; this->Modified(); this->UpdateWidgetsLayout(); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetsFlatAdditionalPadY(int arg) { if (arg == this->WidgetsFlatAdditionalPadY) { return; } this->WidgetsFlatAdditionalPadY = arg; this->Modified(); this->UpdateWidgetsLayout(); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetsInternalPadX(int arg) { if (arg == this->WidgetsInternalPadX) { return; } this->WidgetsInternalPadX = arg; this->Modified(); this->UpdateWidgetsLayout(); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetsInternalPadY(int arg) { if (arg == this->WidgetsInternalPadY) { return; } this->WidgetsInternalPadY = arg; this->Modified(); this->UpdateWidgetsLayout(); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetsFlatAdditionalInternalPadX(int arg) { if (arg == this->WidgetsFlatAdditionalInternalPadX) { return; } this->WidgetsFlatAdditionalInternalPadX = arg; this->Modified(); this->UpdateWidgetsLayout(); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetsFlatAdditionalInternalPadY(int arg) { if (arg == this->WidgetsFlatAdditionalInternalPadY) { return; } this->WidgetsFlatAdditionalInternalPadY = arg; this->Modified(); this->UpdateWidgetsLayout(); } //---------------------------------------------------------------------------- void vtkKWToolbar::UpdateToolbarFrameAspect() { if (!this->IsCreated()) { return; } const char *common_opts = " -side left -anchor nw -fill both -expand n"; if (this->ToolbarAspect == vtkKWToolbar::ToolbarAspectFlat) { this->SetReliefToFlat(); this->SetBorderWidth(0); this->Script("pack %s -ipadx 0 -ipady 0 -padx 0 -pady 0 %s", this->Frame->GetWidgetName(), common_opts); } else if (this->ToolbarAspect == vtkKWToolbar::ToolbarAspectRelief) { this->SetReliefToRaised(); this->SetBorderWidth(1); this->Script("pack %s -ipadx 1 -ipady 1 -padx 0 -pady 0 %s", this->Frame->GetWidgetName(), common_opts); } else { this->Script("pack %s -ipadx 0 -ipady 0 -padx 0 -pady 0 %s", this->Frame->GetWidgetName(), common_opts); } } //---------------------------------------------------------------------------- void vtkKWToolbar::Update() { this->UpdateEnableState(); this->UpdateToolbarFrameAspect(); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetToolbarAspect(int f) { if (f < vtkKWToolbar::ToolbarAspectRelief) { f = vtkKWToolbar::ToolbarAspectRelief; } else if (f > vtkKWToolbar::ToolbarAspectUnChanged) { f = vtkKWToolbar::ToolbarAspectUnChanged; } if (this->ToolbarAspect == f) { return; } this->ToolbarAspect = f; this->Modified(); this->UpdateToolbarFrameAspect(); this->UpdateWidgets(); } void vtkKWToolbar::SetToolbarAspectToFlat() { this->SetToolbarAspect(vtkKWToolbar::ToolbarAspectFlat); } void vtkKWToolbar::SetToolbarAspectToRelief() { this->SetToolbarAspect(vtkKWToolbar::ToolbarAspectRelief); } void vtkKWToolbar::SetToolbarAspectToUnChanged() { this->SetToolbarAspect(vtkKWToolbar::ToolbarAspectUnChanged); } int vtkKWToolbar::GetGlobalToolbarAspect() { return vtkKWToolbarGlobalToolbarAspect; } void vtkKWToolbar::SetGlobalToolbarAspect(int val) { vtkKWToolbarGlobalToolbarAspect = val; }; void vtkKWToolbar::SetGlobalToolbarAspectToFlat() { vtkKWToolbar::SetGlobalToolbarAspect(vtkKWToolbar::ToolbarAspectFlat); } void vtkKWToolbar::SetGlobalToolbarAspectToRelief() { vtkKWToolbar::SetGlobalToolbarAspect(vtkKWToolbar::ToolbarAspectRelief); } void vtkKWToolbar::SetGlobalToolbarAspectToUnChanged() { vtkKWToolbar::SetGlobalToolbarAspect(vtkKWToolbar::ToolbarAspectUnChanged); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetWidgetsAspect(int f) { if (f < vtkKWToolbar::WidgetsAspectRelief) { f = vtkKWToolbar::WidgetsAspectRelief; } else if (f > vtkKWToolbar::WidgetsAspectUnChanged) { f = vtkKWToolbar::WidgetsAspectUnChanged; } if (this->WidgetsAspect == f) { return; } this->WidgetsAspect = f; this->Modified(); this->UpdateWidgets(); } void vtkKWToolbar::SetWidgetsAspectToFlat() { this->SetWidgetsAspect(vtkKWToolbar::WidgetsAspectFlat); } void vtkKWToolbar::SetWidgetsAspectToRelief() { this->SetWidgetsAspect(vtkKWToolbar::WidgetsAspectRelief); } void vtkKWToolbar::SetWidgetsAspectToUnChanged() { this->SetWidgetsAspect(vtkKWToolbar::WidgetsAspectUnChanged); } int vtkKWToolbar::GetGlobalWidgetsAspect() { return vtkKWToolbarGlobalWidgetsAspect; } void vtkKWToolbar::SetGlobalWidgetsAspect(int val) { vtkKWToolbarGlobalWidgetsAspect = val; }; void vtkKWToolbar::SetGlobalWidgetsAspectToFlat() { vtkKWToolbar::SetGlobalWidgetsAspect(vtkKWToolbar::WidgetsAspectFlat); } void vtkKWToolbar::SetGlobalWidgetsAspectToRelief() { vtkKWToolbar::SetGlobalWidgetsAspect(vtkKWToolbar::WidgetsAspectRelief); } void vtkKWToolbar::SetGlobalWidgetsAspectToUnChanged() { vtkKWToolbar::SetGlobalWidgetsAspect(vtkKWToolbar::WidgetsAspectUnChanged); } //---------------------------------------------------------------------------- void vtkKWToolbar::SetResizable(int r) { if (this->Resizable == r) { return; } this->Resizable = r; this->Modified(); this->UpdateWidgets(); } //---------------------------------------------------------------------------- void vtkKWToolbar::UpdateEnableState() { this->Superclass::UpdateEnableState(); vtkKWToolbarInternals::WidgetsContainerIterator it = this->Internals->Widgets.begin(); vtkKWToolbarInternals::WidgetsContainerIterator end = this->Internals->Widgets.end(); for (; it != end; ++it) { this->PropagateEnableState((*it).Widget); } } //---------------------------------------------------------------------------- void vtkKWToolbar::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Frame: " << this->Frame << endl; os << indent << "Resizable: " << (this->Resizable ? "On" : "Off") << endl; os << indent << "ToolbarAspect: " << this->ToolbarAspect << endl; os << indent << "WidgetsAspect: " << this->WidgetsAspect << endl; os << indent << "WidgetsPadX: " << this->WidgetsPadX << endl; os << indent << "WidgetsPadY: " << this->WidgetsPadY << endl; os << indent << "WidgetsFlatAdditionalPadX: " << this->WidgetsFlatAdditionalPadX << endl; os << indent << "WidgetsFlatAdditionalPadY: " << this->WidgetsFlatAdditionalPadY << endl; os << indent << "WidgetsInternalPadX: " << this->WidgetsInternalPadX << endl; os << indent << "WidgetsInternalPadY: " << this->WidgetsInternalPadY << endl; os << indent << "WidgetsFlatAdditionalInternalPadX: " << this->WidgetsFlatAdditionalInternalPadX << endl; os << indent << "WidgetsFlatAdditionalInternalPadY: " << this->WidgetsFlatAdditionalInternalPadY << endl; os << indent << "Name: " << (this->Name ? this->Name : "None") << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWSmallCounterLabel.h0000644000175000017500000000346011076647462021611 0ustar domibeldomibel/*========================================================================= Module: vtkKWSmallCounterLabel.h,v Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWSmallCounterLabel - a (very) small counter label (icon) // .SECTION Description // A widget that represents a very small counter (as an icon), counting // from 1 to 9 (any value over 9 is represented as 9+). #ifndef __vtkKWSmallCounterLabel_h #define __vtkKWSmallCounterLabel_h #include "vtkKWLabel.h" class KWWidgets_EXPORT vtkKWSmallCounterLabel : public vtkKWLabel { public: static vtkKWSmallCounterLabel* New(); vtkTypeRevisionMacro(vtkKWSmallCounterLabel,vtkKWLabel); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the value of the counter. // Set it to 0 to hide the counter. Any value over 9 will be stored as // 10 and represented as a 9+ icon. virtual void SetValue(unsigned int v); vtkGetMacro(Value, unsigned int); // Description: // Place the icon on top of its parent virtual void Place(); protected: vtkKWSmallCounterLabel(); ~vtkKWSmallCounterLabel(); // Description: // Create the widget. virtual void CreateWidget(); // Description: // Update the icon. virtual void UpdateIcon(); unsigned int Value; vtkKWWidget *OriginalParent; private: vtkKWSmallCounterLabel(const vtkKWSmallCounterLabel&); // Not implemented void operator=(const vtkKWSmallCounterLabel&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWPopupFrame.h0000644000175000017500000000426510424463537020316 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWPopupFrame.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWPopupFrame - a popup frame // .SECTION Description // A class that provides a frame that can be collapsed as a popup button. #ifndef __vtkKWPopupFrame_h #define __vtkKWPopupFrame_h #include "vtkKWCompositeWidget.h" class vtkKWFrameWithLabel; class vtkKWPopupButton; class KWWidgets_EXPORT vtkKWPopupFrame : public vtkKWCompositeWidget { public: static vtkKWPopupFrame* New(); vtkTypeRevisionMacro(vtkKWPopupFrame,vtkKWCompositeWidget); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Display the frame as a popup. This has to be called before Create(). vtkSetMacro(PopupMode, int); vtkGetMacro(PopupMode, int); vtkBooleanMacro(PopupMode, int); // Description: // Access to sub-widgets vtkGetObjectMacro(PopupButton, vtkKWPopupButton); vtkGetObjectMacro(Frame, vtkKWFrameWithLabel); // Description: // Update the "enable" state of the object and its internal parts. // Depending on different Ivars (this->Enabled, the application's // Limited Edition Mode, etc.), the "enable" state of the object is updated // and propagated to its internal parts/subwidgets. This will, for example, // enable/disable parts of the widget UI, enable/disable the visibility // of 3D widgets, etc. virtual void UpdateEnableState(); protected: vtkKWPopupFrame(); ~vtkKWPopupFrame(); // Description: // Create the widget. virtual void CreateWidget(); // GUI int PopupMode; vtkKWPopupButton *PopupButton; vtkKWFrameWithLabel *Frame; private: vtkKWPopupFrame(const vtkKWPopupFrame&); // Not implemented void operator=(const vtkKWPopupFrame&); // Not Implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWCoreWidget.cxx0000644000175000017500000003037711153573110020637 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWCoreWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWCoreWidget.h" #include "vtkKWApplication.h" #include "vtkObjectFactory.h" #include "vtkKWTkUtilities.h" #include "vtkKWIcon.h" #include "vtkKWOptions.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWCoreWidget ); vtkCxxRevisionMacro(vtkKWCoreWidget, "$Revision: 1.22 $"); //---------------------------------------------------------------------------- class vtkKWCoreWidgetInternals { public: // Some temporary storage var that do not need to be exposed in the .h double ConfigurationOptionAsColorTemp[3]; vtksys_stl::string ConvertInternalStringToTclStringTemp; vtksys_stl::string ConvertTclStringToInternalStringTemp; // For performance, let's cache the -state option value so that we // can query it faster. This is important as setting a lot of other // options on a widget can only be achieved given a specific state. int CachedStateOption; }; //---------------------------------------------------------------------------- vtkKWCoreWidget::vtkKWCoreWidget() { this->Internals = new vtkKWCoreWidgetInternals; this->Internals->CachedStateOption = vtkKWOptions::StateUnknown; } //---------------------------------------------------------------------------- vtkKWCoreWidget::~vtkKWCoreWidget() { delete this->Internals; this->Internals = NULL; } //---------------------------------------------------------------------------- void vtkKWCoreWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); } //---------------------------------------------------------------------------- int vtkKWCoreWidget::SetConfigurationOption( const char *option, const char *value) { if (!this->IsCreated()) { vtkWarningMacro("Widget is not created yet !"); return 0; } if (!option) { vtkWarningMacro("Missing option !"); return 0; } const char *res = this->Script("%s configure %s {%s}", this->GetWidgetName(), option, value ? value : ""); // 'configure' is not supposed to return anything, so let's assume // any output is an error if (res && *res) { vtksys_stl::string err_msg(res); vtksys_stl::string tcl_name(this->GetTclName()); vtksys_stl::string widget_name(this->GetWidgetName()); vtksys_stl::string type(this->GetType()); vtkErrorMacro( "Error configuring " << tcl_name.c_str() << " (" << type.c_str() << ": " << widget_name.c_str() << ") with option: [" << option << "] and value [" << value << "] => " << err_msg.c_str()); return 0; } return 1; } //---------------------------------------------------------------------------- int vtkKWCoreWidget::HasConfigurationOption(const char *option) { if (!this->IsCreated()) { vtkWarningMacro("Widget is not created yet !"); return 0; } return (this->GetApplication() && !this->GetApplication()->EvaluateBooleanExpression( "catch {%s cget %s}", this->GetWidgetName(), option)); } //---------------------------------------------------------------------------- const char* vtkKWCoreWidget::GetConfigurationOption(const char *option) { if (!this->HasConfigurationOption(option)) { return NULL; } return this->Script("%s cget %s", this->GetWidgetName(), option); } //---------------------------------------------------------------------------- int vtkKWCoreWidget::SetConfigurationOptionAsInt( const char *option, int value) { char buffer[20]; sprintf(buffer, "%d", value); return this->SetConfigurationOption(option, buffer); } //---------------------------------------------------------------------------- int vtkKWCoreWidget::GetConfigurationOptionAsInt(const char *option) { if (!this->HasConfigurationOption(option)) { return 0; } return atoi(this->Script("%s cget %s", this->GetWidgetName(), option)); } //---------------------------------------------------------------------------- int vtkKWCoreWidget::SetConfigurationOptionAsDouble( const char *option, double value) { char buffer[2048]; sprintf(buffer, "%f", value); return this->SetConfigurationOption(option, buffer); } //---------------------------------------------------------------------------- double vtkKWCoreWidget::GetConfigurationOptionAsDouble(const char *option) { if (!this->HasConfigurationOption(option)) { return 0.0; } return atof(this->Script("%s cget %s", this->GetWidgetName(), option)); } //---------------------------------------------------------------------------- void vtkKWCoreWidget::GetConfigurationOptionAsColor( const char *option, double *r, double *g, double *b) { vtkKWTkUtilities::GetOptionColor(this, option, r, g, b); } //---------------------------------------------------------------------------- double* vtkKWCoreWidget::GetConfigurationOptionAsColor(const char *option) { // Now this is still not super-safe if in a multi-thread context this // method is called with different 'option' argument... this->GetConfigurationOptionAsColor( option, this->Internals->ConfigurationOptionAsColorTemp, this->Internals->ConfigurationOptionAsColorTemp + 1, this->Internals->ConfigurationOptionAsColorTemp + 2); return this->Internals->ConfigurationOptionAsColorTemp; } //---------------------------------------------------------------------------- void vtkKWCoreWidget::SetConfigurationOptionAsColor( const char *option, double r, double g, double b) { vtkKWTkUtilities::SetOptionColor(this, option, r, g, b); } //---------------------------------------------------------------------------- void vtkKWCoreWidget::GetDefaultConfigurationOptionAsColor( const char *option, double *r, double *g, double *b) { vtkKWTkUtilities::GetDefaultOptionColor(this, option, r, g, b); } //---------------------------------------------------------------------------- double* vtkKWCoreWidget::GetDefaultConfigurationOptionAsColor( const char *option) { // Now this is still not super-safe if in a multi-thread context this // method is called with different 'option' argument... this->GetDefaultConfigurationOptionAsColor( option, this->Internals->ConfigurationOptionAsColorTemp, this->Internals->ConfigurationOptionAsColorTemp + 1, this->Internals->ConfigurationOptionAsColorTemp + 2); return this->Internals->ConfigurationOptionAsColorTemp; } //---------------------------------------------------------------------------- const char* vtkKWCoreWidget::ConvertInternalStringToTclString( const char *source, int options) { if (!source || !this->IsCreated()) { return NULL; } vtksys_stl::string &dest = this->Internals->ConvertInternalStringToTclStringTemp; const char *res = source; // Handle the encoding int app_encoding = this->GetApplication()->GetCharacterEncoding(); if (app_encoding != VTK_ENCODING_NONE && app_encoding != VTK_ENCODING_UNKNOWN) { // Get the Tcl encoding name const char *tcl_encoding_name = vtkKWOptions::GetCharacterEncodingAsTclOptionValue(app_encoding); // Check if we have that encoding Tcl_Encoding tcl_encoding = Tcl_GetEncoding( this->GetApplication()->GetMainInterp(), tcl_encoding_name); if (tcl_encoding != NULL) { Tcl_FreeEncoding(tcl_encoding); // Convert from that encoding // We need to escape interpretable chars to perform that conversion dest = vtksys::SystemTools::EscapeChars(source, "[]$\"\\"); res = source = this->Script( "encoding convertfrom %s \"%s\"", tcl_encoding_name, dest.c_str()); } } // Escape vtksys_stl::string escape_chars; if (options) { if (options & vtkKWCoreWidget::ConvertStringEscapeCurlyBraces) { escape_chars += "{}"; } if (options & vtkKWCoreWidget::ConvertStringEscapeInterpretable) { escape_chars += "[]$\"\\"; } dest = vtksys::SystemTools::EscapeChars(source, escape_chars.c_str()); res = source = dest.c_str(); } return res; } //---------------------------------------------------------------------------- const char* vtkKWCoreWidget::ConvertTclStringToInternalString( const char *source, int options) { if (!source || !this->IsCreated()) { return NULL; } vtksys_stl::string &dest = this->Internals->ConvertTclStringToInternalStringTemp; const char *res = source; // Handle the encoding int app_encoding = this->GetApplication()->GetCharacterEncoding(); if (app_encoding != VTK_ENCODING_NONE && app_encoding != VTK_ENCODING_UNKNOWN) { // Convert from that encoding // We need to escape interpretable chars to perform that conversion dest = vtksys::SystemTools::EscapeChars(source, "[]$\"\\"); res = source = this->Script( "encoding convertfrom identity \"%s\"", dest.c_str()); } // Escape vtksys_stl::string escape_chars; if (options) { if (options & vtkKWCoreWidget::ConvertStringEscapeCurlyBraces) { escape_chars += "{}"; } if (options & vtkKWCoreWidget::ConvertStringEscapeInterpretable) { escape_chars += "[]$\"\\"; } dest = vtksys::SystemTools::EscapeChars(source, escape_chars.c_str()); res = source = dest.c_str(); } return res; } //---------------------------------------------------------------------------- void vtkKWCoreWidget::SetTextOption(const char *option, const char *value) { if (!option || !this->IsCreated()) { return; } const char *val = this->ConvertInternalStringToTclString( value, vtkKWCoreWidget::ConvertStringEscapeInterpretable); this->Script("%s configure %s \"%s\"", this->GetWidgetName(), option, val ? val : ""); } //---------------------------------------------------------------------------- const char* vtkKWCoreWidget::GetTextOption(const char *option) { if (!option || !this->IsCreated()) { return ""; } return this->ConvertTclStringToInternalString( this->GetConfigurationOption(option)); } //---------------------------------------------------------------------------- void vtkKWCoreWidget::SetState(int state) { if (this->GetState() != state && this->IsAlive()) { this->Internals->CachedStateOption = state; this->SetConfigurationOption( "-state", vtkKWOptions::GetStateAsTkOptionValue(state)); } } void vtkKWCoreWidget::SetStateToDisabled() { this->SetState(vtkKWOptions::StateDisabled); }; void vtkKWCoreWidget::SetStateToNormal() { this->SetState(vtkKWOptions::StateNormal); }; void vtkKWCoreWidget::SetStateToReadOnly() { this->SetState(vtkKWOptions::StateReadOnly); }; //---------------------------------------------------------------------------- int vtkKWCoreWidget::GetState() { if (this->Internals->CachedStateOption == vtkKWOptions::StateUnknown && this->IsAlive()) { this->Internals->CachedStateOption = vtkKWOptions::GetStateFromTkOptionValue( this->GetConfigurationOption("-state")); } return this->Internals->CachedStateOption; } //---------------------------------------------------------------------------- const char* vtkKWCoreWidget::GetType() { const char *res = vtkKWTkUtilities::GetWidgetClass(this); if (!res) { return "None"; } return res; } //---------------------------------------------------------------------------- void vtkKWCoreWidget::Raise() { if (this->IsCreated()) { this->Script("raise %s", this->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWCoreWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWWizardStep.cxx0000644000175000017500000004120311164226600020666 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWizardStep.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWWizardStep.h" #include "vtkKWStateMachineState.h" #include "vtkKWStateMachineInput.h" #include "vtkKWStateMachineTransition.h" #include "vtkKWTkUtilities.h" #include "vtkObjectFactory.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWWizardStep); vtkCxxRevisionMacro(vtkKWWizardStep, "$Revision: 1.6 $"); vtkIdType vtkKWWizardStep::IdCounter = 1; vtkKWWizardStepCleanup vtkKWWizardStep::Cleanup; vtkKWStateMachineInput* vtkKWWizardStep::ValidationInput = NULL; vtkKWStateMachineInput* vtkKWWizardStep::ValidationSucceededInput = NULL; vtkKWStateMachineInput* vtkKWWizardStep::ValidationFailedInput = NULL; //---------------------------------------------------------------------------- vtkKWWizardStepCleanup::~vtkKWWizardStepCleanup() { vtkKWWizardStep::SetValidationInput(NULL); vtkKWWizardStep::SetValidationSucceededInput(NULL); vtkKWWizardStep::SetValidationFailedInput(NULL); } //---------------------------------------------------------------------------- vtkKWWizardStep::vtkKWWizardStep() { this->Id = vtkKWWizardStep::IdCounter++; this->Name = NULL; this->Description = NULL; this->InteractionState = NULL; this->ValidationState = NULL; this->ValidationTransition = NULL; this->ValidationFailedTransition = NULL; this->GoToSelfInput = NULL; this->GoBackToSelfInput = NULL; this->ShowUserInterfaceCommand = NULL; this->HideUserInterfaceCommand = NULL; this->ValidateCommand = NULL; this->CanGoToSelfCommand = NULL; } //---------------------------------------------------------------------------- vtkKWWizardStep::~vtkKWWizardStep() { if (this->InteractionState) { this->InteractionState->Delete(); this->InteractionState = NULL; } if (this->ValidationState) { this->ValidationState->Delete(); this->ValidationState = NULL; } if (this->ValidationTransition) { this->ValidationTransition->Delete(); this->ValidationTransition = NULL; } if (this->ValidationFailedTransition) { this->ValidationFailedTransition->Delete(); this->ValidationFailedTransition = NULL; } if (this->GoToSelfInput) { this->GoToSelfInput->Delete(); this->GoToSelfInput = NULL; } if (this->GoBackToSelfInput) { this->GoBackToSelfInput->Delete(); this->GoBackToSelfInput = NULL; } if (this->ShowUserInterfaceCommand) { delete [] this->ShowUserInterfaceCommand; this->ShowUserInterfaceCommand = NULL; } if (this->HideUserInterfaceCommand) { delete [] this->HideUserInterfaceCommand; this->HideUserInterfaceCommand = NULL; } if (this->ValidateCommand) { delete [] this->ValidateCommand; this->ValidateCommand = NULL; } if (this->CanGoToSelfCommand) { delete [] this->CanGoToSelfCommand; this->CanGoToSelfCommand = NULL; } } //---------------------------------------------------------------------------- vtkKWStateMachineState* vtkKWWizardStep::GetInteractionState() { if (!this->InteractionState) { this->InteractionState = vtkKWStateMachineState::New(); vtksys_ios::ostringstream name; if (this->Name) { name << this->Name; } else { name << this->Id; } name << " (I)"; this->InteractionState->SetName(name.str().c_str()); this->AddCallbackCommandObserver( this->InteractionState, vtkKWStateMachineState::EnterEvent); } return this->InteractionState; } //---------------------------------------------------------------------------- vtkKWStateMachineState* vtkKWWizardStep::GetValidationState() { if (!this->ValidationState) { this->ValidationState = vtkKWStateMachineState::New(); vtksys_ios::ostringstream name; if (this->Name) { name << this->Name; } else { name << this->Id; } name << " (V)"; this->ValidationState->SetName(name.str().c_str()); } return this->ValidationState; } //---------------------------------------------------------------------------- vtkKWStateMachineTransition* vtkKWWizardStep::GetValidationTransition() { if (!this->ValidationTransition) { this->ValidationTransition = vtkKWStateMachineTransition::New(); this->ValidationTransition->SetOriginState( this->GetInteractionState()); this->ValidationTransition->SetInput( vtkKWWizardStep::GetValidationInput()); this->ValidationTransition->SetDestinationState( this->GetValidationState()); this->AddCallbackCommandObserver( this->ValidationTransition, vtkKWStateMachineTransition::EndEvent); } return this->ValidationTransition; } //---------------------------------------------------------------------------- vtkKWStateMachineTransition* vtkKWWizardStep::GetValidationFailedTransition() { if (!this->ValidationFailedTransition) { this->ValidationFailedTransition = vtkKWStateMachineTransition::New(); this->ValidationFailedTransition->SetOriginState( this->GetValidationState()); this->ValidationFailedTransition->SetInput( vtkKWWizardStep::GetValidationFailedInput()); this->ValidationFailedTransition->SetDestinationState( this->GetInteractionState()); } return this->ValidationFailedTransition; } //---------------------------------------------------------------------------- vtkKWStateMachineInput* vtkKWWizardStep::GetGoToSelfInput() { if (!this->GoToSelfInput) { this->GoToSelfInput = vtkKWStateMachineInput::New(); vtksys_ios::ostringstream name; name << "go to: "; if (this->Name) { name << this->Name; } else { name << this->Id; } this->GoToSelfInput->SetName(name.str().c_str()); } return this->GoToSelfInput; } //---------------------------------------------------------------------------- vtkKWStateMachineInput* vtkKWWizardStep::GetGoBackToSelfInput() { if (!this->GoBackToSelfInput) { this->GoBackToSelfInput = vtkKWStateMachineInput::New(); vtksys_ios::ostringstream name; name << "back to: "; if (this->Name) { name << this->Name; } else { name << this->Id; } this->GoBackToSelfInput->SetName(name.str().c_str()); } return this->GoBackToSelfInput; } //---------------------------------------------------------------------------- vtkKWStateMachineInput* vtkKWWizardStep::GetValidationInput() { if (!vtkKWWizardStep::ValidationInput) { vtkKWWizardStep::ValidationInput = vtkKWStateMachineInput::New(); vtkKWWizardStep::ValidationInput->SetName("validate"); } return vtkKWWizardStep::ValidationInput; } //---------------------------------------------------------------------------- void vtkKWWizardStep::SetValidationInput(vtkKWStateMachineInput *input) { if (vtkKWWizardStep::ValidationInput == input) { return; } if (vtkKWWizardStep::ValidationInput) { vtkKWWizardStep::ValidationInput->Delete();; } vtkKWWizardStep::ValidationInput = input; if (input) { input->Register(NULL); } } //---------------------------------------------------------------------------- vtkKWStateMachineInput* vtkKWWizardStep::GetValidationSucceededInput() { if (!vtkKWWizardStep::ValidationSucceededInput) { vtkKWWizardStep::ValidationSucceededInput = vtkKWStateMachineInput::New(); vtkKWWizardStep::ValidationSucceededInput->SetName("valid"); } return vtkKWWizardStep::ValidationSucceededInput; } //---------------------------------------------------------------------------- void vtkKWWizardStep::SetValidationSucceededInput(vtkKWStateMachineInput *input) { if (vtkKWWizardStep::ValidationSucceededInput == input) { return; } if (vtkKWWizardStep::ValidationSucceededInput) { vtkKWWizardStep::ValidationSucceededInput->Delete();; } vtkKWWizardStep::ValidationSucceededInput = input; if (input) { input->Register(NULL); } } //---------------------------------------------------------------------------- vtkKWStateMachineInput* vtkKWWizardStep::GetValidationFailedInput() { if (!vtkKWWizardStep::ValidationFailedInput) { vtkKWWizardStep::ValidationFailedInput = vtkKWStateMachineInput::New(); vtkKWWizardStep::ValidationFailedInput->SetName("invalid"); } return vtkKWWizardStep::ValidationFailedInput; } //---------------------------------------------------------------------------- void vtkKWWizardStep::SetValidationFailedInput(vtkKWStateMachineInput *input) { if (vtkKWWizardStep::ValidationFailedInput == input) { return; } if (vtkKWWizardStep::ValidationFailedInput) { vtkKWWizardStep::ValidationFailedInput->Delete();; } vtkKWWizardStep::ValidationFailedInput = input; if (input) { input->Register(NULL); } } //---------------------------------------------------------------------------- void vtkKWWizardStep::ShowUserInterface() { this->InvokeEvent(vtkKWWizardStep::ShowUserInterfaceEvent); this->InvokeShowUserInterfaceCommand(); } //---------------------------------------------------------------------------- void vtkKWWizardStep::SetShowUserInterfaceCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->ShowUserInterfaceCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWWizardStep::InvokeShowUserInterfaceCommand() { if (this->HasShowUserInterfaceCommand()) { this->InvokeObjectMethodCommand(this->ShowUserInterfaceCommand); } } //---------------------------------------------------------------------------- int vtkKWWizardStep::HasShowUserInterfaceCommand() { return this->ShowUserInterfaceCommand && *this->ShowUserInterfaceCommand; } //---------------------------------------------------------------------------- void vtkKWWizardStep::HideUserInterface() { this->InvokeEvent(vtkKWWizardStep::HideUserInterfaceEvent); this->InvokeHideUserInterfaceCommand(); } //---------------------------------------------------------------------------- void vtkKWWizardStep::SetHideUserInterfaceCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->HideUserInterfaceCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWWizardStep::InvokeHideUserInterfaceCommand() { if (this->HasHideUserInterfaceCommand()) { this->InvokeObjectMethodCommand(this->HideUserInterfaceCommand); } } //---------------------------------------------------------------------------- int vtkKWWizardStep::HasHideUserInterfaceCommand() { return this->HideUserInterfaceCommand && *this->HideUserInterfaceCommand; } //---------------------------------------------------------------------------- void vtkKWWizardStep::Validate() { this->InvokeEvent(vtkKWWizardStep::ValidateEvent); this->InvokeValidateCommand(); } //---------------------------------------------------------------------------- void vtkKWWizardStep::SetValidateCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->ValidateCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWWizardStep::InvokeValidateCommand() { if (this->HasValidateCommand()) { this->InvokeObjectMethodCommand(this->ValidateCommand); } } //---------------------------------------------------------------------------- int vtkKWWizardStep::HasValidateCommand() { return this->ValidateCommand && *this->ValidateCommand; } //---------------------------------------------------------------------------- int vtkKWWizardStep::CanGoToSelf() { if (this->HasCanGoToSelfCommand()) { return this->InvokeCanGoToSelfCommand(); } return 0; } //---------------------------------------------------------------------------- void vtkKWWizardStep::SetCanGoToSelfCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->CanGoToSelfCommand, object, method); } //---------------------------------------------------------------------------- int vtkKWWizardStep::InvokeCanGoToSelfCommand() { if (this->HasCanGoToSelfCommand()) { return atoi(vtkKWTkUtilities::EvaluateSimpleString( this->GetApplication(), this->CanGoToSelfCommand)); } return 0; } //---------------------------------------------------------------------------- int vtkKWWizardStep::HasCanGoToSelfCommand() { return this->CanGoToSelfCommand && *this->CanGoToSelfCommand; } //---------------------------------------------------------------------------- void vtkKWWizardStep::RemoveCallbackCommandObservers() { this->Superclass::RemoveCallbackCommandObservers(); if (this->InteractionState) { this->RemoveCallbackCommandObserver( this->InteractionState, vtkKWStateMachineState::EnterEvent); } if (this->ValidationTransition) { this->RemoveCallbackCommandObserver( this->ValidationTransition, vtkKWStateMachineTransition::EndEvent); } } //---------------------------------------------------------------------------- void vtkKWWizardStep::ProcessCallbackCommandEvents(vtkObject *caller, unsigned long event, void *calldata) { if (caller == this->InteractionState) { switch (event) { case vtkKWStateMachineState::EnterEvent: this->ShowUserInterface(); break; } } else if (caller == this->ValidationTransition) { switch (event) { case vtkKWStateMachineTransition::EndEvent: this->Validate(); break; } } this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata); } //---------------------------------------------------------------------------- void vtkKWWizardStep::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Name: " << (this->Name ? this->Name : "None") << endl; os << indent << "Description: " << (this->Description ? this->Description : "None") << endl; os << indent << "InteractionState: "; if (this->InteractionState) { os << endl; this->InteractionState->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "ValidationState: "; if (this->ValidationState) { os << endl; this->ValidationState->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "ValidationTransition: "; if (this->ValidationTransition) { os << endl; this->ValidationTransition->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "ValidationFailedTransition: "; if (this->ValidationFailedTransition) { os << endl; this->ValidationFailedTransition->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "GoToSelfInput: "; if (this->GoToSelfInput) { os << endl; this->GoToSelfInput->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "GoBackToSelfInput: "; if (this->GoBackToSelfInput) { os << endl; this->GoBackToSelfInput->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "vtkKWWizardStep::ValidationInput: "; if (vtkKWWizardStep::ValidationInput) { os << endl; vtkKWWizardStep::ValidationInput->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "vtkKWWizardStep::ValidationSucceededInput: "; if (vtkKWWizardStep::ValidationSucceededInput) { os << endl; vtkKWWizardStep::ValidationSucceededInput->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "vtkKWWizardStep::ValidationFailedInput: "; if (vtkKWWizardStep::ValidationFailedInput) { os << endl; vtkKWWizardStep::ValidationFailedInput->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWPiecewiseFunctionEditor.cxx0000644000175000017500000011355211066021757023402 0ustar domibeldomibel/*========================================================================= Module: vtkKWPiecewiseFunctionEditor.cxx,v Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWPiecewiseFunctionEditor.h" #include "vtkKWCheckButton.h" #include "vtkKWEntry.h" #include "vtkKWEntryWithLabel.h" #include "vtkKWEvent.h" #include "vtkKWFrame.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWRange.h" #include "vtkKWScaleWithEntry.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPiecewiseFunction.h" #include "vtkColorTransferFunction.h" #include #include vtkStandardNewMacro(vtkKWPiecewiseFunctionEditor); vtkCxxRevisionMacro(vtkKWPiecewiseFunctionEditor, "$Revision: 1.59 $"); #define EPSILON 0.0001 #define EPSILON_MIN_WINDOW (EPSILON * 2.5) //---------------------------------------------------------------------------- vtkKWPiecewiseFunctionEditor::vtkKWPiecewiseFunctionEditor() { this->PiecewiseFunction = NULL; this->PointColorTransferFunction = NULL; this->WindowLevelMode = 0; this->WindowLevelModeLockEndPointValue = 0; this->WindowLevelModeButtonVisibility = 0; this->ValueEntryVisibility = 1; this->Window = 1.0; this->Level = 1.0; this->WindowLevelModeChangedCommand = NULL; this->ValueEntry = vtkKWEntryWithLabel::New(); this->WindowLevelModeCheckButton = vtkKWCheckButton::New(); } //---------------------------------------------------------------------------- vtkKWPiecewiseFunctionEditor::~vtkKWPiecewiseFunctionEditor() { if (this->WindowLevelModeChangedCommand) { delete [] this->WindowLevelModeChangedCommand; this->WindowLevelModeChangedCommand = NULL; } if (this->ValueEntry) { this->ValueEntry->Delete(); this->ValueEntry = NULL; } if (this->WindowLevelModeCheckButton) { this->WindowLevelModeCheckButton->Delete(); this->WindowLevelModeCheckButton = NULL; } this->SetPiecewiseFunction(NULL); this->SetPointColorTransferFunction(NULL); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::SetPiecewiseFunction( vtkPiecewiseFunction *arg) { if (this->PiecewiseFunction == arg) { return; } if (this->PiecewiseFunction) { this->PiecewiseFunction->UnRegister(this); } this->PiecewiseFunction = arg; if (this->PiecewiseFunction) { this->PiecewiseFunction->Register(this); // Reset the whole parameter range to the function range. // This is done to avoid extreme case where the current parameter range // would be several order of magnitudes smaller than the function range: // the next Update() would redraw the function at a very high zoom level // which could produce a very unreasonable number of segments if the // function was to be sampled at regular pixels interval. this->SetWholeParameterRangeToFunctionRange(); } this->Modified(); this->LastRedrawFunctionTime = 0; this->Update(); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::SetPointColorTransferFunction( vtkColorTransferFunction *arg) { if (this->PointColorTransferFunction == arg) { return; } if (this->PointColorTransferFunction) { this->PointColorTransferFunction->UnRegister(this); } this->PointColorTransferFunction = arg; if (this->PointColorTransferFunction) { this->PointColorTransferFunction->Register(this); } this->Modified(); this->RedrawFunction(); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::FunctionPointCanBeAdded() { return (this->Superclass::FunctionPointCanBeAdded() && !this->WindowLevelMode); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::FunctionPointCanBeRemoved(int id) { return (this->Superclass::FunctionPointCanBeRemoved(id) && !this->WindowLevelMode); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::FunctionPointParameterIsLocked(int id) { return (this->Superclass::FunctionPointParameterIsLocked(id) || (this->HasFunction() && this->WindowLevelMode && (id == 0 || (this->GetFunctionSize() && id == this->GetFunctionSize() - 1)))); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::FunctionPointValueIsLocked(int id) { return (this->Superclass::FunctionPointValueIsLocked(id) || (this->HasFunction() && this->WindowLevelMode && this->WindowLevelModeLockEndPointValue && ((this->GetFunctionSize() > 0 && (id == 0 || id == this->GetFunctionSize() - 1)) || (this->GetFunctionSize() > 1 && (id == 1 || id == this->GetFunctionSize() - 2)) ))); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::FunctionPointMidPointIsLocked(int id) { return (this->Superclass::FunctionPointMidPointIsLocked(id) || this->WindowLevelMode); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::FunctionPointSharpnessIsLocked( int id) { return (this->Superclass::FunctionPointSharpnessIsLocked(id) || this->WindowLevelMode); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::HasFunction() { return this->PiecewiseFunction ? 1 : 0; } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::GetFunctionSize() { return this->PiecewiseFunction ? this->PiecewiseFunction->GetSize() : 0; } //---------------------------------------------------------------------------- unsigned long vtkKWPiecewiseFunctionEditor::GetFunctionMTime() { return this->PiecewiseFunction ? this->PiecewiseFunction->GetMTime() : 0; } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::GetFunctionPointParameter( int id, double *parameter) { if (!this->HasFunction() || id < 0 || id >= this->GetFunctionSize() || !parameter) { return 0; } #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); *parameter = node_value[0]; #else *parameter = this->PiecewiseFunction->GetDataPointer()[ id * (1 + this->GetFunctionPointDimensionality())]; #endif return 1; } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::GetFunctionPointDimensionality() { return 1; } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::GetFunctionPointValues( int id, double *values) { if (!this->HasFunction() || id < 0 || id >= this->GetFunctionSize() || !values) { return 0; } #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); values[0] = node_value[1]; #else values[0] = this->PiecewiseFunction->GetDataPointer()[ id * (1 + this->GetFunctionPointDimensionality()) + 1]; #endif return 1; } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::SetFunctionPointValues( int id, const double *values) { double parameter; if (!values || !this->GetFunctionPointParameter(id, ¶meter)) { return 0; } // Clamp double value = 0.0; vtkMath::ClampValue(values[0], this->GetWholeValueRange(), &value); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); if (node_value[1] != value) { this->PiecewiseFunction->AddPoint( parameter, value, node_value[2], node_value[3]); } #else this->PiecewiseFunction->AddPoint(parameter, value); #endif return 1; } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::InterpolateFunctionPointValues( double parameter, double *values) { if (!this->HasFunction() || !values) { return 0; } values[0] = this->PiecewiseFunction->GetValue(parameter); return 1; } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::AddFunctionPoint( double parameter, const double *values, int *id) { if (!this->HasFunction() || !values || !id) { return 0; } // Clamp vtkMath::ClampValue(¶meter, this->GetWholeParameterRange()); double value = 0.0; vtkMath::ClampValue(values[0], this->GetWholeValueRange(), &value); // Add the point int old_size = this->GetFunctionSize(); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) if (this->GetFunctionPointId(parameter, id)) { double node_value[4]; this->PiecewiseFunction->GetNodeValue(*id, node_value); if (node_value[1] != value) { *id = this->PiecewiseFunction->AddPoint( parameter, value, node_value[2], node_value[3]); } } else #endif { *id = this->PiecewiseFunction->AddPoint(parameter, value); } return (old_size != this->GetFunctionSize()); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::SetFunctionPoint( int id, double parameter, const double *values) { if (!this->HasFunction() || !values) { return 0; } double old_parameter; if (!this->GetFunctionPointParameter(id, &old_parameter)) { return 0; } #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); #endif // Clamp vtkMath::ClampValue(¶meter, this->GetWholeParameterRange()); double value = 0.0; vtkMath::ClampValue(values[0], this->GetWholeValueRange(), &value); if (parameter != old_parameter) { this->PiecewiseFunction->RemovePoint(old_parameter); } int new_id; #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) if (parameter != old_parameter || node_value[1] != value) { new_id = this->PiecewiseFunction->AddPoint( parameter, value, node_value[2], node_value[3]); } else { new_id = id; } #else new_id = this->PiecewiseFunction->AddPoint(parameter, value); #endif if (new_id != id) { vtkWarningMacro(<< "Setting a function point (id: " << id << ") parameter/values resulted in a different point (id:" << new_id << "). Inconsistent."); return 0; } return 1; } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::RemoveFunctionPoint(int id) { if (!this->HasFunction() || id < 0 || id >= this->GetFunctionSize()) { return 0; } // Remove the point #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); double parameter = node_value[0]; #else double parameter = this->PiecewiseFunction->GetDataPointer()[ id * (1 + this->GetFunctionPointDimensionality())]; #endif int old_size = this->GetFunctionSize(); this->PiecewiseFunction->RemovePoint(parameter); return (old_size != this->GetFunctionSize()); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::MoveFunctionPoint( int id, double parameter, const double *values) { int res = this->Superclass::MoveFunctionPoint(id, parameter, values); if (!res) { return res; } // In window-level mode, the first and second point are value-constrained // (so are the last and last - 1 points) int fsize = this->GetFunctionSize(); if (this->WindowLevelMode && (id <= 1 || (fsize >= 2 && id >= fsize - 2))) { // Do not use 'values', as it might have been clamped or adjusted double current_values[ vtkKWParameterValueFunctionEditor::MaxFunctionPointDimensionality]; if (!this->GetFunctionPointValues(id, current_values)) { return 0; } int constrained_id; if (id <= 1) { constrained_id = (id == 0) ? 1 : 0; } else { constrained_id = (id == fsize - 2) ? fsize - 1 : fsize - 2; } unsigned long mtime = this->GetFunctionMTime(); this->SetFunctionPointValues(constrained_id, current_values); if (this->GetFunctionMTime() > mtime) { this->RedrawFunctionDependentElements(); } } return 1; } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::GetFunctionPointColorInCanvas( int id, double rgb[3]) { double parameter; if (this->PointColorTransferFunction && this->GetFunctionPointParameter(id, ¶meter)) { this->PointColorTransferFunction->GetColor(parameter, rgb); return 1; } return this->Superclass::GetFunctionPointColorInCanvas(id, rgb); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::GetFunctionPointMidPoint( int id, double *pos) { if (id < 0 || id >= this->GetFunctionSize() || !pos) { return 0; } #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); *pos = node_value[2]; return 1; #else return 0; #endif } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::SetFunctionPointMidPoint( int id, double pos) { if (id < 0 || id >= this->GetFunctionSize()) { return 0; } if (pos < 0.0) { pos = 0.0; } else if (pos > 1.0) { pos = 1.0; } #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); if (node_value[2] != pos) { this->PiecewiseFunction->AddPoint( node_value[0], node_value[1], pos, node_value[3]); } return 1; #else return 0; #endif } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::GetFunctionPointSharpness( int id, double *sharpness) { if (id < 0 || id >= this->GetFunctionSize() || !sharpness) { return 0; } #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); *sharpness = node_value[3]; return 1; #else return 0; #endif } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::SetFunctionPointSharpness( int id, double sharpness) { if (id < 0 || id >= this->GetFunctionSize()) { return 0; } if (sharpness < 0.0) { sharpness = 0.0; } else if (sharpness > 1.0) { sharpness = 1.0; } #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); if (node_value[3] != sharpness) { this->PiecewiseFunction->AddPoint( node_value[0], node_value[1], node_value[2], sharpness); } return 1; #else return 0; #endif } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::FunctionLineIsSampledBetweenPoints( int id1, int vtkNotUsed(id2)) { if (!this->HasFunction() || id1 < 0 || id1 >= this->GetFunctionSize()) { return 0; } // If sharpness == 0.0 and midpoint = 0.5, then it's the good // old piecewise linear and we do not need to sample, the default // superclass implementation (staight line between id1 and id2) is fine double midpoint, sharpness; if (this->GetFunctionPointMidPoint(id1, &midpoint) && this->GetFunctionPointSharpness(id1, &sharpness)) { return (sharpness == 0.0 && midpoint == 0.5) ? 0 : 1; } return 0; } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::GetLineCoordinates( int id1, int id2, vtksys_ios::ostream *tk_cmd) { // We want to intercept specific case like // sharpness = 1.0: step (3 segments), could not be done using sampling // sharpness = 0.0 and midpoint != 0.5: two segments, for efficiency // (also mid_point should be != 0.0 or 1.0 otherwise the midpoint // parameter is the same as one of the end-point, and its value // (vertical position) is wrong). // We assume all parameters are OK, they were checked by RedrawLine double midpoint, sharpness, p; this->GetFunctionPointMidPoint(id1, &midpoint); this->GetFunctionPointSharpness(id1, &sharpness); int sharp_1 = (sharpness == 1.0) ? 1 : 0; int sharp_0 = (sharpness == 0.0 && midpoint != 0.5 && midpoint != 0.0 && midpoint != 1.0) ? 1 : 0; if (!sharp_1 && !sharp_0) { this->Superclass::GetLineCoordinates(id1, id2, tk_cmd); return; } // Get end-point coordinates int x1, y1, x2, y2, xp, yp; this->GetFunctionPointCanvasCoordinates(id1, &x1, &y1); this->GetFunctionPointCanvasCoordinates(id2, &x2, &y2); // Get midpoint coordinates this->GetMidPointCanvasCoordinates(id1, &xp, &yp, &p); *tk_cmd << " " << x1 << " " << y1; if (sharp_1) { *tk_cmd << " " << xp << " " << y1 << " " << xp << " " << y2; } else { *tk_cmd << " " << xp << " " << yp; } *tk_cmd << " " << x2 << " " << y2; } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::UpdatePointEntries(int id) { this->Superclass::UpdatePointEntries(id); if (!this->ValueEntry || !this->HasFunction()) { return; } // No point ? Empty the entry and disable if (id < 0 || id >= this->GetFunctionSize()) { this->ValueEntry->GetWidget()->SetValue(""); this->ValueEntry->SetEnabled(0); return; } // Disable entry if value is locked this->ValueEntry->SetEnabled( this->FunctionPointValueIsLocked(id) ? 0 : this->GetEnabled()); // Get the value #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; this->PiecewiseFunction->GetNodeValue(id, node_value); #else double *node_value = this->PiecewiseFunction->GetDataPointer() + id * 2; #endif this->ValueEntry->GetWidget()->SetValueAsFormattedDouble(node_value[1], 3); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro("PiecewiseFunctionEditor already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // Create the value entry if (this->ValueEntryVisibility && this->PointEntriesVisibility) { this->CreateValueEntry(); } // Window/Level mode if (this->WindowLevelModeButtonVisibility) { this->CreateWindowLevelModeCheckButton(); } // Pack the widget this->Pack(); // Update this->Update(); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::CreateWindowLevelModeCheckButton() { if (this->WindowLevelModeCheckButton && !this->WindowLevelModeCheckButton->IsCreated()) { this->CreateTopLeftFrame(); this->WindowLevelModeCheckButton->SetParent(this->TopLeftFrame); this->WindowLevelModeCheckButton->Create(); this->WindowLevelModeCheckButton->SetPadX(0); this->WindowLevelModeCheckButton->SetPadY(0); this->WindowLevelModeCheckButton->SetHighlightThickness(0); this->WindowLevelModeCheckButton->IndicatorVisibilityOff(); this->WindowLevelModeCheckButton->SetBalloonHelpString( k_("Place the editor in window/level mode.")); this->WindowLevelModeCheckButton->SetCommand( this, "WindowLevelModeCallback"); this->WindowLevelModeCheckButton->SetImageToPredefinedIcon( vtkKWIcon::IconContrast); } } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::CreateValueEntry() { if (this->ValueEntry && !this->ValueEntry->IsCreated()) { this->CreatePointEntriesFrame(); this->ValueEntry->SetParent(this->PointEntriesFrame); this->ValueEntry->Create(); this->ValueEntry->GetWidget()->SetWidth(6); this->ValueEntry->GetWidget()->SetRestrictValueToDouble(); this->ValueEntry->GetLabel()->SetText( ks_("Transfer Function Editor|Value|V:")); this->UpdatePointEntries(this->GetSelectedPoint()); this->ValueEntry->GetWidget()->SetCommand( this, "ValueEntryCallback"); } } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::IsTopLeftFrameUsed() { return (this->Superclass::IsTopLeftFrameUsed() || this->WindowLevelModeButtonVisibility); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::IsPointEntriesFrameUsed() { return (this->Superclass::IsPointEntriesFrameUsed()); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::Pack() { if (!this->IsCreated()) { return; } // Pack the whole widget this->Superclass::Pack(); vtksys_ios::ostringstream tk_cmd; // Window/Level mode (in top left frame) if (this->WindowLevelModeButtonVisibility && this->WindowLevelModeCheckButton && this->WindowLevelModeCheckButton->IsCreated()) { tk_cmd << "pack " << this->WindowLevelModeCheckButton->GetWidgetName() << " -side left -fill both -padx 0" << endl; } this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::PackPointEntries() { if (!this->IsCreated()) { return; } // Pack the other entries this->Superclass::PackPointEntries(); vtksys_ios::ostringstream tk_cmd; // Value entry (in top right frame) if (this->HasSelection() && this->ValueEntryVisibility && this->PointEntriesVisibility && this->ValueEntry && this->ValueEntry->IsCreated()) { tk_cmd << "pack " << this->ValueEntry->GetWidgetName() << " -side left" << endl; } this->Script(tk_cmd.str().c_str()); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::Update() { this->Superclass::Update(); // Window/Level mode if (this->WindowLevelModeCheckButton) { this->WindowLevelModeCheckButton->SetSelectedState(this->WindowLevelMode); } } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->ValueEntry); this->PropagateEnableState(this->WindowLevelModeCheckButton); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::InvokeFunctionChangedCommand() { if (this->WindowLevelMode) { this->UpdateWindowLevelFromPoints(); double args[2]; args[0] = this->GetWindow(); args[1] = this->GetLevel(); this->InvokeEvent(vtkKWEvent::WindowLevelChangedEvent, args); } this->Superclass::InvokeFunctionChangedCommand(); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::InvokeFunctionChangingCommand() { if (this->WindowLevelMode) { this->UpdateWindowLevelFromPoints(); double args[2]; args[0] = this->GetWindow(); args[1] = this->GetLevel(); this->InvokeEvent(vtkKWEvent::WindowLevelChangingEvent, args); } this->Superclass::InvokeFunctionChangingCommand(); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::SetWindowLevelMode(int arg) { if (this->WindowLevelMode == arg) { return; } this->WindowLevelMode = arg; this->Modified(); if (this->WindowLevelMode) { // Use the whole value range double parameter; double *v_w_range = this->GetWholeValueRange(); #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; #endif if (this->GetFunctionSize() > 0 && this->GetFunctionPointParameter(0, ¶meter)) { #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) this->PiecewiseFunction->GetNodeValue(0, node_value); if (node_value[1] != v_w_range[0]) { this->PiecewiseFunction->AddPoint( parameter, v_w_range[0], node_value[2], node_value[3]); } #else this->PiecewiseFunction->AddPoint(parameter, v_w_range[0]); #endif } if (this->GetFunctionSize() > 1 && this->GetFunctionPointParameter(this->GetFunctionSize()-1, ¶meter)) { #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) this->PiecewiseFunction->GetNodeValue( this->GetFunctionSize() - 1, node_value); if (node_value[1] != v_w_range[1]) { this->PiecewiseFunction->AddPoint( parameter, v_w_range[1], node_value[2], node_value[3]); } #else this->PiecewiseFunction->AddPoint(parameter, v_w_range[1]); #endif } } this->InvokeWindowLevelModeChangedCommand(this->WindowLevelMode); this->UpdatePointsFromWindowLevel(); this->Update(); this->RedrawFunction(); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::SetValueEntryVisibility(int arg) { if (this->ValueEntryVisibility == arg) { return; } this->ValueEntryVisibility = arg; // Make sure that if the range has to be shown, we create it on the fly if // needed if (this->ValueEntryVisibility && this->PointEntriesVisibility && this->IsCreated()) { this->CreateValueEntry(); } this->UpdatePointEntries(this->GetSelectedPoint()); this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- int vtkKWPiecewiseFunctionEditor::GetMidPointVisibility() { return this->Superclass::GetMidPointVisibility() && !this->WindowLevelMode; } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::SetWindowLevelModeButtonVisibility(int arg) { if (this->WindowLevelModeButtonVisibility == arg) { return; } this->WindowLevelModeButtonVisibility = arg; // Make sure that if the button has to be shown, we create it on the fly if // needed if (this->WindowLevelModeButtonVisibility && this->IsCreated()) { this->CreateWindowLevelModeCheckButton(); } this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::SetWindowLevel(double window, double level) { if (this->Window == window && this->Level == level) { return; } this->Window = window; this->Level = level; if (this->WindowLevelMode) { this->UpdatePointsFromWindowLevel(); } } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::SetInteractiveWindowLevel( double window, double level) { if (this->Window == window && this->Level == level) { return; } this->Window = window; this->Level = level; if (this->WindowLevelMode) { this->UpdatePointsFromWindowLevel(1); } } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::UpdateWindowLevelFromPoints() { if (this->WindowLevelMode && this->GetFunctionSize() >= 4) { double p0, p1, p2, p3; if (this->GetFunctionPointParameter(0, &p0) && this->GetFunctionPointParameter(1, &p1) && this->GetFunctionPointParameter(2, &p2) && this->GetFunctionPointParameter(3, &p3)) { // we had to cheat here sadly because we can't have 2 points the same // see UpdatePointsFromWindowLevel. Fix it for this special case. if (p1 <= p0 + EPSILON) { p1 = p0; } if (p2 >= p3 - EPSILON) { p2 = p3; } double v1, v2; v1 = this->PiecewiseFunction->GetValue(p1); v2 = this->PiecewiseFunction->GetValue(p2); this->Window = (v1 <= v2 ? (p2 - p1) : p1 - p2); if (fabs(this->Window) <= EPSILON_MIN_WINDOW * 1.1) { this->Window = 0; } this->Level = (p1 + p2) * 0.5; } } } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::UpdatePointsFromWindowLevel(int interactive) { if (!this->HasFunction()) { return; } unsigned long mtime = this->GetFunctionMTime(); double *p_w_range = this->GetWholeParameterRange(); double *v_w_range = this->GetWholeValueRange(); double parameter; int id; #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) double node_value[4]; #endif // We are in not WindowLevel mode, make sure our points are within the // range (while in W/L mode, those points can be out of the parameter range) if (!this->WindowLevelMode) { int done; do { done = 1; for (id = 0; id < this->GetFunctionSize(); id++) { if (this->GetFunctionPointParameter(id, ¶meter) && (parameter < p_w_range[0] || parameter > p_w_range[1])) { #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) this->PiecewiseFunction->GetNodeValue(id, node_value); #endif double value = this->PiecewiseFunction->GetValue(parameter); this->PiecewiseFunction->RemovePoint(parameter); this->PiecewiseFunction->AddPoint( (parameter < p_w_range[0] ? p_w_range[0] : p_w_range[1]), value #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) , node_value[2], node_value[3] #endif ); done = 0; break; } } } while (!done); } // We are in WindowLevel mode, make sure we have 4 points representing // the ramp else { // Get the current value bounds (default to the whole range if no points) double start_v, end_v; start_v = v_w_range[0]; end_v = v_w_range[1]; // Make sure that if Window < 0 the ramp is going down (if > 0, going up) if ((this->Window < 0 && start_v < end_v) || (this->Window > 0 && start_v > end_v)) { double temp = start_v; start_v = end_v; end_v = temp; } // Compute the 4 points parameters double points[4]; double window = this->Window > 0 ? this->Window : -this->Window; // We need to make sure window < EPSILON_MIN_WINDOW because each point // is around the level at window * 0.5, then to avoid point 0,1 and // point 2,3 to coincide we distance them by EPSILON, so we need // at least the window > EPSILON * 2.0 to make sure things "work". if (window < EPSILON_MIN_WINDOW) { window = EPSILON_MIN_WINDOW; } points[1] = (this->Level - window * 0.5); points[0] = (points[1] > p_w_range[0]) ? p_w_range[0] : points[1]; if (points[1] == points[0]) { // we have to cheat here sadly because we can't have 2 points the same points[1] += EPSILON; } points[2] = (this->Level + window * 0.5); points[3] = (points[2] < p_w_range[1]) ? p_w_range[1] : points[2]; if (points[2] == points[3]) { // we have to cheat here sadly because we can't have 2 points the same points[2] -= EPSILON; } // Remove all extra-points while (this->GetFunctionSize() > 4) { if (this->GetFunctionPointParameter( this->GetFunctionSize() - 1, ¶meter)) { this->PiecewiseFunction->RemovePoint(parameter); } } // Check if modification is needed (if any of those points is different, // just remove everything) for (id = 0; id < 4; id++) { double value = id < 2 ? start_v : end_v; if (!this->GetFunctionPointParameter(id, ¶meter) || parameter != points[id] || this->PiecewiseFunction->GetValue(parameter) != value) { this->PiecewiseFunction->RemoveAllPoints(); break; } } // Set the points #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) int size = this->GetFunctionSize(); #endif for (id = 0; id < 4; id++) { double value = id < 2 ? start_v : end_v; #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) if (id < size) { this->PiecewiseFunction->GetNodeValue(id, node_value); if (node_value[1] != value) { this->PiecewiseFunction->AddPoint( points[id], value, node_value[2], node_value[3]); } } else #endif { this->PiecewiseFunction->AddPoint(points[id], value); } this->SetFunctionPointMidPoint(id, 0.5); this->SetFunctionPointSharpness(id, 0.0); } } // Was the function modified ? if (this->GetFunctionMTime() > mtime) { this->RedrawFunctionDependentElements(); if (interactive) { this->InvokeFunctionChangingCommand(); } else { this->InvokeFunctionChangedCommand(); } } } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::ValueEntryCallback(const char*) { if (!this->ValueEntry || !this->HasSelection()) { return; } // Get the parameter double parameter; if (!this->GetFunctionPointParameter(this->GetSelectedPoint(), ¶meter)) { return; } // Get the value from the entry double value = this->ValueEntry->GetWidget()->GetValueAsDouble(); // Move the point, check if something has really been moved unsigned long mtime = this->GetFunctionMTime(); this->MoveFunctionPoint(this->GetSelectedPoint(), parameter, &value); if (this->GetFunctionMTime() > mtime) { this->InvokePointChangedCommand(this->GetSelectedPoint()); this->InvokeFunctionChangedCommand(); } } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::SetWindowLevelModeChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->WindowLevelModeChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::InvokeWindowLevelModeChangedCommand(int mode) { if (this->WindowLevelModeChangedCommand && *this->WindowLevelModeChangedCommand && this->GetApplication()) { this->Script("%s %d", this->WindowLevelModeChangedCommand, mode); } } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::WindowLevelModeCallback(int state) { this->SetWindowLevelMode(state); } //---------------------------------------------------------------------------- unsigned long vtkKWPiecewiseFunctionEditor::GetRedrawFunctionTime() { unsigned long t = this->Superclass::GetRedrawFunctionTime(); if (this->PointColorTransferFunction && this->PointColorTransferFunction->GetMTime() > t) { return this->PointColorTransferFunction->GetMTime(); } return t; } //---------------------------------------------------------------------------- void vtkKWPiecewiseFunctionEditor::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "ValueEntryVisibility: " << (this->ValueEntryVisibility ? "On" : "Off") << endl; os << indent << "WindowLevelMode: " << (this->WindowLevelMode ? "On" : "Off") << endl; os << indent << "WindowLevelModeButtonVisibility: " << (this->WindowLevelModeButtonVisibility ? "On" : "Off") << endl; os << indent << "WindowLevelModeLockEndPointValue: " << (this->WindowLevelModeLockEndPointValue ? "On" : "Off") << endl; os << indent << "Window: " << this->Window << endl; os << indent << "Level: " << this->Level << endl; os << indent << "PiecewiseFunction: "; if (this->PiecewiseFunction) { os << endl; this->PiecewiseFunction->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "ValueEntry: "; if (this->ValueEntry) { os << endl; this->ValueEntry->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "PointColorTransferFunction: "; if (this->PointColorTransferFunction) { os << endl; this->PointColorTransferFunction->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } os << indent << "WindowLevelModeCheckButton: "; if (this->WindowLevelModeCheckButton) { os << endl; this->WindowLevelModeCheckButton->PrintSelf(os, indent.GetNextIndent()); } else { os << "None" << endl; } } kwwidgets-1.0.0~cvs20100930/vtkKWWizardWidget.cxx0000644000175000017500000006653510551525410021215 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWizardWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWWizardWidget.h" #include "vtkObjectFactory.h" #include "vtkKWApplication.h" #include "vtkKWPushButton.h" #include "vtkKWSeparator.h" #include "vtkKWFrame.h" #include "vtkKWLabel.h" #include "vtkKWLabelWithLabel.h" #include "vtkKWTkUtilities.h" #include "vtkKWInternationalization.h" #include "vtkKWWizardWorkflow.h" #include "vtkKWWizardStep.h" #include "vtkKWIcon.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWWizardWidget); vtkCxxRevisionMacro(vtkKWWizardWidget, "$Revision: 1.9 $"); //---------------------------------------------------------------------------- vtkKWWizardWidget::vtkKWWizardWidget() { this->TitleFrame = NULL; this->TitleLabel = NULL; this->SubTitleLabel = NULL; this->TitleIconLabel = NULL; this->SeparatorAfterTitleArea = NULL; this->LayoutFrame = NULL; this->PreTextLabel = NULL; this->ClientArea = NULL; this->PostTextLabel = NULL; this->ErrorTextLabel = NULL; this->SeparatorBeforeButtons = NULL; this->ButtonFrame = NULL; this->BackButton = NULL; this->NextButton = NULL; this->FinishButton = NULL; this->CancelButton = NULL; this->HelpButton = NULL; this->OKButton = NULL; this->WizardWorkflow = vtkKWWizardWorkflow::New(); this->BackButtonVisibility = 1; this->NextButtonVisibility = 1; this->FinishButtonVisibility = 1; this->CancelButtonVisibility = 1; this->HelpButtonVisibility = 0; this->OKButtonVisibility = 1; this->ButtonsPosition = vtkKWWizardWidget::ButtonsPositionBottom; } //---------------------------------------------------------------------------- vtkKWWizardWidget::~vtkKWWizardWidget() { if (this->WizardWorkflow) { this->WizardWorkflow->Delete(); this->WizardWorkflow = NULL; } if (this->TitleFrame) { this->TitleFrame->Delete(); this->TitleFrame = NULL; } if (this->TitleLabel) { this->TitleLabel->Delete(); this->TitleLabel = NULL; } if (this->SubTitleLabel) { this->SubTitleLabel->Delete(); this->SubTitleLabel = NULL; } if (this->TitleIconLabel) { this->TitleIconLabel->Delete(); this->TitleIconLabel = NULL; } if (this->SeparatorAfterTitleArea) { this->SeparatorAfterTitleArea->Delete(); this->SeparatorAfterTitleArea = NULL; } if (this->LayoutFrame) { this->LayoutFrame->Delete(); this->LayoutFrame = NULL; } if (this->PreTextLabel) { this->PreTextLabel->Delete(); this->PreTextLabel = NULL; } if (this->ClientArea) { this->ClientArea->Delete(); this->ClientArea = NULL; } if (this->PostTextLabel) { this->PostTextLabel->Delete(); this->PostTextLabel = NULL; } if (this->ErrorTextLabel) { this->ErrorTextLabel->Delete(); this->ErrorTextLabel = NULL; } if (this->SeparatorBeforeButtons) { this->SeparatorBeforeButtons->Delete(); this->SeparatorBeforeButtons = NULL; } if (this->ButtonFrame) { this->ButtonFrame->Delete(); this->ButtonFrame = NULL; } if (this->BackButton) { this->BackButton->Delete(); this->BackButton = NULL; } if (this->NextButton) { this->NextButton->Delete(); this->NextButton = NULL; } if (this->FinishButton) { this->FinishButton->Delete(); this->FinishButton = NULL; } if (this->CancelButton) { this->CancelButton->Delete(); this->CancelButton = NULL; } if (this->HelpButton) { this->HelpButton->Delete(); this->HelpButton = NULL; } if (this->OKButton) { this->OKButton->Delete(); this->OKButton = NULL; } } //---------------------------------------------------------------------------- void vtkKWWizardWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); // ------------------------------------------------------------------- // Workflow if (!this->WizardWorkflow) { this->WizardWorkflow = vtkKWWizardWorkflow::New(); } if (!this->WizardWorkflow->GetApplication()) { this->WizardWorkflow->SetApplication(this->GetApplication()); } // ------------------------------------------------------------------- // Title frame if (!this->TitleFrame) { this->TitleFrame = vtkKWFrame::New(); } this->TitleFrame->SetParent(this); this->TitleFrame->Create(); this->Script("pack %s -side top -fill x", this->TitleFrame->GetWidgetName()); // ------------------------------------------------------------------- // Title frame: Title label if (!this->TitleLabel) { this->TitleLabel = vtkKWLabel::New(); } this->TitleLabel->SetParent(this->TitleFrame); this->TitleLabel->Create(); this->TitleLabel->SetAnchorToNorthWest(); vtkKWTkUtilities::ChangeFontWeightToBold(this->TitleLabel); this->Script("grid %s -row 0 -column 0 -sticky news -padx 4 -pady 1", this->TitleLabel->GetWidgetName()); this->Script("grid rowconfigure %s 0 -weight 0", this->TitleFrame->GetWidgetName()); this->Script("grid columnconfigure %s 0 -weight 1", this->TitleFrame->GetWidgetName()); // ------------------------------------------------------------------- // Title frame: SubTitle label if (!this->SubTitleLabel) { this->SubTitleLabel = vtkKWLabel::New(); } this->SubTitleLabel->SetParent(this->TitleFrame); this->SubTitleLabel->Create(); this->SubTitleLabel->SetPadX(15); this->SubTitleLabel->AdjustWrapLengthToWidthOn(); this->SubTitleLabel->SetAnchorToNorthWest(); this->Script("grid %s -row 1 -column 0 -sticky news -padx 4 -pady 2", this->SubTitleLabel->GetWidgetName()); this->Script("grid rowconfigure %s 1 -weight 1", this->TitleFrame->GetWidgetName()); // ------------------------------------------------------------------- // Title frame: Icon if (!this->TitleIconLabel) { this->TitleIconLabel = vtkKWLabel::New(); } this->TitleIconLabel->SetParent(this->TitleFrame); this->TitleIconLabel->Create(); this->TitleIconLabel->SetReliefToFlat(); this->TitleIconLabel->SetHighlightThickness(0); this->TitleIconLabel->SetPadX(0); this->TitleIconLabel->SetPadY(0); this->Script("grid %s -row 0 -column 1 -sticky nsew -rowspan 2 -padx 8", this->TitleIconLabel->GetWidgetName()); this->Script("grid columnconfigure %s 1 -weight 0", this->TitleFrame->GetWidgetName()); // ------------------------------------------------------------------- // Separator (between title frame and layout frame if (!this->SeparatorAfterTitleArea) { this->SeparatorAfterTitleArea = vtkKWSeparator::New(); } this->SeparatorAfterTitleArea->SetParent(this); this->SeparatorAfterTitleArea->Create(); this->Script("pack %s -side top -fill x", this->SeparatorAfterTitleArea->GetWidgetName()); // ------------------------------------------------------------------- // Layout frame if (!this->LayoutFrame) { this->LayoutFrame = vtkKWFrame::New(); } this->LayoutFrame->SetParent(this); this->LayoutFrame->Create(); this->LayoutFrame->SetBorderWidth(0); this->Script("pack %s -side top -fill both -expand y -padx 0 -pady 0", this->LayoutFrame->GetWidgetName()); this->Script("grid columnconfigure %s 0 -weight 1", this->LayoutFrame->GetWidgetName()); // ------------------------------------------------------------------- // Layout frame: Pre-text if (!this->PreTextLabel) { this->PreTextLabel = vtkKWLabel::New(); } this->PreTextLabel->SetParent(this->LayoutFrame); this->PreTextLabel->Create(); this->PreTextLabel->AdjustWrapLengthToWidthOn(); this->PreTextLabel->SetJustificationToLeft(); this->PreTextLabel->SetAnchorToNorthWest(); this->Script("grid %s -row 0 -sticky nsew -padx 2 -pady 4", this->PreTextLabel->GetWidgetName()); this->Script("grid rowconfigure %s 0 -weight 0", this->LayoutFrame->GetWidgetName()); // ------------------------------------------------------------------- // Layout frame: Client area if (!this->ClientArea) { this->ClientArea = vtkKWFrame::New(); } this->ClientArea->SetParent(this->LayoutFrame); this->ClientArea->Create(); this->Script("grid %s -row 1 -sticky nsew -padx 0 -pady 0", this->ClientArea->GetWidgetName()); this->Script("grid rowconfigure %s 1 -weight 1", this->LayoutFrame->GetWidgetName()); // ------------------------------------------------------------------- // Layout frame: Post-text if (!this->PostTextLabel) { this->PostTextLabel = vtkKWLabel::New(); } this->PostTextLabel->SetParent(this->LayoutFrame); this->PostTextLabel->Create(); this->PostTextLabel->AdjustWrapLengthToWidthOn(); this->PostTextLabel->SetJustificationToLeft(); this->PostTextLabel->SetAnchorToNorthWest(); this->Script("grid %s -row 2 -sticky ew -padx 2 -pady 4", this->PostTextLabel->GetWidgetName()); this->Script("grid rowconfigure %s 2 -weight 0", this->LayoutFrame->GetWidgetName()); // ------------------------------------------------------------------- // Layout frame: Error-text if (!this->ErrorTextLabel) { this->ErrorTextLabel = vtkKWLabelWithLabel::New(); } this->ErrorTextLabel->SetParent(this->LayoutFrame); this->ErrorTextLabel->Create(); this->ErrorTextLabel->ExpandWidgetOn(); this->ErrorTextLabel->GetWidget()->SetJustificationToLeft(); this->ErrorTextLabel->GetWidget()->SetAnchorToNorthWest(); this->ErrorTextLabel->GetWidget()->AdjustWrapLengthToWidthOn(); this->Script("grid %s -row 3 -sticky ew -padx 2 -pady 2", this->ErrorTextLabel->GetWidgetName()); this->Script("grid rowconfigure %s 3 -weight 0", this->LayoutFrame->GetWidgetName()); // ------------------------------------------------------------------- // Separator (between layout frame and buttons frame) if (!this->SeparatorBeforeButtons) { this->SeparatorBeforeButtons = vtkKWSeparator::New(); } this->SeparatorBeforeButtons->SetParent(this); this->SeparatorBeforeButtons->Create(); // ------------------------------------------------------------------- // Button frame if (!this->ButtonFrame) { this->ButtonFrame = vtkKWFrame::New(); } this->ButtonFrame->SetParent(this); this->ButtonFrame->Create(); this->ButtonFrame->SetBorderWidth(0); // ------------------------------------------------------------------- // Button frame: Back if (!this->BackButton) { this->BackButton = vtkKWPushButton::New(); } this->BackButton->SetParent(this->ButtonFrame); vtksys_stl::string back("< "); back += ks_("Wizard|Button|Back"); this->BackButton->SetText(back.c_str()); this->BackButton->Create(); this->BackButton->SetWidth(8); this->BackButton->SetCommand( this->WizardWorkflow, "AttemptToGoToPreviousStep"); // ------------------------------------------------------------------- // Button frame: Next if (!this->NextButton) { this->NextButton = vtkKWPushButton::New(); } this->NextButton->SetParent(this->ButtonFrame); vtksys_stl::string next(ks_("Wizard|Button|Next")); next += " >"; this->NextButton->SetText(next.c_str()); this->NextButton->Create(); this->NextButton->SetWidth(8); this->NextButton->SetCommand( this->WizardWorkflow, "AttemptToGoToNextStep"); // ------------------------------------------------------------------- // Button frame: Finish if (!this->FinishButton) { this->FinishButton = vtkKWPushButton::New(); } this->FinishButton->SetParent(this->ButtonFrame); this->FinishButton->Create(); this->FinishButton->SetWidth(8); this->FinishButton->SetText(ks_("Wizard|Button|Finish")); this->FinishButton->SetCommand( this->WizardWorkflow, "AttemptToGoToFinishStep"); // ------------------------------------------------------------------- // Button frame: Cancel if (!this->CancelButton) { this->CancelButton = vtkKWPushButton::New(); } this->CancelButton->SetParent(this->ButtonFrame); this->CancelButton->SetText(ks_("Wizard|Button|Cancel")); this->CancelButton->Create(); this->CancelButton->SetWidth(8); // ------------------------------------------------------------------- // Button frame: Cancel if (!this->HelpButton) { this->HelpButton = vtkKWPushButton::New(); } this->HelpButton->SetParent(this->ButtonFrame); this->HelpButton->SetText(ks_("Wizard|Button|Help")); this->HelpButton->Create(); this->HelpButton->SetWidth(8); // ------------------------------------------------------------------- // Button frame: OK if (!this->OKButton) { this->OKButton = vtkKWPushButton::New(); } this->OKButton->SetParent(this->ButtonFrame); this->OKButton->SetText(ks_("Wizard|Button|OK")); this->OKButton->Create(); this->OKButton->SetWidth(8); this->PackButtons(); // The pre and post text will initially not be visible. They will pop into // existence if they are configured to have a value this->Script("grid remove %s %s", this->PreTextLabel->GetWidgetName(), this->PostTextLabel->GetWidgetName() ); this->SetTitleAreaBackgroundColor(1.0, 1.0, 1.0); this->AddCallbackCommandObservers(); this->Update(); } //--------------------------------------------------------------------------- void vtkKWWizardWidget::Update() { this->UpdateEnableState(); this->PackButtons(); vtkKWWizardStep *current_step = this->WizardWorkflow->GetCurrentStep(); vtkKWWizardStep *finish_step = this->WizardWorkflow->GetFinishStep(); vtkKWWizardStep *previous_step = NULL; int nb_steps_in_stack = this->WizardWorkflow->GetNumberOfStepsInNavigationStack(); if (nb_steps_in_stack >= 2) // both current step and previous step on stack { previous_step = this->WizardWorkflow->GetNthStepInNavigationStack(nb_steps_in_stack - 2); } // Update title this->SetTitle(current_step ? current_step->GetName() : NULL); this->SetSubTitle(current_step ? current_step->GetDescription() : NULL); // Update buttons if (this->BackButton) { int can_go = (previous_step && previous_step != current_step); this->BackButton->SetEnabled(can_go ? this->GetEnabled() : 0); } if (this->NextButton) { int can_go = (current_step != finish_step); this->NextButton->SetEnabled(can_go ? this->GetEnabled() : 0); } if (this->FinishButton) { int can_go = (finish_step && finish_step != current_step && finish_step->CanGoToSelf()); this->FinishButton->SetEnabled(can_go ? this->GetEnabled() : 0); } if (this->OKButton) { int can_go = (finish_step && finish_step == current_step); this->OKButton->SetEnabled(can_go ? this->GetEnabled() : 0); } } //---------------------------------------------------------------------------- void vtkKWWizardWidget::PackButtons() { if (this->ButtonsPosition == vtkKWWizardWidget::ButtonsPositionBottom) { this->Script("pack %s -side top -fill x -pady 2 -after %s", this->SeparatorBeforeButtons->GetWidgetName(), this->LayoutFrame->GetWidgetName()); this->Script("pack %s -side top -fill x -padx 0 -pady 0 -after %s", this->ButtonFrame->GetWidgetName(), this->SeparatorBeforeButtons->GetWidgetName()); } else { this->Script("pack %s -side top -fill x -pady {2 1} -before %s", this->SeparatorBeforeButtons->GetWidgetName(), this->TitleFrame->GetWidgetName()); this->Script("pack %s -side top -fill x -padx 0 -pady 0 -before %s", this->ButtonFrame->GetWidgetName(), this->SeparatorBeforeButtons->GetWidgetName()); } this->ButtonFrame->UnpackChildren(); vtkKWWizardStep *current_step = this->WizardWorkflow->GetCurrentStep(); vtkKWWizardStep *finish_step = this->WizardWorkflow->GetFinishStep(); if (this->HelpButtonVisibility && this->HelpButton && this->HelpButton->IsCreated()) { this->Script("pack %s -side right", this->HelpButton->GetWidgetName()); } if (this->CancelButtonVisibility && this->CancelButton && this->CancelButton->IsCreated()) { this->Script("pack %s -side right -padx %d", this->CancelButton->GetWidgetName(), this->HelpButtonVisibility ? 4 : 0); } if (this->OKButtonVisibility && current_step && current_step == finish_step && this->OKButton && this->OKButton->IsCreated()) { this->Script("pack %s -side right -padx 4", this->OKButton->GetWidgetName()); } if (this->FinishButtonVisibility && current_step && current_step != finish_step && this->FinishButton && this->FinishButton->IsCreated()) { this->Script("pack %s -side right -padx 4", this->FinishButton->GetWidgetName()); } if (this->NextButtonVisibility && this->NextButton && this->NextButton->IsCreated()) { this->Script("pack %s -side right", this->NextButton->GetWidgetName()); } if (this->BackButtonVisibility && this->BackButton && this->BackButton->IsCreated()) { this->Script("pack %s -side right", this->BackButton->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetButtonsPosition(int arg) { if (arg < vtkKWWizardWidget::ButtonsPositionTop) { arg = vtkKWWizardWidget::ButtonsPositionTop; } else if (arg > vtkKWWizardWidget::ButtonsPositionBottom) { arg = vtkKWWizardWidget::ButtonsPositionBottom; } if (this->ButtonsPosition == arg) { return; } this->ButtonsPosition = arg; this->Modified(); this->PackButtons(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetClientAreaMinimumHeight(int arg) { if (this->LayoutFrame && this->LayoutFrame->IsCreated()) { this->Script("grid rowconfigure %s 1 -minsize %d", this->LayoutFrame->GetWidgetName(), arg); } } //---------------------------------------------------------------------------- void vtkKWWizardWidget::AddCallbackCommandObservers() { this->Superclass::AddCallbackCommandObservers(); this->AddCallbackCommandObserver( this->WizardWorkflow, vtkKWWizardWorkflow::NavigationStackedChangedEvent); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::RemoveCallbackCommandObservers() { this->Superclass::RemoveCallbackCommandObservers(); this->RemoveCallbackCommandObserver( this->WizardWorkflow, vtkKWWizardWorkflow::NavigationStackedChangedEvent); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::ProcessCallbackCommandEvents(vtkObject *caller, unsigned long event, void *calldata) { if (caller == this->WizardWorkflow) { switch (event) { case vtkKWWizardWorkflow::NavigationStackedChangedEvent: this->Update(); break; } } this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::GetTitleAreaBackgroundColor(double *r, double *g, double *b) { if (this->TitleFrame) { this->TitleFrame->GetBackgroundColor(r, g, b); } } //---------------------------------------------------------------------------- double* vtkKWWizardWidget::GetTitleAreaBackgroundColor() { if (this->TitleFrame) { return this->TitleFrame->GetBackgroundColor(); } return NULL; } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetTitleAreaBackgroundColor(double r, double g, double b) { if (this->TitleFrame) { this->TitleFrame->SetBackgroundColor(r, g, b); } if (this->TitleLabel) { this->TitleLabel->SetBackgroundColor(r, g, b); } if (this->SubTitleLabel) { this->SubTitleLabel->SetBackgroundColor(r, g, b); } if (this->TitleIconLabel) { this->TitleIconLabel->SetForegroundColor(r, g, b); this->TitleIconLabel->SetBackgroundColor(r, g, b); } } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetBackButtonVisibility(int arg) { if (this->BackButtonVisibility == arg) { return; } this->BackButtonVisibility = arg; this->Modified(); this->PackButtons(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetNextButtonVisibility(int arg) { if (this->NextButtonVisibility == arg) { return; } this->NextButtonVisibility = arg; this->Modified(); this->PackButtons(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetFinishButtonVisibility(int arg) { if (this->FinishButtonVisibility == arg) { return; } this->FinishButtonVisibility = arg; this->Modified(); this->PackButtons(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetCancelButtonVisibility(int arg) { if (this->CancelButtonVisibility == arg) { return; } this->CancelButtonVisibility = arg; this->Modified(); this->PackButtons(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetHelpButtonVisibility(int arg) { if (this->HelpButtonVisibility == arg) { return; } this->HelpButtonVisibility = arg; this->Modified(); this->PackButtons(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetOKButtonVisibility(int arg) { if (this->OKButtonVisibility == arg) { return; } this->OKButtonVisibility = arg; this->Modified(); this->PackButtons(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::ClearPage() { this->ClientArea->UnpackChildren(); this->SetPreText(NULL); this->SetPostText(NULL); this->SetErrorText(NULL); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetPreText(const char* str) { if (this->PreTextLabel) { this->PreTextLabel->SetText(str); } if (this->IsCreated()) { this->Script("grid %s %s", ((str && *str) ? "" : "remove"), this->PreTextLabel->GetWidgetName()); } } //---------------------------------------------------------------------------- char* vtkKWWizardWidget::GetPreText() { return this->PreTextLabel->GetText(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetPostText(const char* str) { this->PostTextLabel->SetText(str); if (this->IsCreated()) { this->Script("grid %s %s", ((str && *str) ? "" : "remove"), this->PostTextLabel->GetWidgetName()); } } //---------------------------------------------------------------------------- char* vtkKWWizardWidget::GetPostText() { return this->PostTextLabel->GetText(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetErrorText(const char* str) { this->ErrorTextLabel->GetWidget()->SetText(str); if (str && *str) { this->ErrorTextLabel->GetLabel()->SetImageToPredefinedIcon( vtkKWIcon::IconWarningMini); } else { this->ErrorTextLabel->GetLabel()->SetImageToIcon(NULL); } } //---------------------------------------------------------------------------- char* vtkKWWizardWidget::GetErrorText() { return this->ErrorTextLabel->GetWidget()->GetText(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetTitle(const char* str) { this->TitleLabel->SetText(str); } //---------------------------------------------------------------------------- char* vtkKWWizardWidget::GetTitle() { return this->TitleLabel->GetText(); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::SetSubTitle(const char* str) { this->SubTitleLabel->SetText(str); } //---------------------------------------------------------------------------- char* vtkKWWizardWidget::GetSubTitle() { return this->SubTitleLabel->GetText(); } //--------------------------------------------------------------------------- void vtkKWWizardWidget::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->TitleFrame); this->PropagateEnableState(this->TitleLabel); this->PropagateEnableState(this->SubTitleLabel); this->PropagateEnableState(this->SeparatorAfterTitleArea); this->PropagateEnableState(this->LayoutFrame); this->PropagateEnableState(this->PreTextLabel); this->PropagateEnableState(this->ClientArea); this->PropagateEnableState(this->PostTextLabel); this->PropagateEnableState(this->ErrorTextLabel); this->PropagateEnableState(this->SeparatorBeforeButtons); this->PropagateEnableState(this->ButtonFrame); this->PropagateEnableState(this->BackButton); this->PropagateEnableState(this->NextButton); this->PropagateEnableState(this->CancelButton); this->PropagateEnableState(this->HelpButton); this->PropagateEnableState(this->OKButton); this->PropagateEnableState(this->FinishButton); } //---------------------------------------------------------------------------- void vtkKWWizardWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "BackButtonVisibility: " << (this->BackButtonVisibility ? "On" : "Off") << endl; os << indent << "NextButtonVisibility: " << (this->NextButtonVisibility ? "On" : "Off") << endl; os << indent << "FinishButtonVisibility: " << (this->FinishButtonVisibility ? "On" : "Off") << endl; os << indent << "CancelButtonVisibility: " << (this->CancelButtonVisibility ? "On" : "Off") << endl; os << indent << "HelpButtonVisibility: " << (this->HelpButtonVisibility ? "On" : "Off") << endl; os << indent << "OKButtonVisibility: " << (this->OKButtonVisibility ? "On" : "Off") << endl; os << indent << "ButtonsPosition: " << this->ButtonsPosition << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWEventMap.cxx0000644000175000017500000010724711101670566020331 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWEventMap.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWEventMap.h" #include "vtkObjectFactory.h" #include "vtksys/stl/string" vtkCxxRevisionMacro(vtkKWEventMap, "$Revision: 1.4 $"); vtkStandardNewMacro(vtkKWEventMap); //---------------------------------------------------------------------------- vtkKWEventMap::vtkKWEventMap() { this->NumberOfMouseEvents = 0; this->NumberOfKeyEvents = 0; this->NumberOfKeySymEvents = 0; this->MouseEvents = NULL; this->KeyEvents = NULL; this->KeySymEvents = NULL; } //---------------------------------------------------------------------------- vtkKWEventMap::~vtkKWEventMap() { this->RemoveAllMouseEvents(); this->RemoveAllKeyEvents(); this->RemoveAllKeySymEvents(); } //---------------------------------------------------------------------------- void vtkKWEventMap::RemoveAllMouseEvents() { if (this->MouseEvents) { for (int i = 0; i < this->NumberOfMouseEvents; i++) { delete [] this->MouseEvents[i].Action; delete [] this->MouseEvents[i].Context; delete [] this->MouseEvents[i].Description; } delete [] this->MouseEvents; this->MouseEvents = NULL; } this->NumberOfMouseEvents = 0; } //---------------------------------------------------------------------------- void vtkKWEventMap::RemoveAllKeyEvents() { if (this->KeyEvents) { for (int i = 0; i < this->NumberOfKeyEvents; i++) { delete [] this->KeyEvents[i].Action; delete [] this->KeyEvents[i].Context; delete [] this->KeyEvents[i].Description; } delete [] this->KeyEvents; this->KeyEvents = NULL; } this->NumberOfKeyEvents = 0; } //---------------------------------------------------------------------------- void vtkKWEventMap::RemoveAllKeySymEvents() { if (this->KeySymEvents) { for (int i = 0; i < this->NumberOfKeySymEvents; i++) { delete [] this->KeySymEvents[i].KeySym; delete [] this->KeySymEvents[i].Action; delete [] this->KeySymEvents[i].Context; delete [] this->KeySymEvents[i].Description; } delete [] this->KeySymEvents; this->KeySymEvents = NULL; } this->NumberOfKeySymEvents = 0; } //---------------------------------------------------------------------------- void vtkKWEventMap::AddMouseEvent(vtkKWEventMap::MouseEvent *me) { if (me) { this->AddMouseEvent(me->Button, me->Modifier, me->Action, me->Context, me->Description); } } //---------------------------------------------------------------------------- void vtkKWEventMap::AddMouseEvent(int button, int modifier, const char *action) { this->AddMouseEvent(button, modifier, action, NULL, NULL); } //---------------------------------------------------------------------------- void vtkKWEventMap::AddMouseEvent( int button, int modifier, const char *action, const char *context, const char *description) { if ( ! action) { vtkErrorMacro("Can't add NULL action"); return; } if (this->FindMouseAction(button, modifier)) { vtkErrorMacro("Action already exists for this button and modifier.\n" << "Try SetMouseEvent to change this binding."); return; } int i; MouseEvent *events = new MouseEvent[this->NumberOfMouseEvents]; for (i = 0; i < this->NumberOfMouseEvents; i++) { events[i].Button = this->MouseEvents[i].Button; events[i].Modifier = this->MouseEvents[i].Modifier; events[i].Action = new char[strlen(this->MouseEvents[i].Action) + 1]; strcpy(events[i].Action, this->MouseEvents[i].Action); delete [] this->MouseEvents[i].Action; if (this->MouseEvents[i].Context) { events[i].Context = new char[strlen(this->MouseEvents[i].Context) + 1]; strcpy(events[i].Context, this->MouseEvents[i].Context); delete [] this->MouseEvents[i].Context; } else { events[i].Context = NULL; } if (this->MouseEvents[i].Description) { events[i].Description = new char[strlen(this->MouseEvents[i].Description) + 1]; strcpy(events[i].Description, this->MouseEvents[i].Description); delete [] this->MouseEvents[i].Description; } else { events[i].Description = NULL; } } if (this->MouseEvents) { delete [] this->MouseEvents; this->MouseEvents = NULL; } this->MouseEvents = new MouseEvent[this->NumberOfMouseEvents + 1]; for (i = 0; i < this->NumberOfMouseEvents; i++) { this->MouseEvents[i].Button = events[i].Button; this->MouseEvents[i].Modifier = events[i].Modifier; this->MouseEvents[i].Action = new char[strlen(events[i].Action) + 1]; strcpy(this->MouseEvents[i].Action, events[i].Action); delete [] events[i].Action; if (events[i].Context) { this->MouseEvents[i].Context = new char[strlen(events[i].Context) + 1]; strcpy(this->MouseEvents[i].Context, events[i].Context); delete [] events[i].Context; } else { this->MouseEvents[i].Context = NULL; } if (events[i].Description) { this->MouseEvents[i].Description = new char[strlen(events[i].Description) + 1]; strcpy(this->MouseEvents[i].Description, events[i].Description); delete [] events[i].Description; } else { this->MouseEvents[i].Description = NULL; } } delete [] events; this->MouseEvents[i].Button = button; this->MouseEvents[i].Modifier = modifier; this->MouseEvents[i].Action = new char[strlen(action) + 1]; strcpy(this->MouseEvents[i].Action, action); if (context) { this->MouseEvents[i].Context = new char[strlen(context) + 1]; strcpy(this->MouseEvents[i].Context, context); } else { this->MouseEvents[i].Context = NULL; } if (description) { this->MouseEvents[i].Description = new char[strlen(description) + 1]; strcpy(this->MouseEvents[i].Description, description); } else { this->MouseEvents[i].Description = NULL; } this->NumberOfMouseEvents++; } //---------------------------------------------------------------------------- void vtkKWEventMap::AddKeyEvent(vtkKWEventMap::KeyEvent *me) { if (me) { this->AddKeyEvent(me->Key, me->Modifier, me->Action, me->Context, me->Description); } } //---------------------------------------------------------------------------- void vtkKWEventMap::AddKeyEvent(char key, int modifier, const char *action) { this->AddKeyEvent(key, modifier, action, NULL, NULL); } //---------------------------------------------------------------------------- void vtkKWEventMap::AddKeyEvent( char key, int modifier, const char *action, const char *context, const char *description) { if ( ! action) { vtkErrorMacro("Can't add NULL action"); return; } if (this->FindKeyAction(key, modifier)) { vtkErrorMacro("Action already exists for this key and modifier.\n" << "Try SetKeyEvent to change this binding."); return; } int i; KeyEvent *events = new KeyEvent[this->NumberOfKeyEvents]; for (i = 0; i < this->NumberOfKeyEvents; i++) { events[i].Key = this->KeyEvents[i].Key; events[i].Modifier = this->KeyEvents[i].Modifier; events[i].Action = new char[strlen(this->KeyEvents[i].Action) + 1]; strcpy(events[i].Action, this->KeyEvents[i].Action); delete [] this->KeyEvents[i].Action; if (this->KeyEvents[i].Context) { events[i].Context = new char[strlen(this->KeyEvents[i].Context) + 1]; strcpy(events[i].Context, this->KeyEvents[i].Context); delete [] this->KeyEvents[i].Context; } else { events[i].Context = NULL; } if (this->KeyEvents[i].Description) { events[i].Description = new char[strlen(this->KeyEvents[i].Description) + 1]; strcpy(events[i].Description, this->KeyEvents[i].Description); delete [] this->KeyEvents[i].Description; } else { events[i].Description = NULL; } } if (this->KeyEvents) { delete [] this->KeyEvents; this->KeyEvents = NULL; } this->KeyEvents = new KeyEvent[this->NumberOfKeyEvents + 1]; for (i = 0; i < this->NumberOfKeyEvents; i++) { this->KeyEvents[i].Key = events[i].Key; this->KeyEvents[i].Modifier = events[i].Modifier; this->KeyEvents[i].Action = new char[strlen(events[i].Action) + 1]; strcpy(this->KeyEvents[i].Action, events[i].Action); delete [] events[i].Action; if (events[i].Context) { this->KeyEvents[i].Context = new char[strlen(events[i].Context) + 1]; strcpy(this->KeyEvents[i].Context, events[i].Context); delete [] events[i].Context; } else { this->KeyEvents[i].Context = NULL; } if (events[i].Description) { this->KeyEvents[i].Description = new char[strlen(events[i].Description) + 1]; strcpy(this->KeyEvents[i].Description, events[i].Description); delete [] events[i].Description; } else { this->KeyEvents[i].Description = NULL; } } delete [] events; this->KeyEvents[i].Key = key; this->KeyEvents[i].Modifier = modifier; this->KeyEvents[i].Action = new char[strlen(action) + 1]; strcpy(this->KeyEvents[i].Action, action); if (context) { this->KeyEvents[i].Context = new char[strlen(context) + 1]; strcpy(this->KeyEvents[i].Context, context); } else { this->KeyEvents[i].Context = NULL; } if (description) { this->KeyEvents[i].Description = new char[strlen(description) + 1]; strcpy(this->KeyEvents[i].Description, description); } else { this->KeyEvents[i].Description = NULL; } this->NumberOfKeyEvents++; } //---------------------------------------------------------------------------- void vtkKWEventMap::AddKeySymEvent(vtkKWEventMap::KeySymEvent *me) { if (me) { this->AddKeySymEvent(me->KeySym, me->Modifier, me->Action, me->Context, me->Description); } } //---------------------------------------------------------------------------- void vtkKWEventMap::AddKeySymEvent(const char *keySym, int modifier, const char *action) { this->AddKeySymEvent(keySym, modifier, action, NULL, NULL); } //---------------------------------------------------------------------------- void vtkKWEventMap::AddKeySymEvent( const char *keySym, int modifier, const char *action, const char *context, const char *description) { if ( ! keySym) { vtkErrorMacro("Can't add event for NULL keySym"); return; } if ( ! action) { vtkErrorMacro("Can't add NULL action"); return; } if (this->FindKeySymAction(keySym, modifier)) { vtkErrorMacro("Action already exists for this keySym.\n" << "Try SetKeySymEvent to change this binding."); return; } int i; KeySymEvent *events = new KeySymEvent[this->NumberOfKeySymEvents]; for (i = 0; i < this->NumberOfKeySymEvents; i++) { events[i].KeySym = new char[strlen(this->KeySymEvents[i].KeySym) + 1]; strcpy(events[i].KeySym, this->KeySymEvents[i].KeySym); delete [] this->KeySymEvents[i].KeySym; events[i].Modifier = this->KeySymEvents[i].Modifier; events[i].Action = new char[strlen(this->KeySymEvents[i].Action) + 1]; strcpy(events[i].Action, this->KeySymEvents[i].Action); delete [] this->KeySymEvents[i].Action; if (this->KeySymEvents[i].Context) { events[i].Context = new char[strlen(this->KeySymEvents[i].Context) + 1]; strcpy(events[i].Context, this->KeySymEvents[i].Context); delete [] this->KeySymEvents[i].Context; } else { events[i].Context = NULL; } if (this->KeySymEvents[i].Description) { events[i].Description = new char[strlen(this->KeySymEvents[i].Description) + 1]; strcpy(events[i].Description, this->KeySymEvents[i].Description); delete [] this->KeySymEvents[i].Description; } else { events[i].Description = NULL; } } if (this->KeySymEvents) { delete [] this->KeySymEvents; this->KeySymEvents = NULL; } this->KeySymEvents = new KeySymEvent[this->NumberOfKeySymEvents + 1]; for (i = 0; i < this->NumberOfKeySymEvents; i++) { this->KeySymEvents[i].KeySym = new char[strlen(events[i].KeySym) + 1]; strcpy(this->KeySymEvents[i].KeySym, events[i].KeySym); delete [] events[i].KeySym; this->KeySymEvents[i].Modifier = events[i].Modifier; this->KeySymEvents[i].Action = new char[strlen(events[i].Action) + 1]; strcpy(this->KeySymEvents[i].Action, events[i].Action); delete [] events[i].Action; if (events[i].Context) { this->KeySymEvents[i].Context = new char[strlen(events[i].Context) + 1]; strcpy(this->KeySymEvents[i].Context, events[i].Context); delete [] events[i].Context; } else { this->KeySymEvents[i].Context = NULL; } if (events[i].Description) { this->KeySymEvents[i].Description = new char[strlen(events[i].Description) + 1]; strcpy(this->KeySymEvents[i].Description, events[i].Description); delete [] events[i].Description; } else { this->KeySymEvents[i].Description = NULL; } } delete [] events; this->KeySymEvents[i].KeySym = new char[strlen(keySym) + 1]; strcpy(this->KeySymEvents[i].KeySym, keySym); this->KeySymEvents[i].Modifier = modifier; this->KeySymEvents[i].Action = new char[strlen(action) + 1]; strcpy(this->KeySymEvents[i].Action, action); if (context) { this->KeySymEvents[i].Context = new char[strlen(context) + 1]; strcpy(this->KeySymEvents[i].Context, context); } else { this->KeySymEvents[i].Context = NULL; } if (description) { this->KeySymEvents[i].Description = new char[strlen(description) + 1]; strcpy(this->KeySymEvents[i].Description, description); } else { this->KeySymEvents[i].Description = NULL; } this->NumberOfKeySymEvents++; } //---------------------------------------------------------------------------- void vtkKWEventMap::SetMouseEvent(vtkKWEventMap::MouseEvent *me) { if (me) { this->SetMouseEvent(me->Button, me->Modifier, me->Action, me->Context, me->Description); } } //---------------------------------------------------------------------------- void vtkKWEventMap::SetMouseEvent(int button, int modifier, const char *action) { this->SetMouseEvent(button, modifier, action, NULL, NULL); } //---------------------------------------------------------------------------- void vtkKWEventMap::SetMouseEvent( int button, int modifier, const char *action, const char *context, const char *description) { int i; if ( ! action) { vtkErrorMacro("Can't set NULL action"); return; } for (i = 0; i < this->NumberOfMouseEvents; i++) { if (this->MouseEvents[i].Button == button && this->MouseEvents[i].Modifier == modifier) { delete [] this->MouseEvents[i].Action; this->MouseEvents[i].Action = new char[strlen(action)+1]; strcpy(this->MouseEvents[i].Action, action); delete [] this->MouseEvents[i].Context; if (context) { this->MouseEvents[i].Context = new char[strlen(context)+1]; strcpy(this->MouseEvents[i].Context, context); } else { this->MouseEvents[i].Context = NULL; } delete [] this->MouseEvents[i].Description; if (description) { this->MouseEvents[i].Description = new char[strlen(description)+1]; strcpy(this->MouseEvents[i].Description, description); } else { this->MouseEvents[i].Description = NULL; } break; } } } //---------------------------------------------------------------------------- void vtkKWEventMap::SetKeyEvent(char key, int modifier, const char *action) { this->SetKeyEvent(key, modifier, action, NULL, NULL); } //---------------------------------------------------------------------------- void vtkKWEventMap::SetKeyEvent( char key, int modifier, const char *action, const char *context, const char *description) { int i; if ( ! action) { vtkErrorMacro("Can't set NULL action"); return; } for (i = 0; i < this->NumberOfKeyEvents; i++) { if (this->KeyEvents[i].Key == key && this->KeyEvents[i].Modifier == modifier) { delete [] this->KeyEvents[i].Action; this->KeyEvents[i].Action = new char[strlen(action)+1]; strcpy(this->KeyEvents[i].Action, action); delete [] this->KeyEvents[i].Context; if (context) { this->KeyEvents[i].Context = new char[strlen(context)+1]; strcpy(this->KeyEvents[i].Context, context); } else { this->KeyEvents[i].Context = NULL; } delete [] this->KeyEvents[i].Description; if (description) { this->KeyEvents[i].Description = new char[strlen(description)+1]; strcpy(this->KeyEvents[i].Description, description); } else { this->KeyEvents[i].Description = NULL; } break; } } } //---------------------------------------------------------------------------- void vtkKWEventMap::SetKeySymEvent(const char *keySym, int modifier, const char *action) { this->SetKeySymEvent(keySym, modifier, action, NULL, NULL); } //---------------------------------------------------------------------------- void vtkKWEventMap::SetKeySymEvent( const char *keySym, int modifier, const char *action, const char *context, const char *description) { int i; if ( ! action) { vtkErrorMacro("Can't set NULL action"); return; } for (i = 0; i < this->NumberOfKeySymEvents; i++) { if (this->KeySymEvents[i].Modifier == modifier && ! strcmp(this->KeySymEvents[i].KeySym, keySym)) { delete [] this->KeySymEvents[i].Action; this->KeySymEvents[i].Action = new char[strlen(action)+1]; strcpy(this->KeySymEvents[i].Action, action); delete [] this->KeySymEvents[i].Context; if (context) { this->KeySymEvents[i].Context = new char[strlen(context)+1]; strcpy(this->KeySymEvents[i].Context, context); } else { this->KeySymEvents[i].Context = NULL; } delete [] this->KeySymEvents[i].Description; if (description) { this->KeySymEvents[i].Description = new char[strlen(description)+1]; strcpy(this->KeySymEvents[i].Description, description); } else { this->KeySymEvents[i].Description = NULL; } break; } } } //---------------------------------------------------------------------------- void vtkKWEventMap::RemoveMouseEvent(vtkKWEventMap::MouseEvent *me) { if (me) { this->RemoveMouseEvent(me->Button, me->Modifier, me->Action); } } //---------------------------------------------------------------------------- void vtkKWEventMap::RemoveMouseEvent(int button, int modifier, const char *action) { if ( ! action) { // No action specified, then remove all actions do { action = this->FindMouseAction(button, modifier); if (action) { this->RemoveMouseEvent(button, modifier, action); } } while (action); return; } if (strcmp(this->FindMouseAction(button, modifier), action)) { // If this event doesn't exist, we can't remove it. return; } int i; MouseEvent *events = NULL; if (this->NumberOfMouseEvents > 1) { events = new MouseEvent[this->NumberOfMouseEvents]; for (i = 0; i < this->NumberOfMouseEvents; i++) { events[i].Button = this->MouseEvents[i].Button; events[i].Modifier = this->MouseEvents[i].Modifier; events[i].Action = new char[strlen(this->MouseEvents[i].Action) + 1]; strcpy(events[i].Action, this->MouseEvents[i].Action); if (this->MouseEvents[i].Context) { events[i].Context = new char[strlen(this->MouseEvents[i].Context) + 1]; strcpy(events[i].Context, this->MouseEvents[i].Context); } else { events[i].Context = NULL; } if (this->MouseEvents[i].Description) { events[i].Description = new char[strlen(this->MouseEvents[i].Description) + 1]; strcpy(events[i].Description, this->MouseEvents[i].Description); } else { events[i].Description = NULL; } } } // Need to keep it around in case sombody is passing a pointer // to an action that we are going to delete below vtksys_stl::string old_action(action); if (this->MouseEvents) { for (i = 0; i < this->NumberOfMouseEvents; i++) { delete [] this->MouseEvents[i].Action; delete [] this->MouseEvents[i].Context; delete [] this->MouseEvents[i].Description; } delete [] this->MouseEvents; this->MouseEvents = NULL; } if (this->NumberOfMouseEvents > 1) { int count = 0; this->MouseEvents = new MouseEvent[this->NumberOfMouseEvents-1]; for (i = 0; i < this->NumberOfMouseEvents; i++) { if (events[i].Button != button || events[i].Modifier != modifier || strcmp(events[i].Action, old_action.c_str())) { this->MouseEvents[count].Button = events[i].Button; this->MouseEvents[count].Modifier = events[i].Modifier; this->MouseEvents[count].Action = new char[strlen(events[i].Action)+1]; strcpy(this->MouseEvents[count].Action, events[i].Action); delete [] events[i].Action; if (events[i].Context) { this->MouseEvents[count].Context = new char[strlen(events[i].Context)+1]; strcpy(this->MouseEvents[count].Context, events[i].Context); delete [] events[i].Context; } else { this->MouseEvents[count].Context = NULL; } if (events[i].Description) { this->MouseEvents[count].Description = new char[strlen(events[i].Description)+1]; strcpy(this->MouseEvents[count].Description, events[i].Description); delete [] events[i].Description; } else { this->MouseEvents[count].Description = NULL; } count++; } } delete [] events; } this->NumberOfMouseEvents--; } //---------------------------------------------------------------------------- void vtkKWEventMap::RemoveKeyEvent(char key, int modifier, const char *action) { if ( ! action) { // No action specified, then remove all actions do { action = this->FindKeyAction(key, modifier); if (action) { this->RemoveKeyEvent(key, modifier, action); } } while (action); return; } if (strcmp(this->FindKeyAction(key, modifier), action)) { // If this event doesn't exist, we can't remove it. return; } int i; KeyEvent *events = NULL; if (this->NumberOfKeyEvents > 1) { events = new KeyEvent[this->NumberOfKeyEvents]; for (i = 0; i < this->NumberOfKeyEvents; i++) { events[i].Key = this->KeyEvents[i].Key; events[i].Modifier = this->KeyEvents[i].Modifier; events[i].Action = new char[strlen(this->KeyEvents[i].Action) + 1]; strcpy(events[i].Action, this->KeyEvents[i].Action); if (this->KeyEvents[i].Context) { events[i].Context = new char[strlen(this->KeyEvents[i].Context) + 1]; strcpy(events[i].Context, this->KeyEvents[i].Context); } else { events[i].Context = NULL; } if (this->KeyEvents[i].Description) { events[i].Description = new char[strlen(this->KeyEvents[i].Description) + 1]; strcpy(events[i].Description, this->KeyEvents[i].Description); } else { events[i].Description = NULL; } } } // Need to keep it around in case sombody is passing a pointer // to an action that we are going to delete below vtksys_stl::string old_action(action); if (this->KeyEvents) { for (i = 0; i < this->NumberOfKeyEvents; i++) { delete [] this->KeyEvents[i].Action; delete [] this->KeyEvents[i].Context; delete [] this->KeyEvents[i].Description; } delete [] this->KeyEvents; this->KeyEvents = NULL; } if (this->NumberOfKeyEvents > 1) { int count = 0; this->KeyEvents = new KeyEvent[this->NumberOfKeyEvents-1]; for (i = 0; i < this->NumberOfKeyEvents; i++) { if (events[i].Key != key || events[i].Modifier != modifier || strcmp(events[i].Action, old_action.c_str())) { this->KeyEvents[count].Key = events[i].Key; this->KeyEvents[count].Modifier = events[i].Modifier; this->KeyEvents[count].Action = new char[strlen(events[i].Action)+1]; strcpy(this->KeyEvents[count].Action, events[i].Action); delete [] events[i].Action; if (events[i].Context) { this->KeyEvents[count].Context = new char[strlen(events[i].Context)+1]; strcpy(this->KeyEvents[count].Context, events[i].Context); delete [] events[i].Context; } else { this->KeyEvents[count].Context = NULL; } if (events[i].Description) { this->KeyEvents[count].Description = new char[strlen(events[i].Description)+1]; strcpy(this->KeyEvents[count].Description, events[i].Description); delete [] events[i].Description; } else { this->KeyEvents[count].Description = NULL; } count++; } } delete [] events; } this->NumberOfKeyEvents--; } //---------------------------------------------------------------------------- void vtkKWEventMap::RemoveKeySymEvent(const char *keySym, int modifier, const char *action) { if ( ! action) { // No action specified, then remove all actions do { action = this->FindKeySymAction(keySym, modifier); if (action) { this->RemoveKeySymEvent(keySym, modifier, action); } } while (action); return; } if ( ! keySym) { // It isn't possible to add a NULL keySym, so there's no reason to // try to remove it. return; } if (strcmp(this->FindKeySymAction(keySym, modifier), action)) { // If this event doesn't exist, we can't remove it. return; } int i; KeySymEvent *events = NULL; if (this->NumberOfKeySymEvents > 1) { events = new KeySymEvent[this->NumberOfKeySymEvents]; for (i = 0; i < this->NumberOfKeySymEvents; i++) { events[i].KeySym = new char[strlen(this->KeySymEvents[i].KeySym) + 1]; strcpy(events[i].KeySym, this->KeySymEvents[i].KeySym); events[i].Modifier = this->KeySymEvents[i].Modifier; events[i].Action = new char[strlen(this->KeySymEvents[i].Action) + 1]; strcpy(events[i].Action, this->KeySymEvents[i].Action); if (this->KeySymEvents[i].Context) { events[i].Context = new char[strlen(this->KeySymEvents[i].Context) + 1]; strcpy(events[i].Context, this->KeySymEvents[i].Context); } else { events[i].Context = NULL; } if (this->KeySymEvents[i].Description) { events[i].Description = new char[strlen(this->KeySymEvents[i].Description) + 1]; strcpy(events[i].Description, this->KeySymEvents[i].Description); } else { events[i].Description = NULL; } } } // Need to keep it around in case sombody is passing a pointer // to an action that we are going to delete below vtksys_stl::string old_action(action); vtksys_stl::string old_keysym(keySym); if (this->KeySymEvents) { for (i = 0; i < this->NumberOfKeySymEvents; i++) { delete [] this->KeySymEvents[i].KeySym; delete [] this->KeySymEvents[i].Action; delete [] this->KeySymEvents[i].Context; delete [] this->KeySymEvents[i].Description; } delete [] this->KeySymEvents; this->KeySymEvents = NULL; } if (this->NumberOfKeySymEvents > 1) { int count = 0; this->KeySymEvents = new KeySymEvent[this->NumberOfKeySymEvents-1]; for (i = 0; i < this->NumberOfKeySymEvents; i++) { if (strcmp(events[i].KeySym, old_keysym.c_str()) || events[i].Modifier != modifier || strcmp(events[i].Action, old_action.c_str())) { this->KeySymEvents[count].KeySym = new char[strlen(events[i].KeySym) + 1]; strcpy(this->KeySymEvents[count].KeySym, events[i].KeySym); delete [] events[i].KeySym; this->KeySymEvents[count].Modifier = events[i].Modifier; this->KeySymEvents[count].Action = new char[strlen(events[i].Action)+1]; strcpy(this->KeySymEvents[count].Action, events[i].Action); delete [] events[i].Action; if (events[i].Context) { this->KeySymEvents[count].Context = new char[strlen(events[i].Context)+1]; strcpy(this->KeySymEvents[count].Context, events[i].Context); delete [] events[i].Context; } else { this->KeySymEvents[count].Context = NULL; } if (events[i].Description) { this->KeySymEvents[count].Description = new char[strlen(events[i].Description)+1]; strcpy(this->KeySymEvents[count].Description, events[i].Description); delete [] events[i].Description; } else { this->KeySymEvents[count].Description = NULL; } count++; } } delete [] events; } this->NumberOfKeySymEvents--; } //---------------------------------------------------------------------------- const char* vtkKWEventMap::FindMouseAction(int button, int modifier) { if (this->MouseEvents) { int i; for (i = 0; i < this->NumberOfMouseEvents; i++) { if (this->MouseEvents[i].Button == button && this->MouseEvents[i].Modifier == modifier) { return this->MouseEvents[i].Action; } } } return NULL; } //---------------------------------------------------------------------------- const char* vtkKWEventMap::FindKeyAction(char key, int modifier) { if (this->KeyEvents) { int i; for (i = 0; i < this->NumberOfKeyEvents; i++) { if (this->KeyEvents[i].Key == key && this->KeyEvents[i].Modifier == modifier) { return this->KeyEvents[i].Action; } } } return NULL; } //---------------------------------------------------------------------------- const char* vtkKWEventMap::FindKeySymAction(const char *keySym, int modifier) { if (keySym && this->KeySymEvents) { int i; for (i = 0; i < this->NumberOfKeySymEvents; i++) { if (this->KeySymEvents[i].Modifier == modifier && ! strcmp(this->KeySymEvents[i].KeySym, keySym)) { return this->KeySymEvents[i].Action; } } } return NULL; } //---------------------------------------------------------------------------- vtkKWEventMap::MouseEvent* vtkKWEventMap::GetMouseEvent(int index) { if (index < 0 || index >= this->NumberOfMouseEvents) { return NULL; } return &this->MouseEvents[index]; } //---------------------------------------------------------------------------- vtkKWEventMap::KeyEvent* vtkKWEventMap::GetKeyEvent(int index) { if (index < 0 || index >= this->NumberOfKeyEvents) { return NULL; } return &this->KeyEvents[index]; } //---------------------------------------------------------------------------- vtkKWEventMap::KeySymEvent* vtkKWEventMap::GetKeySymEvent(int index) { if (index < 0 || index >= this->NumberOfKeySymEvents) { return NULL; } return &this->KeySymEvents[index]; } //---------------------------------------------------------------------------- void vtkKWEventMap::ShallowCopy(vtkKWEventMap *map) { if (!map || map == this) { return; } int i; this->RemoveAllMouseEvents(); for (i = 0; i < map->GetNumberOfMouseEvents(); i++) { this->AddMouseEvent(map->GetMouseEvent(i)); } this->RemoveAllKeyEvents(); for (i = 0; i < map->GetNumberOfKeyEvents(); i++) { this->AddKeyEvent(map->GetKeyEvent(i)); } this->RemoveAllKeySymEvents(); for (i = 0; i < map->GetNumberOfKeySymEvents(); i++) { this->AddKeySymEvent(map->GetKeySymEvent(i)); } } //---------------------------------------------------------------------------- void vtkKWEventMap::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "NumberOfMouseEvents: " << this->NumberOfMouseEvents << endl;; if (this->MouseEvents) { for (int i = 0; i < this->NumberOfMouseEvents; i++) { os << indent << " * "; if (this->MouseEvents[i].Modifier & vtkKWEventMap::ShiftModifier) { os << "Shift + "; } if (this->MouseEvents[i].Modifier & vtkKWEventMap::ControlModifier) { os << "Control + "; } switch (this->MouseEvents[i].Button) { case 0: os << "Left"; break; case 1: os << "Middle"; break; case 2: os << "Right"; break; } if (this->MouseEvents[i].Action) { os << " : " << this->MouseEvents[i].Action; } if (this->MouseEvents[i].Context) { os << " (" << this->MouseEvents[i].Context << ")"; } if (this->MouseEvents[i].Description) { os << " (" << this->MouseEvents[i].Description << ")"; } os << endl; } } os << indent << "NumberOfKeyEvents: " << this->NumberOfKeyEvents << endl;; if (this->KeyEvents) { for (int i = 0; i < this->NumberOfKeyEvents; i++) { os << indent << " * "; if (this->KeyEvents[i].Modifier & vtkKWEventMap::ShiftModifier) { os << "Shift + "; } if (this->KeyEvents[i].Modifier & vtkKWEventMap::ControlModifier) { os << "Control + "; } os << "'" << this->KeyEvents[i].Key << "'"; if (this->KeyEvents[i].Action) { os << " : " << this->KeyEvents[i].Action; } if (this->KeyEvents[i].Description) { os << " (" << this->KeyEvents[i].Description << ")"; } os << endl; } } os << indent << "NumberOfKeySymEvents: " << this->NumberOfKeySymEvents << endl;; if (this->KeySymEvents) { for (int i = 0; i < this->NumberOfKeySymEvents; i++) { os << indent << " * "; if (this->KeySymEvents[i].Modifier & vtkKWEventMap::ShiftModifier) { os << "Shift + "; } if (this->KeySymEvents[i].Modifier & vtkKWEventMap::ControlModifier) { os << "Control + "; } if (this->KeySymEvents[i].KeySym) { os << "'" << this->KeySymEvents[i].KeySym << "'"; } if (this->KeySymEvents[i].Action) { os << " : " << this->KeySymEvents[i].Action; } if (this->KeySymEvents[i].Description) { os << " (" << this->KeySymEvents[i].Description << ")"; } os << endl; } } } kwwidgets-1.0.0~cvs20100930/vtkKWSplitFrame.cxx0000644000175000017500000006413210754417147020662 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWSplitFrame.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWSplitFrame.h" #include "vtkKWFrame.h" #include "vtkObjectFactory.h" #include "vtkKWTkUtilities.h" #include "vtkKWPushButton.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" vtkStandardNewMacro( vtkKWSplitFrame ); vtkCxxRevisionMacro(vtkKWSplitFrame, "$Revision: 1.46 $"); //---------------------------------------------------------------------------- vtkKWSplitFrame::vtkKWSplitFrame() { this->Frame1 = vtkKWFrame::New(); this->SeparatorFrame = vtkKWFrame::New(); this->Frame2 = vtkKWFrame::New(); this->Separator = vtkKWFrame::New(); this->Expand1Button = vtkKWPushButton::New(); this->Expand2Button = vtkKWPushButton::New(); this->Frame1Size = 250; this->Frame2Size = 250; this->Frame1MinimumSize = 50; this->Frame2MinimumSize = 50; this->Frame1Visibility = 1; this->Frame2Visibility = 1; this->SeparatorSize = 4; this->SeparatorMargin = 2; this->SeparatorVisibility = 1; this->Size = this->Frame1Size + this->Frame2Size + this->GetTotalSeparatorSize(); this->Orientation = vtkKWSplitFrame::OrientationHorizontal; this->ExpandableFrame = vtkKWSplitFrame::ExpandableFrame2; this->FrameLayout = vtkKWSplitFrame::FrameLayoutDefault; } //---------------------------------------------------------------------------- vtkKWSplitFrame::~vtkKWSplitFrame() { this->RemoveBindings(); if (this->Frame1) { this->Frame1->Delete(); this->Frame1 = NULL; } if (this->SeparatorFrame) { this->SeparatorFrame->Delete(); this->SeparatorFrame = NULL; } if (this->Frame2) { this->Frame2->Delete(); this->Frame2 = NULL; } if (this->Separator) { this->Separator->Delete(); this->Separator = NULL; } if (this->Expand1Button) { this->Expand1Button->Delete(); this->Expand1Button = NULL; } if (this->Expand2Button) { this->Expand2Button->Delete(); this->Expand2Button = NULL; } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); this->SetConfigurationOptionAsInt("-width", 200); this->SetConfigurationOptionAsInt("-height", 100); this->Frame1->SetParent(this); this->Frame1->Create(); this->SeparatorFrame->SetParent(this); this->SeparatorFrame->Create(); this->Frame2->SetParent(this); this->Frame2->Create(); this->Separator->SetParent(this->SeparatorFrame); this->Separator->Create(); this->Separator->SetBorderWidth(2); this->Separator->SetReliefToRaised(); this->Expand1Button->SetParent(this->SeparatorFrame); this->Expand1Button->Create(); this->Expand1Button->SetBorderWidth(1); this->Expand1Button->SetReliefToFlat(); this->Expand1Button->SetOverReliefToRaised(); this->Expand1Button->SetCommand(this, "Expand1ButtonCallback"); this->Expand2Button->SetParent(this->SeparatorFrame); this->Expand2Button->Create(); this->Expand2Button->SetBorderWidth(1); this->Expand2Button->SetReliefToFlat(); this->Expand2Button->SetOverReliefToRaised(); this->Expand2Button->SetCommand(this, "Expand2ButtonCallback"); this->Pack(); this->AddBindings(); this->ConfigureSeparator(); this->ConfigureExpandButtons(); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::AddSeparatorBindings() { if (this->Separator) { this->Separator->SetBinding("", this, "DragCallback"); } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::RemoveSeparatorBindings() { if (this->Separator) { this->Separator->RemoveBinding(""); } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::AddBindings() { if (!this->IsAlive()) { return; } this->AddSeparatorBindings(); this->SetBinding("", this, "ConfigureCallback"); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::RemoveBindings() { if (!this->IsAlive()) { return; } this->RemoveSeparatorBindings(); this->RemoveBinding(""); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetOrientation(int val) { if (val < vtkKWSplitFrame::OrientationHorizontal) { val = vtkKWSplitFrame::OrientationHorizontal; } if (val > vtkKWSplitFrame::OrientationVertical) { val = vtkKWSplitFrame::OrientationVertical; } if (this->Orientation == val) { return; } this->Orientation = val; this->Modified(); this->ConfigureSeparator(); this->ConfigureExpandButtons(); // If we are created already, make sure we forget all layout settings. // This can't be done each time we Pack(), otherwise nasty flickers occur. if (this->IsCreated()) { this->Script("place forget %s", this->Frame1->GetWidgetName()); this->Script("place forget %s", this->SeparatorFrame->GetWidgetName()); this->Script("place forget %s", this->Frame2->GetWidgetName()); } this->ConfigureCallback(); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetFrameLayout(int val) { if (val < vtkKWSplitFrame::FrameLayoutDefault) { val = vtkKWSplitFrame::FrameLayoutDefault; } if (val > vtkKWSplitFrame::FrameLayoutSwapped) { val = vtkKWSplitFrame::FrameLayoutSwapped; } if (this->FrameLayout == val) { return; } this->FrameLayout = val; this->Modified(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::ConfigureSeparator() { if (!this->Separator || !this->Separator->IsCreated()) { return; } if (this->Frame1Visibility && this->Frame2Visibility) { #ifdef _WIN32 if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { this->Separator->SetConfigurationOption("-cursor", "size_we"); } else { this->Separator->SetConfigurationOption("-cursor", "size_ns"); } #else if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { this->Separator->SetConfigurationOption("-cursor", "sb_h_double_arrow"); } else { this->Separator->SetConfigurationOption("-cursor", "sb_v_double_arrow"); } #endif } else { this->Separator->SetConfigurationOption("-cursor", "dot"); } if (this->Frame1Visibility && this->Frame2Visibility && this->SeparatorVisibility) { this->AddSeparatorBindings(); } else { this->RemoveSeparatorBindings(); } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::ConfigureExpandButtons() { if (!this->Expand1Button || !this->Expand1Button->IsCreated() || !this->Expand2Button || !this->Expand2Button->IsCreated()) { return; } this->SeparatorFrame->UnpackChildren(); if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { this->Expand1Button->SetImageToPredefinedIcon( vtkKWIcon::IconExpandRightMini); this->Expand2Button->SetImageToPredefinedIcon( vtkKWIcon::IconExpandLeftMini); this->Script("pack %s %s -side top -expand n -fill both -pady 1", this->Expand2Button->GetWidgetName(), this->Expand1Button->GetWidgetName()); this->Script("pack %s -side top -expand y -fill both", this->Separator->GetWidgetName()); this->Expand1Button->SetBalloonHelpString( ks_("Split Frame|Expand right")); this->Expand2Button->SetBalloonHelpString( ks_("Split Frame|Expand left")); } else { this->Expand1Button->SetImageToPredefinedIcon( vtkKWIcon::IconExpandUpMini); this->Expand2Button->SetImageToPredefinedIcon( vtkKWIcon::IconExpandMini); this->Script("pack %s %s -side left -expand n -fill both -padx 1", this->Expand2Button->GetWidgetName(), this->Expand1Button->GetWidgetName()); this->Script("pack %s -side left -expand y -fill both", this->Separator->GetWidgetName()); this->Expand1Button->SetBalloonHelpString( ks_("Split Frame|Expand up")); this->Expand2Button->SetBalloonHelpString( ks_("Split Frame|Expand down")); } this->UpdateExpandButtonsEnableState(); } //---------------------------------------------------------------------------- int vtkKWSplitFrame::GetInternalMarginHorizontal() { return this->GetBorderWidth() + this->GetPadX(); } //---------------------------------------------------------------------------- int vtkKWSplitFrame::GetInternalMarginVertical() { return this->GetBorderWidth() + this->GetPadY(); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::ReConfigure() { if (this->IsCreated()) { this->Size = this->Frame1Size + this->Frame2Size + this->GetTotalSeparatorSize(); if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { int margin = this->GetInternalMarginHorizontal(); this->SetWidth(this->Size + margin * 2); } else { int margin = this->GetInternalMarginVertical(); this->SetHeight(this->Size + margin * 2); } } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::ConfigureCallback() { if (!this->IsCreated()) { return; } int tmp; int size; if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { vtkKWTkUtilities::GetWidgetSize(this, &size, NULL); size -= this->GetInternalMarginHorizontal() * 2; } else { vtkKWTkUtilities::GetWidgetSize(this, NULL, &size); size -= this->GetInternalMarginVertical() * 2; } // If size == 1 then the widget has not been packed, it will be later // and the event will bring us back here with the correct size if (size <= 1) { return; } // First check to see if we have to make the window larger. tmp = this->Frame1MinimumSize + this->Frame2MinimumSize + this->GetTotalSeparatorSize(); if (size < tmp) { this->Frame1Size = this->Frame1MinimumSize; this->Frame2Size = this->Frame2MinimumSize; this->ReConfigure(); this->Pack(); return; } // Size of second frame // Adjust the first frame size if needed if (this->ExpandableFrame == vtkKWSplitFrame::ExpandableFrame2) { tmp = size - this->Frame1Size - this->GetTotalSeparatorSize(); if (tmp < this->Frame2MinimumSize) { tmp = this->Frame2MinimumSize; this->Frame1Size = size - this->Frame2Size-this->GetTotalSeparatorSize(); } this->Frame2Size = tmp; } else if (this->ExpandableFrame == vtkKWSplitFrame::ExpandableFrame1) { tmp = size - this->Frame2Size - this->GetTotalSeparatorSize(); if (tmp < this->Frame1MinimumSize) { tmp = this->Frame1MinimumSize; this->Frame2Size = size - this->Frame1Size-this->GetTotalSeparatorSize(); } this->Frame1Size = tmp; } else { tmp = size - this->Size; int frame1size = this->Frame1Size + tmp / 2; int frame2size = this->Frame2Size + (tmp - tmp / 2); if (frame1size < this->Frame1MinimumSize) { frame2size -= (this->Frame1MinimumSize - frame1size); frame1size = this->Frame1MinimumSize; } if (frame2size < this->Frame2MinimumSize) { frame1size -= (this->Frame2MinimumSize - frame2size); frame2size = this->Frame2MinimumSize; } this->Frame1Size = frame1size; this->Frame2Size = frame2size; } this->Size = size; this->Pack(); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::DragCallback() { int size, s, smin, tmp; if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { vtkKWTkUtilities::GetWidgetSize(this, &size, NULL); size -= this->GetInternalMarginHorizontal() * 2; } else { vtkKWTkUtilities::GetWidgetSize(this, NULL, &size); size -= this->GetInternalMarginVertical() * 2; } this->Size = size; // Get the position of the widget in screen if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { vtkKWTkUtilities::GetWidgetCoordinates(this, &smin, NULL); } else { vtkKWTkUtilities::GetWidgetCoordinates(this, NULL, &smin); } // Get the position of the mouse in screen if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { vtkKWTkUtilities::GetMousePointerCoordinates(this, &s, NULL); } else { vtkKWTkUtilities::GetMousePointerCoordinates(this, NULL, &s); } // Relative position. s -= smin; // Constraints on the window. int half_sep_size1 = this->GetTotalSeparatorSize() / 2; int half_sep_size2 = this->GetTotalSeparatorSize() - half_sep_size1; int frame1_new_size, frame2_new_size; int frame1_min_size, frame2_min_size; if (this->FrameLayout == vtkKWSplitFrame::FrameLayoutDefault) { frame1_min_size = this->Frame1MinimumSize; frame2_min_size = this->Frame2MinimumSize; } else { frame1_min_size = this->Frame2MinimumSize; frame2_min_size = this->Frame1MinimumSize; } if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { tmp = frame1_min_size + half_sep_size1; if (s < tmp) { s = tmp; } tmp = size - frame2_min_size - half_sep_size2; if (s > tmp) { s = tmp; } frame1_new_size = s - half_sep_size1; frame2_new_size = size - s - half_sep_size2; } else { tmp = frame2_min_size + half_sep_size2; if (s < tmp) { s = tmp; } tmp = size - frame1_min_size - half_sep_size1; if (s > tmp) { s = tmp; } frame2_new_size = s - half_sep_size2; frame1_new_size = size - s - half_sep_size1; } if (this->FrameLayout == vtkKWSplitFrame::FrameLayoutDefault) { this->Frame1Size = frame1_new_size; this->Frame2Size = frame2_new_size; } else { this->Frame1Size = frame2_new_size; this->Frame2Size = frame1_new_size; } this->Pack(); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::Expand1ButtonCallback() { if (this->FrameLayout == vtkKWSplitFrame::FrameLayoutDefault) { if (this->GetFrame1Visibility()) { this->Frame2VisibilityOff(); } this->Frame1VisibilityOn(); } else { if (this->GetFrame2Visibility()) { this->Frame1VisibilityOff(); } this->Frame2VisibilityOn(); } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::Expand2ButtonCallback() { if (this->FrameLayout == vtkKWSplitFrame::FrameLayoutDefault) { if (this->GetFrame2Visibility()) { this->Frame1VisibilityOff(); } this->Frame2VisibilityOn(); } else { if (this->GetFrame1Visibility()) { this->Frame2VisibilityOff(); } this->Frame1VisibilityOn(); } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetFrame1MinimumSize(int minSize) { if (this->Frame1MinimumSize == minSize) { return; } this->Frame1MinimumSize = minSize; if (this->Frame1Size < this->Frame1MinimumSize) { this->SetFrame1Size(this->Frame1MinimumSize); } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetFrame1Size(int size) { if (this->Frame1Size == size) { return; } this->Frame1Size = size; this->Frame2Size = this->Size - this->Frame1Size - this->GetTotalSeparatorSize(); if (this->Frame2Size < this->Frame2MinimumSize) { this->Frame2Size = this->Frame2MinimumSize; this->ReConfigure(); } this->Pack(); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetFrame2MinimumSize(int minSize) { if (this->Frame2MinimumSize == minSize) { return; } this->Frame2MinimumSize = minSize; if (this->Frame2Size < this->Frame2MinimumSize) { this->SetFrame2Size(this->Frame2MinimumSize); } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetFrame2Size(int size) { if (this->Frame2Size == size) { return; } this->Frame2Size = size; this->Frame1Size = this->Size - this->Frame2Size - this->GetTotalSeparatorSize(); if (this->Frame1Size < this->Frame1MinimumSize) { this->Frame1Size = this->Frame1MinimumSize; this->ReConfigure(); } this->Pack(); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetSeparatorPosition(double pos) { if (pos < 0.0) { pos = 0.0; } if (pos > 1.0) { pos = 1.0; } if (this->GetSeparatorPosition() == pos) { return; } double total_size = (double)(this->GetFrame1Size() + this->GetFrame2Size()); this->SetFrame1Size((int)(pos * total_size)); } //---------------------------------------------------------------------------- double vtkKWSplitFrame::GetSeparatorPosition() { int total_size = this->GetFrame1Size() + this->GetFrame2Size(); if (total_size) { return (double)this->GetFrame1Size() / (double)total_size; } return 0.0; } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetSeparatorSize(int size) { if (this->SeparatorSize == size) { return; } this->SeparatorSize = size; this->SetFrame1Size(this->Frame1Size); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetSeparatorMargin(int size) { if (this->SeparatorMargin == size) { return; } this->SeparatorMargin = size; this->SetFrame1Size(this->Frame1Size); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetSeparatorVisibility(int flag) { if (this->SeparatorVisibility == flag) { return; } this->SeparatorVisibility = flag; this->Modified(); this->Pack(); this->ConfigureSeparator(); } //---------------------------------------------------------------------------- int vtkKWSplitFrame::GetTotalSeparatorSize() { return this->SeparatorMargin * 2 + this->SeparatorSize; } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetFrame1Visibility(int flag) { if (this->Frame1Visibility == flag) { return; } this->Frame1Visibility = flag; this->Modified(); this->ConfigureSeparator(); this->ConfigureExpandButtons(); this->Pack(); this->InvokeEvent(vtkKWSplitFrame::FrameVisibilityChangedEvent); this->InvokeEvent(vtkKWSplitFrame::Frame1VisibilityChangedEvent); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::SetFrame2Visibility(int flag) { if (this->Frame2Visibility == flag) { return; } this->Frame2Visibility = flag; this->Modified(); this->ConfigureSeparator(); this->ConfigureExpandButtons(); this->Pack(); this->InvokeEvent(vtkKWSplitFrame::FrameVisibilityChangedEvent); this->InvokeEvent(vtkKWSplitFrame::Frame2VisibilityChangedEvent); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::Pack() { if (!this->IsCreated()) { return; } int total_separator_size, separator_size, separator_margin; int frame1_size, frame2_size; int frame1_visibility = this->Frame1Visibility; int frame2_visibility = this->Frame2Visibility; vtkKWFrame *frame1 = this->Frame1; vtkKWFrame *frame2 = this->Frame2; // Compute the real size of each element, given the visibility parameters int remaining = 0; if (this->SeparatorVisibility) { separator_size = this->SeparatorSize; separator_margin = this->SeparatorMargin; total_separator_size = this->GetTotalSeparatorSize(); } else { separator_size = 0; separator_margin = 0; total_separator_size = 0; remaining = this->GetTotalSeparatorSize() - total_separator_size; } frame1_size = this->Frame1Size + (remaining / 2); frame2_size = this->Frame2Size + (remaining - remaining / 2); if (!frame1_visibility) { if (frame2_visibility) { frame2_size += frame1_size; } frame1_size = 0; } if (!frame2_visibility) { if (frame1_visibility) { frame1_size += frame2_size; } frame2_size = 0; } int margin_h = 0; // this->GetInternalMarginHorizontal(); int margin_v = 0; // this->GetInternalMarginVertical(); // If we are swapped, switch Frame1 and Frame2 if (this->FrameLayout == vtkKWSplitFrame::FrameLayoutSwapped) { int temp; temp = frame1_size; frame1_size = frame2_size; frame2_size = temp; temp = frame1_visibility; frame1_visibility = frame2_visibility; frame2_visibility = temp; frame1 = this->Frame2; frame2 = this->Frame1; } // Frame 1 if (frame1_visibility) { if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { this->Script("place %s -x %d -y %d -width %d -relheight 1.0 -height -%d", frame1->GetWidgetName(), margin_h, margin_v, frame1_size, margin_v * 2); } else { this->Script("place %s -x %d -y %d -height %d -relwidth 1.0 -width -%d", frame1->GetWidgetName(), margin_h, margin_v + frame2_size + total_separator_size, frame1_size, margin_h * 2); } } else { this->Script("place forget %s", frame1->GetWidgetName()); } // Separator if (this->SeparatorVisibility) { if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { this->Script("place %s -x %d -y %d -width %d -relheight 1.0 -height -%d", this->SeparatorFrame->GetWidgetName(), margin_h + frame1_size + separator_margin, margin_v, separator_size, margin_v * 2); } else { this->Script("place %s -x %d -y %d -height %d -relwidth 1.0 -width -%d", this->SeparatorFrame->GetWidgetName(), margin_h, margin_v + frame2_size + separator_margin, separator_size, margin_h * 2); } } else { this->Script("place forget %s", this->SeparatorFrame->GetWidgetName()); } // Frame 2 if (frame2_visibility) { if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { this->Script("place %s -x %d -y %d -width %d -relheight 1.0 -height -%d", frame2->GetWidgetName(), margin_h + frame1_size + total_separator_size, margin_v, frame2_size, margin_v * 2); } else { this->Script("place %s -x %d -y %d -height %d -relwidth 1.0 -width -%d", frame2->GetWidgetName(), margin_h, margin_v, frame2_size, margin_h * 2); } } else { this->Script("place forget %s", frame2->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->Frame1); this->PropagateEnableState(this->SeparatorFrame); this->PropagateEnableState(this->Frame2); this->PropagateEnableState(this->Separator); this->UpdateExpandButtonsEnableState(); } //---------------------------------------------------------------------------- void vtkKWSplitFrame::UpdateExpandButtonsEnableState() { if (this->FrameLayout == vtkKWSplitFrame::FrameLayoutDefault) { this->Expand1Button->SetEnabled( this->Frame2Visibility ? this->GetEnabled() : 0); this->Expand2Button->SetEnabled( this->Frame1Visibility ? this->GetEnabled() : 0); } else { this->Expand1Button->SetEnabled( this->Frame1Visibility ? this->GetEnabled() : 0); this->Expand2Button->SetEnabled( this->Frame2Visibility ? this->GetEnabled() : 0); } } //---------------------------------------------------------------------------- void vtkKWSplitFrame::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Frame1MinimumSize: " << this->GetFrame1MinimumSize() << endl; os << indent << "Frame1Size: " << this->GetFrame1Size() << endl; os << indent << "Frame1Visibility: " << (this->Frame1Visibility ? "On" : "Off") << endl; os << indent << "Frame2MinimumSize: " << this->GetFrame2MinimumSize() << endl; os << indent << "Frame2Size: " << this->GetFrame2Size() << endl; os << indent << "Frame2Visibility: " << (this->Frame2Visibility ? "On" : "Off") << endl; os << indent << "SeparatorSize: " << this->GetSeparatorSize() << endl; os << indent << "SeparatorMargin: " << this->GetSeparatorMargin() << endl; os << indent << "SeparatorVisibility: " << (this->SeparatorVisibility ? "On" : "Off") << endl; if (this->Orientation == vtkKWSplitFrame::OrientationHorizontal) { os << indent << "Orientation: Horizontal\n"; } else { os << indent << "Orientation: Vertical\n"; } os << indent << "ExpandableFrame: " << this->GetExpandableFrame() << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWWin32RegistryHelper.cxx0000644000175000017500000001362110661347105022375 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWWin32RegistryHelper.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWWin32RegistryHelper.h" #include "vtkObjectFactory.h" #include #include #include vtkCxxRevisionMacro(vtkKWWin32RegistryHelper, "$Revision: 1.7 $"); vtkStandardNewMacro( vtkKWWin32RegistryHelper ); #define BUFFER_SIZE 8192 //---------------------------------------------------------------------------- vtkKWWin32RegistryHelper::vtkKWWin32RegistryHelper() { this->HKey = 0; this->Organization = 0; this->SetOrganization("Kitware"); } //---------------------------------------------------------------------------- vtkKWWin32RegistryHelper::~vtkKWWin32RegistryHelper() { this->SetOrganization(0); } //---------------------------------------------------------------------------- int vtkKWWin32RegistryHelper::OpenInternal(const char *toplevel, const char *subkey, int readonly) { int res = 0; vtksys_ios::ostringstream str; if ( this->GetGlobalScope() ) { str << "HKEY_LOCAL_MACHINE\\"; } else { str << "HKEY_CURRENT_USER\\"; } str << "Software\\"; if (this->Organization) { str << this->Organization << "\\"; } str << toplevel << "\\" << subkey; res = this->OpenInternal(str.str().c_str(), readonly); return res; } //---------------------------------------------------------------------------- int vtkKWWin32RegistryHelper::OpenInternal(const char *key, int readonly) { int res = 0; vtksys_stl::string primary = key; vtksys_stl::string second; size_t start = primary.find("\\"); if (start == vtksys_stl::string::npos) { return res; } second = primary.substr(start+1, primary.length()-start-1); primary = primary.substr(0, start); HKEY primaryKey = HKEY_CURRENT_USER; if (primary == "HKEY_CURRENT_CONFIG") { primaryKey = HKEY_CURRENT_CONFIG; } else if (primary == "HKEY_CLASSES_ROOT") { primaryKey = HKEY_CLASSES_ROOT; } else if (primary == "HKEY_LOCAL_MACHINE") { primaryKey = HKEY_LOCAL_MACHINE; } else if (primary == "HKEY_USERS") { primaryKey = HKEY_USERS; } DWORD dwDummy; if ( readonly == vtkKWRegistryHelper::ReadOnly ) { res = ( RegOpenKeyEx(primaryKey, second.c_str(), 0, KEY_READ, &this->HKey) == ERROR_SUCCESS ); } else { res = ( RegCreateKeyEx(primaryKey, second.c_str(), 0, "", REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &this->HKey, &dwDummy) == ERROR_SUCCESS ); } return res; } //---------------------------------------------------------------------------- int vtkKWWin32RegistryHelper::CloseInternal() { int res; res = ( RegCloseKey(this->HKey) == ERROR_SUCCESS ); return res; } //---------------------------------------------------------------------------- int vtkKWWin32RegistryHelper::ReadValueInternal(const char *key, char *value) { int res = 1; DWORD dwType, dwSize; dwType = REG_SZ; dwSize = BUFFER_SIZE; char data[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; data[0] = 0; res = ( RegQueryValueEx(this->HKey, key, NULL, &dwType, (BYTE *)data, &dwSize) == ERROR_SUCCESS ); if (res) { if (dwType == REG_SZ) { strcpy(value, data); } else if(dwType == REG_DWORD) { int dwBuff; res = this->ReadValueInternal(key, &dwBuff); sprintf(value, "%d", dwBuff); } } return res; } //---------------------------------------------------------------------------- int vtkKWWin32RegistryHelper::ReadValueInternal(const char *key, int *value) { int res = 1; DWORD dwType, dwSize; dwType = REG_DWORD; dwSize = sizeof(DWORD); res = ( RegQueryValueEx(this->HKey, key, NULL, &dwType, (LPBYTE)value, &dwSize) == ERROR_SUCCESS ); return res; } //---------------------------------------------------------------------------- int vtkKWWin32RegistryHelper::DeleteKeyInternal(const char *key) { int res = 1; res = ( RegDeleteKey( this->HKey, key ) == ERROR_SUCCESS ); return res; } //---------------------------------------------------------------------------- int vtkKWWin32RegistryHelper::DeleteValueInternal(const char *key) { int res = 1; res = ( RegDeleteValue( this->HKey, key ) == ERROR_SUCCESS ); return res; } //---------------------------------------------------------------------------- int vtkKWWin32RegistryHelper::SetValueInternal(const char *key, const char *value) { int res = 1; DWORD len = (DWORD)(value ? strlen(value) : 0); res = ( RegSetValueEx(this->HKey, key, 0, REG_SZ, (CONST BYTE *)(const char *)value, len+1) == ERROR_SUCCESS ); return res; } //---------------------------------------------------------------------------- int vtkKWWin32RegistryHelper::SetValueInternal(const char *key, int *value) { int res = 1; res = ( RegSetValueEx(this->HKey, key, 0, REG_DWORD, (PBYTE)value, sizeof(DWORD)) == ERROR_SUCCESS ); return res; } //---------------------------------------------------------------------------- void vtkKWWin32RegistryHelper::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWLogWidget.cxx0000644000175000017500000006536311101670551020473 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWLogWidget.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWLogWidget.h" #include "vtkKWApplication.h" #include "vtkKWEvent.h" #include "vtkKWFrameWithLabel.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" #include "vtkKWLoadSaveButton.h" #include "vtkKWLoadSaveDialog.h" #include "vtkKWMessage.h" #include "vtkKWMessageDialog.h" #include "vtkKWMultiColumnList.h" #include "vtkKWMultiColumnListWithScrollbars.h" #include "vtkKWPushButton.h" #include "vtkKWText.h" #include "vtkKWTextWithScrollbars.h" #include "vtkKWTkUtilities.h" #include "vtkKWToolbar.h" #include "vtkObjectFactory.h" #include #include #include #include #include #define MAX_NUMBER_OF_RECORDS 5000 #define MIN_NUMBER_OF_RECORDS 1 //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWLogWidget ); vtkCxxRevisionMacro(vtkKWLogWidget, "$Revision: 1.15 $"); vtkIdType vtkKWLogWidget::IdCounter = 1; //---------------------------------------------------------------------------- class vtkKWLogWidgetInternals { public: // A struct to store an record info struct Record { vtkIdType Id; int Type; unsigned int Time; vtksys_stl::string Description; }; typedef vtksys_stl::list RecordContainerType; typedef vtksys_stl::list::iterator RecordContainerIterator; RecordContainerType RecordContainer; vtksys_stl::string ErrorImage; vtksys_stl::string WarningImage; vtksys_stl::string InformationImage; vtksys_stl::string DebugImage; }; //---------------------------------------------------------------------------- vtkKWLogWidget::vtkKWLogWidget() { this->Internals = new vtkKWLogWidgetInternals; this->Toolbar = NULL; this->RecordList = NULL; this->SaveButton = NULL; this->RemoveSelectedButton = NULL; this->RemoveAllButton = NULL; this->EmailButton = NULL; this->DescriptionFrame = NULL; this->DescriptionText = NULL; this->MaximumNumberOfRecords = 200; } //---------------------------------------------------------------------------- vtkKWLogWidget::~vtkKWLogWidget() { if (this->Internals) { delete this->Internals; } if (this->RecordList) { this->RecordList->Delete(); } if (this->SaveButton) { this->SaveButton->Delete(); } if (this->RemoveSelectedButton) { this->RemoveSelectedButton->Delete(); } if (this->RemoveAllButton) { this->RemoveAllButton->Delete(); } if (this->EmailButton) { this->EmailButton->Delete(); } if (this->DescriptionFrame) { this->DescriptionFrame->Delete(); } if (this->DescriptionText) { this->DescriptionText->Delete(); } if (this->Toolbar) { this->Toolbar->Delete(); } } //---------------------------------------------------------------------------- void vtkKWLogWidget::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro(<< this->GetClassName() << " already created"); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); this->CreateRecordList(); vtkKWIcon *icon = vtkKWIcon::New(); this->Internals->WarningImage = this->RecordList->GetWidget()->GetWidgetName(); this->Internals->WarningImage.append("_warning"); icon->SetImage(vtkKWIcon::IconNuvola16x16ActionsMessageBoxWarning); if (!vtkKWTkUtilities::UpdatePhoto( this->GetApplication(), this->Internals->WarningImage.c_str(), icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize())) { vtkWarningMacro( << "Error updating Tk photo " << this->Internals->WarningImage.c_str()); } this->Internals->ErrorImage = this->RecordList->GetWidget()->GetWidgetName(); this->Internals->ErrorImage.append("_error"); icon->SetImage(vtkKWIcon::IconNuvola16x16ActionsNo); if (!vtkKWTkUtilities::UpdatePhoto( this->GetApplication(), this->Internals->ErrorImage.c_str(), icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize())) { vtkWarningMacro( << "Error updating Tk photo " << this->Internals->ErrorImage.c_str()); } this->Internals->InformationImage = this->RecordList->GetWidget()->GetWidgetName(); this->Internals->InformationImage.append("_info"); icon->SetImage(vtkKWIcon::IconNuvola16x16ActionsMessageBoxInfo); if (!vtkKWTkUtilities::UpdatePhoto( this->GetApplication(), this->Internals->InformationImage.c_str(), icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize())) { vtkWarningMacro( << "Error updating Tk photo " << this->Internals->InformationImage.c_str()); } this->Internals->DebugImage = this->RecordList->GetWidget()->GetWidgetName(); this->Internals->DebugImage.append("_debug"); icon->SetImage(vtkKWIcon::IconNuvola16x16AppsBug); if (!vtkKWTkUtilities::UpdatePhoto( this->GetApplication(), this->Internals->DebugImage.c_str(), icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize())) { vtkWarningMacro( << "Error updating Tk photo " << this->Internals->DebugImage.c_str()); } icon->Delete(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWLogWidget::CreateRecordList() { if (!this->IsCreated()) { return; } // Setup toolbar if (!this->Toolbar) { this->Toolbar = vtkKWToolbar::New(); } this->Toolbar->SetParent(this); this->Toolbar->Create(); this->Toolbar->SetToolbarAspectToFlat(); this->Toolbar->SetWidgetsAspectToFlat(); // Save Button if (!this->SaveButton) { this->SaveButton = vtkKWLoadSaveButton::New(); } this->SaveButton->SetParent(this->Toolbar->GetFrame()); this->SaveButton->Create(); this->SaveButton->SetImageToPredefinedIcon( vtkKWIcon::IconNuvola16x16ActionsFileSave); this->SaveButton->SetBalloonHelpString("Write records to a text file"); this->SaveButton->SetCommand(this, "WriteRecordsToFileCallback"); this->SaveButton->GetLoadSaveDialog()->SaveDialogOn(); this->SaveButton->GetLoadSaveDialog()->SetDefaultExtension(".txt"); this->SaveButton->GetLoadSaveDialog()->SetFileTypes("{ {Text} {*.txt} }"); this->SaveButton->GetLoadSaveDialog()->RetrieveLastPathFromRegistry( "OpenPath"); this->Toolbar->AddWidget(this->SaveButton); // Remove Selected Button if (!this->RemoveSelectedButton) { this->RemoveSelectedButton = vtkKWPushButton::New(); } this->RemoveSelectedButton->SetParent(this->Toolbar->GetFrame()); this->RemoveSelectedButton->Create(); this->RemoveSelectedButton->SetImageToPredefinedIcon( vtkKWIcon::IconFileDelete); this->RemoveSelectedButton->SetBalloonHelpString( "Remove selected records (or press the key)"); this->RemoveSelectedButton->SetCommand( this, "RemoveSelectedRecordsCallback"); this->Toolbar->AddWidget(this->RemoveSelectedButton); // Remove All Button if (!this->RemoveAllButton) { this->RemoveAllButton = vtkKWPushButton::New(); } this->RemoveAllButton->SetParent(this->Toolbar->GetFrame()); this->RemoveAllButton->Create(); this->RemoveAllButton->SetImageToPredefinedIcon( vtkKWIcon::IconCrystalProject16x16Actions14LayerDeletelayer); this->RemoveAllButton->SetBalloonHelpString("Clear all records"); this->RemoveAllButton->SetCommand(this, "RemoveAllRecordsCallback"); this->Toolbar->AddWidget(this->RemoveAllButton); this->Script("pack %s -side top -anchor nw -padx 0 -pady 0", this->Toolbar->GetWidgetName()); // Email Button if (!this->EmailButton) { this->EmailButton = vtkKWPushButton::New(); } this->EmailButton->SetParent(this->Toolbar->GetFrame()); this->EmailButton->Create(); this->EmailButton->SetImageToPredefinedIcon( vtkKWIcon::IconNuvola16x16AppsEmail); this->EmailButton->SetBalloonHelpString("Email all records"); this->EmailButton->SetCommand(this, "EmailRecordsCallback"); this->Toolbar->AddWidget(this->EmailButton); this->Script("pack %s -side top -anchor nw -padx 0 -pady 0", this->Toolbar->GetWidgetName()); // Setup multicolumn list if (!this->RecordList) { this->RecordList = vtkKWMultiColumnListWithScrollbars::New(); } this->RecordList->SetParent(this); this->RecordList->Create(); vtkKWMultiColumnList *tablelist = this->RecordList->GetWidget(); tablelist->MovableColumnsOn(); tablelist->SetWidth(0); tablelist->SetHeight(13); tablelist->ExportSelectionOff(); tablelist->SetColumnSeparatorsVisibility(0); tablelist->SetStripeHeight(0); tablelist->ColorSortedColumnOn(); tablelist->ClearStripeBackgroundColor(); tablelist->SetRowSpacing(0); tablelist->SetSelectionModeToExtended(); tablelist->SetBinding("", this, "RemoveSelectedRecordsCallback"); tablelist->SetSelectionChangedCommand(this, "SelectionChangedCallback"); int col_index; col_index = tablelist->AddColumn("ID"); tablelist->SetColumnVisibility(col_index, 0); col_index = tablelist->AddColumn("Type"); col_index = tablelist->AddColumn("Time"); tablelist->SetColumnAlignmentToRight(col_index); tablelist->SetColumnFormatCommand( col_index, this, "GetFormatTimeStringCallback"); tablelist->SetColumnSortModeToInteger(col_index); col_index = tablelist->AddColumn("Description"); for (int i = 0; i < tablelist->GetNumberOfColumns(); i++) { tablelist->SetColumnEditable(i, 0); } this->Script( "pack %s -side top -fill both -expand true -padx 0 -pady 2", this->RecordList->GetWidgetName()); // Description Text Frame if (!this->DescriptionFrame) { this->DescriptionFrame = vtkKWFrameWithLabel::New(); } this->DescriptionFrame->SetParent(this); this->DescriptionFrame->Create(); this->DescriptionFrame->SetLabelText("Selected Record Description"); this->Script("pack %s -side top -anchor nw -fill x -padx 0 -pady 0", this->DescriptionFrame->GetWidgetName()); // Description Text Box if (!this->DescriptionText) { this->DescriptionText = vtkKWTextWithScrollbars::New(); } this->DescriptionText->SetParent(this->DescriptionFrame->GetFrame()); this->DescriptionText->Create(); this->DescriptionText->GetWidget()->SetHeight(8); this->DescriptionText->GetWidget()->SetReadOnly(1); this->Script("pack %s -side top -fill both -expand true", this->DescriptionText->GetWidgetName()); } //---------------------------------------------------------------------------- int vtkKWLogWidget::AddErrorRecord(const char* description) { this->InvokeEvent(vtkKWEvent::ErrorMessageEvent, (void*)description); return this->AddRecord(description, vtkKWLogWidget::ErrorType); } //---------------------------------------------------------------------------- int vtkKWLogWidget::AddWarningRecord(const char* description) { this->InvokeEvent(vtkKWEvent::WarningMessageEvent, (void*)description); return this->AddRecord(description, vtkKWLogWidget::WarningType); } //---------------------------------------------------------------------------- int vtkKWLogWidget::AddInformationRecord(const char* description) { this->InvokeEvent(vtkKWEvent::InformationMessageEvent, (void*)description); return this->AddRecord(description, vtkKWLogWidget::InformationType); } //---------------------------------------------------------------------------- int vtkKWLogWidget::AddDebugRecord(const char* description) { this->InvokeEvent(vtkKWEvent::DebugMessageEvent, (void*)description); return this->AddRecord(description, vtkKWLogWidget::DebugType); } //---------------------------------------------------------------------------- int vtkKWLogWidget::GetNumberOfRecords() { if (this->Internals) { return (int)this->Internals->RecordContainer.size(); } return 0; } //---------------------------------------------------------------------------- void vtkKWLogWidget::RemoveAllRecords() { int nb_records = this->GetNumberOfRecords(); if (this->Internals) { this->Internals->RecordContainer.clear(); } if (this->RecordList && this->RecordList->IsCreated() && this->RecordList->GetWidget()->GetNumberOfRows()) { this->RecordList->GetWidget()->DeleteAllRows(); } if (this->DescriptionText && this->DescriptionText->IsCreated()) { this->DescriptionText->GetWidget()->SetText(""); } if (nb_records && !this->GetNumberOfRecords()) { this->InvokeEvent(vtkKWLogWidget::RecordsClearedEvent, NULL); } this->Update(); } //---------------------------------------------------------------------------- unsigned int vtkKWLogWidget::GetCurrentTimeInSeconds() { time_t rawtime; time(&rawtime ); return rawtime; } //---------------------------------------------------------------------------- void vtkKWLogWidget::WriteRecordsToFileCallback() { if (this->SaveButton && this->SaveButton->IsCreated()) { this->SaveButton->SetText(NULL); if (this->SaveButton->GetLoadSaveDialog()->GetStatus() == vtkKWDialog::StatusOK) { this->SaveButton->GetLoadSaveDialog()->SaveLastPathToRegistry( "OpenPath"); this->WriteRecordsToFile(this->SaveButton->GetFileName()); } } } //---------------------------------------------------------------------------- void vtkKWLogWidget::EmailRecordsCallback() { this->EmailRecords(this->GetApplication()->GetEmailFeedbackAddress()); } //---------------------------------------------------------------------------- int vtkKWLogWidget::WriteRecordsToStream(ostream& os) { if (!this->RecordList || !this->RecordList->IsCreated()) { return 0; } // Write all records vtkKWMultiColumnList *record_list = this->RecordList->GetWidget(); int numrows = record_list->GetNumberOfRows(); for (int i = 0; i < numrows; i++) { os << "Type: " << record_list->GetCellText(i, 1) << endl; os << "Time: " << this->GetFormatTimeStringCallback( record_list->GetCellText(i, 2)) << endl; os << "Description: " << this->GetRecordDescription( record_list->GetCellTextAsInt(i, 0)) << endl << endl; } return 1; } //---------------------------------------------------------------------------- int vtkKWLogWidget::WriteRecordsToFile(const char* filename) { // Make sure the user specified a filename if (!filename || !(*filename)) { vtkErrorMacro(<< "Please specify a valid file name!"); return 0; } // Open text file ofstream fout(filename, ios::out | ios::trunc); if (fout.fail()) { vtkWarningMacro(<< "Unable to open file to write: " << filename); return 0; } // Write all records int res = this->WriteRecordsToStream(fout); fout.close(); return res; } //---------------------------------------------------------------------------- int vtkKWLogWidget::EmailRecords(const char *recipient) { vtksys_ios::ostringstream email_subject; this->GetApplication()->AddEmailFeedbackSubject(email_subject); vtksys_ios::ostringstream message; this->GetApplication()->AddEmailFeedbackBody(message); message << endl; this->WriteRecordsToStream(message); return this->GetApplication()->SendEmail( recipient, email_subject.str().c_str(), message.str().c_str(), NULL, NULL); } //---------------------------------------------------------------------------- // Some buggy versions of gcc complain about the use of %c: warning: `%c' // yields only last 2 digits of year in some locales. Of course program- // mers are encouraged to use %c, it gives the preferred date and time // representation. One meets all kinds of strange obfuscations to circum- // vent this gcc problem. A relatively clean one is to add an intermediate // function. This is described as bug #3190 in gcc bugzilla: // [-Wformat-y2k doesn't belong to -Wall - it's hard to avoid] inline size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) { return strftime(s, max, fmt, tm); } //---------------------------------------------------------------------------- char* vtkKWLogWidget::GetFormatTimeStringCallback(const char* celltext) { if (celltext && *celltext) { time_t t = 0; t = atol(celltext); // sscanf(celltext, "%lu", &t); struct tm *new_time = localtime(&t); static char buffer[256]; my_strftime(buffer, 256, "%c", new_time); return buffer; } return NULL; } //---------------------------------------------------------------------------- void vtkKWLogWidget::RemoveAllRecordsCallback() { if (this->IsCreated() && this->RecordList->GetWidget()->GetNumberOfRows()>0) { if (vtkKWMessageDialog::PopupYesNo( this->GetApplication(), this, ks_("Record Widget|Title|Delete All Records?"), k_("Are you sure you want to delete all records?"), vtkKWMessageDialog::WarningIcon)) { this->RemoveAllRecords(); } } } //---------------------------------------------------------------------------- void vtkKWLogWidget::RemoveSelectedRecordsCallback() { if (this->IsCreated() && this->RecordList->GetWidget()->GetNumberOfSelectedRows()>0) { if (vtkKWMessageDialog::PopupYesNo( this->GetApplication(), this, "RemoveSelectedLogRecords", ks_("Record Widget|Title|Delete Selected Records?"), k_("Are you sure you want to delete the selected records?"), vtkKWMessageDialog::WarningIcon | vtkKWMessageDialog::RememberYes)) { vtkKWMultiColumnList *record_list = this->RecordList->GetWidget(); int nb_selected_rows = record_list->GetNumberOfSelectedRows(); int *indices = new int [nb_selected_rows]; nb_selected_rows = record_list->GetSelectedRows(indices); for (int i = nb_selected_rows - 1; i >= 0; i--) { this->RemoveInternalRecord( record_list->GetCellTextAsInt(indices[i], 0)); record_list->DeleteRow(indices[i]); } int nb_rows = record_list->GetNumberOfRows(); record_list->SelectSingleRow( indices[0] >= nb_rows ? nb_rows - 1 : indices[0]); delete [] indices; this->Update(); this->DescriptionText->GetWidget()->SetText(""); if (!this->GetNumberOfRecords()) { this->InvokeEvent(vtkKWLogWidget::RecordsClearedEvent, NULL); } } } } //---------------------------------------------------------------------------- const char* vtkKWLogWidget::GetRecordDescription(int record_id) { if (this->Internals->RecordContainer.size()>0) { vtkKWLogWidgetInternals::RecordContainerIterator it = this->Internals->RecordContainer.begin(); vtkKWLogWidgetInternals::RecordContainerIterator end = this->Internals->RecordContainer.end(); for (; it!=end; it++) { if ((*it).Id == record_id) { return (*it).Description.c_str(); } } } return NULL; } //---------------------------------------------------------------------------- void vtkKWLogWidget::RemoveInternalRecord(int record_id) { if (this->Internals->RecordContainer.size() > 0) { vtkKWLogWidgetInternals::RecordContainerIterator it = this->Internals->RecordContainer.begin(); vtkKWLogWidgetInternals::RecordContainerIterator end = this->Internals->RecordContainer.end(); for (; it!=end; it++) { if ((*it).Id == record_id) { this->Internals->RecordContainer.erase(it); break; } } } } //---------------------------------------------------------------------------- int vtkKWLogWidget::AddRecord( const char* description, int type) { if (!this->IsCreated() || !this->RecordList) { return 0; } struct vtkKWLogWidgetInternals::Record record; record.Id = vtkKWLogWidget::IdCounter++; record.Description = description; record.Time = this->GetCurrentTimeInSeconds(); record.Type = type; vtkKWMultiColumnList *tablelist = this->RecordList->GetWidget(); tablelist->InsertRow(0); tablelist->SeeRow(0); if (record.Type == vtkKWLogWidget::ErrorType) { tablelist->SetCellText(0, 1, "Error"); tablelist->SetCellImage(0, 1, this->Internals->ErrorImage.c_str()); } else if (record.Type == vtkKWLogWidget::WarningType) { tablelist->SetCellText(0, 1, "Warning"); tablelist->SetCellImage(0, 1, this->Internals->WarningImage.c_str()); } else if (record.Type == vtkKWLogWidget::InformationType) { tablelist->SetCellText(0, 1, "Information"); tablelist->SetCellImage(0, 1, this->Internals->InformationImage.c_str()); } else if (record.Type == vtkKWLogWidget::DebugType) { tablelist->SetCellText(0, 1, "Debug"); tablelist->SetCellImage(0, 1, this->Internals->DebugImage.c_str()); } tablelist->SetCellTextAsInt(0, 2, record.Time); // if the description has multiple lines, display only the first // line and add (...) at the end of the first line to indicate // there is more. The whole description will be displayed // in the description box when this record is selected. int newline_pos = (int)record.Description.find_first_of('\n'); if (newline_pos > 0 && newline_pos < (int)record.Description.length()) { vtksys_stl::string celltext = record.Description.substr( 0, newline_pos).append("..."); tablelist->SetCellText(0, 3, celltext.c_str()); } else { tablelist->SetCellText(0, 3, record.Description.c_str()); } tablelist->SetCellTextAsInt(0, 0, record.Id); this->Internals->RecordContainer.push_front(record); this->PruneRecords(); // If the table is sorted, we need to resort it in the same way. int row_index = 0; int sorted_col = tablelist->GetLastSortedColumn(); if (sorted_col >= 1) { tablelist->SortByColumn( sorted_col, tablelist->GetLastSortedOrder()); row_index = this->GetIndexOfRowWithRecordId(record.Id); } tablelist->SeeRow(row_index); this->Update(); return record.Id; } //---------------------------------------------------------------------------- int vtkKWLogWidget::GetIndexOfRowWithRecordId(int record_id) { if (this->RecordList) { vtkKWMultiColumnList *record_list = this->RecordList->GetWidget(); int nb_rows = record_list->GetNumberOfRows(); for (int i = nb_rows - 1; i >= 0; i--) { if (record_list->GetCellTextAsInt(i, 0) == record_id) { return i; } } } return -1; } //---------------------------------------------------------------------------- void vtkKWLogWidget::RemoveRowWithRecordId(int record_id) { int row_index = this->GetIndexOfRowWithRecordId(record_id); if (row_index >= 0) { this->RecordList->GetWidget()->DeleteRow(row_index); } } //---------------------------------------------------------------------------- void vtkKWLogWidget::PruneRecords() { while ((int)this->Internals->RecordContainer.size() > this->GetMaximumNumberOfRecords()) { this->RemoveRowWithRecordId(this->Internals->RecordContainer.back().Id); this->Internals->RecordContainer.pop_back(); } } //---------------------------------------------------------------------------- void vtkKWLogWidget::Update() { this->UpdateEnableState(); if (this->RecordList) { if (this->RecordList->GetWidget()->GetNumberOfRows() == 0) { this->SaveButton->SetEnabled(0); this->RemoveAllButton->SetEnabled(0); this->EmailButton->SetEnabled(0); } if (this->RecordList->GetWidget()-> GetNumberOfSelectedRows() == 0) { this->RemoveSelectedButton->SetEnabled(0); } } } //---------------------------------------------------------------------------- void vtkKWLogWidget::SelectionChangedCallback() { // Update the description text if (this->RecordList->GetWidget()->GetNumberOfSelectedRows() > 0) { this->DescriptionText->GetWidget()->SetText(""); vtkKWMultiColumnList *record_list = this->RecordList->GetWidget(); int nb_selected_rows = record_list->GetNumberOfSelectedRows(); int *indices = new int [nb_selected_rows]; record_list->GetSelectedRows(indices); if (this->Internals->RecordContainer.size() > 0) { vtksys_ios::ostringstream text; if (nb_selected_rows > 1) { for (int i=0; iGetCellText(indices[i], 1) << endl; text << "Time: " << this->GetFormatTimeStringCallback( record_list->GetCellText(indices[i], 2)) << endl; text << "Description: " << this->GetRecordDescription( record_list->GetCellTextAsInt(indices[i], 0)) << endl << endl; } } else { text << this->GetRecordDescription( record_list->GetCellTextAsInt(indices[0], 0)) << endl << endl; } this->DescriptionText->GetWidget()->SetText(text.str().c_str()); } delete [] indices; } this->Update(); } //---------------------------------------------------------------------------- void vtkKWLogWidget::SetMaximumNumberOfRecords(int maxnum) { if (maxnum < MIN_NUMBER_OF_RECORDS) { maxnum = MIN_NUMBER_OF_RECORDS; } else if (maxnum > MAX_NUMBER_OF_RECORDS) { maxnum = MAX_NUMBER_OF_RECORDS; } if (this->MaximumNumberOfRecords == maxnum) { return; } this->MaximumNumberOfRecords = maxnum; this->PruneRecords(); this->Modified(); } //---------------------------------------------------------------------------- void vtkKWLogWidget::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->PropagateEnableState(this->RecordList); this->PropagateEnableState(this->Toolbar); this->PropagateEnableState(this->SaveButton); this->PropagateEnableState(this->RemoveSelectedButton); this->PropagateEnableState(this->RemoveAllButton); this->PropagateEnableState(this->EmailButton); } //---------------------------------------------------------------------------- void vtkKWLogWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "MaximumNumberOfRecords: " << this->MaximumNumberOfRecords << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWMessageDialog.cxx0000644000175000017500000005057711304615640021316 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWMessageDialog.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWMessageDialog.h" #include "vtkKWApplication.h" #include "vtkKWCheckButton.h" #include "vtkKWEvent.h" #include "vtkKWFrame.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWMessage.h" #include "vtkKWPushButton.h" #include "vtkKWRegistryHelper.h" #include "vtkObjectFactory.h" #include //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWMessageDialog ); vtkCxxRevisionMacro(vtkKWMessageDialog, "1.93"); //---------------------------------------------------------------------------- vtkKWMessageDialog::vtkKWMessageDialog() { this->MessageDialogFrame = vtkKWFrame::New(); this->TopFrame = vtkKWFrame::New(); this->BottomFrame = vtkKWFrame::New(); this->Message = vtkKWMessage::New(); this->CheckButton = vtkKWCheckButton::New(); this->ButtonFrame = vtkKWFrame::New(); this->OKFrame = vtkKWFrame::New(); this->CancelFrame = vtkKWFrame::New(); this->OtherFrame = vtkKWFrame::New(); this->OKButton = vtkKWPushButton::New(); this->CancelButton = vtkKWPushButton::New(); this->OtherButton = vtkKWPushButton::New(); this->Style = vtkKWMessageDialog::StyleMessage; this->Icon = vtkKWLabel::New(); this->DialogName = 0; this->Options = 0; this->DialogText = 0; this->OKButtonText = 0; this->SetOKButtonText(ks_("Message Dialog|Button|OK")); this->CancelButtonText = 0; this->SetCancelButtonText(ks_("Message Dialog|Button|Cancel")); this->OtherButtonText = 0; this->SetOtherButtonText(ks_("Message Dialog|Button|Other")); } //---------------------------------------------------------------------------- vtkKWMessageDialog::~vtkKWMessageDialog() { this->Message->Delete(); this->CheckButton->Delete(); this->ButtonFrame->Delete(); this->OKFrame->Delete(); this->CancelFrame->Delete(); this->OtherFrame->Delete(); this->OKButton->Delete(); this->CancelButton->Delete(); this->OtherButton->Delete(); this->Icon->Delete(); this->MessageDialogFrame->Delete(); this->TopFrame->Delete(); this->BottomFrame->Delete(); this->SetDialogName(0); this->SetDialogText(0); this->SetOKButtonText(0); this->SetCancelButtonText(0); this->SetOtherButtonText(0); } //---------------------------------------------------------------------------- void vtkKWMessageDialog::CreateWidget() { // Check if already created if (this->IsCreated()) { vtkErrorMacro("MessageDialog already created"); return; } this->Superclass::CreateWidget(); this->MessageDialogFrame->SetParent(this); this->MessageDialogFrame->Create(); this->Script("pack %s -side right -fill both -expand true -pady 0", this->MessageDialogFrame->GetWidgetName()); if (this->Options & vtkKWMessageDialog::Beep) { this->BeepOn(); } // Top this->TopFrame->SetParent(this->MessageDialogFrame); this->TopFrame->Create(); // The message itself this->Message->SetParent(this->MessageDialogFrame); this->Message->Create(); this->Message->SetWidth(300); this->UpdateMessage(); // The checkbutton this->CheckButton->SetParent(this->MessageDialogFrame); this->CheckButton->Create(); // Bottom frame this->BottomFrame->SetParent(this->MessageDialogFrame); this->BottomFrame->Create(); // Button frame this->ButtonFrame->SetParent(this->MessageDialogFrame); this->ButtonFrame->Create(); this->OKFrame->SetParent(this->ButtonFrame); this->OKFrame->Create(); this->OKFrame->SetBorderWidth(3); this->OKFrame->SetReliefToFlat(); this->OKButton->SetParent(this->OKFrame); this->OKButton->Create(); this->OKButton->SetWidth(16); this->OKButton->SetText(this->OKButtonText); this->OKButton->SetCommand(this, "OK"); this->OKButton->AddBinding( "", this->OKFrame, "SetReliefToGroove"); this->OKButton->AddBinding( "", this->OKFrame, "SetReliefToFlat"); this->OKButton->AddBinding( "", this, "OK"); this->OtherFrame->SetParent(this->ButtonFrame); this->OtherFrame->Create(); this->OtherFrame->SetBorderWidth(3); this->OtherFrame->SetReliefToFlat(); this->OtherButton->SetParent(this->OtherFrame); this->OtherButton->Create(); this->OtherButton->SetWidth(16); this->OtherButton->SetText(this->OtherButtonText); this->OtherButton->SetCommand(this, "Other"); this->OtherButton->AddBinding( "", this->OtherFrame, "SetReliefToGroove"); this->OtherButton->AddBinding( "", this->OtherFrame, "SetReliefToFlat"); this->OtherButton->AddBinding( "", this, "Other"); this->CancelFrame->SetParent(this->ButtonFrame); this->CancelFrame->Create(); this->CancelFrame->SetBorderWidth(3); this->CancelFrame->SetReliefToFlat(); this->CancelButton->SetParent(this->CancelFrame); this->CancelButton->Create(); this->CancelButton->SetWidth(16); this->CancelButton->SetText(this->CancelButtonText); this->CancelButton->SetCommand(this, "Cancel"); this->CancelButton->AddBinding( "", this->CancelFrame, "SetReliefToGroove"); this->CancelButton->AddBinding( "", this->CancelFrame, "SetReliefToFlat"); this->CancelButton->AddBinding( "", this, "Cancel"); this->UpdateButtons(); // Icon this->Icon->SetParent(this); this->Icon->Create(); this->Icon->SetWidth(0); this->Icon->SetPadX(0); this->Icon->SetPadY(0); this->Icon->SetBorderWidth(0); this->Script("pack %s -side left -fill y", this->Icon->GetWidgetName()); this->Script("pack forget %s", this->Icon->GetWidgetName()); this->SetIcon(); // Pack this->Pack(); } //---------------------------------------------------------------------------- void vtkKWMessageDialog::Pack() { if (!this->IsCreated()) { return; } if (!this->MessageDialogFrame || !this->MessageDialogFrame->IsCreated()) { return; } this->MessageDialogFrame->UnpackChildren(); if (this->TopFrame->GetNumberOfChildren()) { this->Script("pack %s -side top -fill both -expand t", this->TopFrame->GetWidgetName()); } if (this->Message && this->DialogText && *this->DialogText) { this->Script("pack %s -side top -fill x -padx 20 -pady 5 -expand t", this->Message->GetWidgetName()); } if (this->BottomFrame->GetNumberOfChildren()) { this->Script("pack %s -side top -fill both -expand true", this->BottomFrame->GetWidgetName()); } if (this->CheckButton && this->GetDialogName()) { this->CheckButton->SetText( ks_("Message Dialog|Do not show this dialog anymore.")); this->Script("pack %s -side top -fill x -padx 20 -pady 5", this->CheckButton->GetWidgetName()); } this->Script("pack %s -side bottom -fill x -pady 2 -expand f", this->ButtonFrame->GetWidgetName()); this->PackButtons(); } //---------------------------------------------------------------------------- void vtkKWMessageDialog::UpdateButtons() { if (this->Style == vtkKWMessageDialog::StyleYesNo) { this->SetOKButtonText(ks_("Message Dialog|Button|Yes")); if (this->OKButton) { this->OKButton->SetText(this->OKButtonText); } this->SetCancelButtonText(ks_("Message Dialog|Button|No")); if (this->CancelButton) { this->CancelButton->SetText(this->CancelButtonText); } } else if (this->Style == vtkKWMessageDialog::StyleMessage) { this->SetOKButtonText(ks_("Message Dialog|Button|OK")); if (this->OKButton) { this->OKButton->SetText(this->OKButtonText); } } else if (this->Style == vtkKWMessageDialog::StyleCancel) { this->SetCancelButtonText(ks_("Message Dialog|Button|Cancel")); if (this->CancelButton) { this->CancelButton->SetText(this->CancelButtonText); } } } //---------------------------------------------------------------------------- void vtkKWMessageDialog::PackButtons() { int has_ok = (this->Style == vtkKWMessageDialog::StyleMessage || this->Style == vtkKWMessageDialog::StyleYesNo || this->Style == vtkKWMessageDialog::StyleOkCancel || this->Style == vtkKWMessageDialog::StyleOkOtherCancel); int has_cancel = (this->Style == vtkKWMessageDialog::StyleCancel || this->Style == vtkKWMessageDialog::StyleYesNo || this->Style == vtkKWMessageDialog::StyleOkCancel || this->Style == vtkKWMessageDialog::StyleOkOtherCancel); int has_other = (this->Style == vtkKWMessageDialog::StyleOkOtherCancel); // Pack buttons if (this->ButtonFrame && this->ButtonFrame->IsCreated()) { this->ButtonFrame->UnpackChildren(); } vtksys_stl::string pack_opt; if (this->Options & vtkKWMessageDialog::PackVertically) { pack_opt = "-side top -expand yes -fill x -padx 4"; } else { pack_opt = "-side left -expand yes -padx 2"; } if (has_ok && this->OKButton && this->OKButton->IsCreated()) { this->Script("pack %s %s %s", this->OKButton->GetWidgetName(), this->OKFrame->GetWidgetName(), pack_opt.c_str()); } if (has_other && this->OtherButton && this->OtherButton->IsCreated()) { this->Script("pack %s %s %s", this->OtherButton->GetWidgetName(), this->OtherFrame->GetWidgetName(), pack_opt.c_str()); } if (has_cancel && this->CancelButton && this->CancelButton->IsCreated()) { this->Script("pack %s %s %s", this->CancelButton->GetWidgetName(), this->CancelFrame->GetWidgetName(), pack_opt.c_str()); } } //---------------------------------------------------------------------------- void vtkKWMessageDialog::UpdateMessage() { if (this->Message) { this->Message->SetText(this->DialogText); } } //---------------------------------------------------------------------------- void vtkKWMessageDialog::SetStyle(int arg) { if (this->Style == arg) { return; } this->Style = arg; this->Modified(); this->UpdateButtons(); this->PackButtons(); } void vtkKWMessageDialog::SetStyleToMessage() { this->SetStyle(vtkKWMessageDialog::StyleMessage); } void vtkKWMessageDialog::SetStyleToYesNo() { this->SetStyle(vtkKWMessageDialog::StyleYesNo); } void vtkKWMessageDialog::SetStyleToOkCancel() { this->SetStyle(vtkKWMessageDialog::StyleOkCancel); } void vtkKWMessageDialog::SetStyleToOkOtherCancel() { this->SetStyle(vtkKWMessageDialog::StyleOkOtherCancel); } void vtkKWMessageDialog::SetStyleToCancel() { this->SetStyle(vtkKWMessageDialog::StyleCancel); } //---------------------------------------------------------------------------- void vtkKWMessageDialog::SetText(const char *txt) { this->SetDialogText(txt); this->UpdateMessage(); this->Pack(); } //---------------------------------------------------------------------------- void vtkKWMessageDialog::SetTextWidth(int w) { if (this->Message) { this->Message->SetWidth(w); } } //---------------------------------------------------------------------------- int vtkKWMessageDialog::GetTextWidth() { if (this->Message) { return this->Message->GetWidth(); } return 0; } //---------------------------------------------------------------------------- void vtkKWMessageDialog::Display() { // Make sure we pack correctly depending on the frame's children this->Pack(); if (this->Options & vtkKWMessageDialog::NoDefault || this->Options & vtkKWMessageDialog::CancelDefault) { this->CancelButton->Focus(); } else if (this->Options & vtkKWMessageDialog::YesDefault || this->Options & vtkKWMessageDialog::OkDefault) { this->OKButton->Focus(); } if (this->OKButton->IsCreated() && this->CancelButton->IsCreated()) { this->OKButton->SetBinding("", "focus [ tk_focusNext %W ]"); this->OKButton->SetBinding("", "focus [ tk_focusPrev %W ]"); this->CancelButton->SetBinding("", "focus [ tk_focusNext %W ]"); this->CancelButton->SetBinding("", "focus [ tk_focusPrev %W ]"); if (this->OtherButton->IsCreated()) { this->OtherButton->SetBinding("", "focus [ tk_focusNext %W ]"); this->OtherButton->SetBinding("", "focus [ tk_focusPrev %W ]"); } } if (this->Options & vtkKWMessageDialog::InvokeAtPointer) { this->SetDisplayPositionToPointer(); } if (!(this->Options & vtkKWMessageDialog::Resizable)) { this->SetResizable(0, 0); } // Display this->Superclass::Display(); } //---------------------------------------------------------------------------- int vtkKWMessageDialog::PreInvoke() { this->InvokeEvent(vtkKWEvent::MessageDialogInvokeEvent, this->DialogText); // Check if the user specified a default answer for this one, stored // in the registry if (this->DialogName) { int res = this->RestoreMessageDialogResponseFromRegistry( this->GetApplication(), this->DialogName); if (res == 1) { this->Done = vtkKWDialog::StatusOK; return 1; } if (res == -1) { this->Done = vtkKWDialog::StatusCanceled; return 1; } } return this->Superclass::PreInvoke(); } //---------------------------------------------------------------------------- void vtkKWMessageDialog::PostInvoke() { this->Superclass::PostInvoke(); // Check if the user specified a default answer for this one, and store it // in the registry if (this->DialogName && this->GetRememberMessage()) { int ires = (this->Done == vtkKWDialog::StatusCanceled ? 0 : 1); if (this->Options & vtkKWMessageDialog::RememberYes) { ires = 1; } else if (this->Options & vtkKWMessageDialog::RememberNo) { ires = -1; } else { if (!ires) { ires = -1; } } this->SaveMessageDialogResponseToRegistry( this->GetApplication(), this->DialogName, ires); } } //---------------------------------------------------------------------------- void vtkKWMessageDialog::SetIcon() { if (this->Options & vtkKWMessageDialog::ErrorIcon) { this->Icon->SetImageToPredefinedIcon( vtkKWIcon::IconNuvola48x48ActionsMessageBoxCritical); } else if (this->Options & vtkKWMessageDialog::QuestionIcon) { this->Icon->SetImageToPredefinedIcon( vtkKWIcon::IconNuvola48x48ActionsHelp); } else if (this->Options & vtkKWMessageDialog::WarningIcon) { this->Icon->SetImageToPredefinedIcon( vtkKWIcon::IconNuvola48x48ActionsMessageBoxWarning); } else if (!(this->Options & vtkKWMessageDialog::CustomIcon)) { this->Icon->SetWidth(0); this->Icon->SetPadY(0); this->Icon->SetPadX(0); this->Icon->SetBorderWidth(0); this->Script("pack forget %s", this->Icon->GetWidgetName()); return; } this->Icon->SetAnchorToNorth(); this->Icon->SetPadY(5); this->Icon->SetPadX(4); this->Icon->SetBorderWidth(4); this->Script("pack %s -pady 17 -side left -fill y", this->Icon->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWMessageDialog::PopupMessage(vtkKWApplication *app, vtkKWWidget *win, const char* title, const char*message, int options) { vtkKWMessageDialog *dlg2 = vtkKWMessageDialog::New(); dlg2->SetApplication(app); dlg2->SetMasterWindow(win); dlg2->SetOptions( options | vtkKWMessageDialog::Beep | vtkKWMessageDialog::YesDefault); dlg2->SetTitle(title); dlg2->SetText(message); dlg2->Invoke(); dlg2->Delete(); } //---------------------------------------------------------------------------- int vtkKWMessageDialog::PopupYesNo(vtkKWApplication *app, vtkKWWidget *win, const char* name, const char* title, const char* message, int options) { vtkKWMessageDialog *dlg2 = vtkKWMessageDialog::New(); dlg2->SetApplication(app); dlg2->SetStyleToYesNo(); dlg2->SetMasterWindow(win); dlg2->SetOptions( options | vtkKWMessageDialog::Beep | vtkKWMessageDialog::YesDefault); dlg2->SetDialogName(name); dlg2->SetTitle(title); dlg2->SetText(message); int ret = dlg2->Invoke(); dlg2->Delete(); return ret; } //---------------------------------------------------------------------------- int vtkKWMessageDialog::PopupYesNo(vtkKWApplication *app, vtkKWWidget *win, const char* title, const char*message, int options) { return vtkKWMessageDialog::PopupYesNo(app, win, 0, title, message, options); } //---------------------------------------------------------------------------- int vtkKWMessageDialog::PopupOkCancel(vtkKWApplication *app, vtkKWWidget *win, const char* title, const char*message, int options) { vtkKWMessageDialog *dlg2 = vtkKWMessageDialog::New(); dlg2->SetApplication(app); dlg2->SetStyleToOkCancel(); dlg2->SetOptions( options | vtkKWMessageDialog::Beep | vtkKWMessageDialog::YesDefault); dlg2->SetMasterWindow(win); dlg2->SetTitle(title); dlg2->SetText(message); int ret = dlg2->Invoke(); dlg2->Delete(); return ret; } //---------------------------------------------------------------------------- int vtkKWMessageDialog::GetRememberMessage() { int res = this->CheckButton->GetSelectedState(); return res; } //---------------------------------------------------------------------------- void vtkKWMessageDialog::Other() { this->Done = vtkKWMessageDialog::StatusOther; this->Withdraw(); } //---------------------------------------------------------------------------- int vtkKWMessageDialog::RestoreMessageDialogResponseFromRegistry( vtkKWApplication *app, const char* dialogname) { char buffer[vtkKWRegistryHelper::RegistryKeyValueSizeMax]; int retval = 0; if (app && dialogname && app->GetRegistryValue(3, "Dialogs", dialogname, buffer)) { retval = atoi(buffer); } return retval; } //---------------------------------------------------------------------------- void vtkKWMessageDialog::SaveMessageDialogResponseToRegistry( vtkKWApplication *app, const char* dialogname, int response) { if (app && dialogname) { app->SetRegistryValue(3, "Dialogs", dialogname, "%d", response); } } //---------------------------------------------------------------------------- void vtkKWMessageDialog::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "DialogName: " << (this->DialogName?this->DialogName:"none") << endl; os << indent << "Options: " << this->GetOptions() << endl; os << indent << "Style: " << this->GetStyle() << endl; os << indent << "MessageDialogFrame: " << this->MessageDialogFrame << endl; os << indent << "OKButtonText: " << (this->OKButtonText? this->OKButtonText:"none") << endl; os << indent << "CancelButtonText: " << (this->CancelButtonText? this->CancelButtonText:"none") << endl; os << indent << "OtherButtonText: " << (this->OtherButtonText? this->OtherButtonText:"none") << endl; os << indent << "DialogName: " << (this->DialogName?this->DialogName:"none") << endl; os << indent << "TopFrame: " << this->TopFrame << endl; os << indent << "BottomFrame: " << this->BottomFrame << endl; os << indent << "OKButton: " << this->OKButton << endl; os << indent << "CancelButton: " << this->CancelButton << endl; os << indent << "OtherButton: " << this->OtherButton << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWMessageDialog.h0000644000175000017500000002007211105126610020717 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWMessageDialog.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWMessageDialog - a message dialog superclass // .SECTION Description // A generic superclass for MessageDialog boxes. #ifndef __vtkKWMessageDialog_h #define __vtkKWMessageDialog_h #include "vtkKWDialog.h" class vtkKWApplication; class vtkKWCheckButton; class vtkKWFrame; class vtkKWMessage; class vtkKWLabel; class vtkKWPushButton; class KWWidgets_EXPORT vtkKWMessageDialog : public vtkKWDialog { public: static vtkKWMessageDialog* New(); vtkTypeRevisionMacro(vtkKWMessageDialog,vtkKWDialog); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set the text of the message virtual void SetText(const char *); // Description: // Set/Get the width of the message, in pixels) virtual void SetTextWidth(int); virtual int GetTextWidth(); // Description: // Status of the dialog. This subclass defines a new 'Other' status on // top of the usual one (active e.g. displayed, canceled, OK'ed). This // status is triggered by pressing the 'Other' button. //BTX enum { StatusOther = 100 }; //ETX // Description: // Set the style of the message box. // No effect if called after Create() //BTX enum { StyleMessage = 0, StyleYesNo, StyleOkCancel, StyleOkOtherCancel, StyleCancel }; //ETX virtual void SetStyle(int); vtkGetMacro(Style,int); void SetStyleToMessage(); void SetStyleToYesNo(); void SetStyleToOkCancel(); void SetStyleToOkOtherCancel(); void SetStyleToCancel(); // Description: // Set different options for the dialog. //BTX enum { RememberYes = 0x00002, RememberNo = 0x00004, ErrorIcon = 0x00008, WarningIcon = 0x00010, QuestionIcon = 0x00020, YesDefault = 0x00040, NoDefault = 0x00080, OkDefault = 0x00100, CancelDefault = 0x00200, Beep = 0x00400, PackVertically = 0x00800, InvokeAtPointer = 0x01000, CustomIcon = 0x02000, Resizable = 0x04000 }; //ETX vtkSetMacro(Options, int); vtkGetMacro(Options, int); // Description: // The label displayed on the OK button. Only used when // the style is OkCancel. vtkSetStringMacro(OKButtonText); vtkGetStringMacro(OKButtonText); // Description: // The label displayed on the cancel button. Only used when // the style is OkCancel. vtkSetStringMacro(CancelButtonText); vtkGetStringMacro(CancelButtonText); // Description: // The label displayed on the other button. Only used when // the style is OkOtherCancel. vtkSetStringMacro(OtherButtonText); vtkGetStringMacro(OtherButtonText); // Description: // Utility methods to create various dialog windows. // icon is a enumerated icon type described in vtkKWIcon. // title is a title string of the dialog. name is the dialog name // used for the registry. message is the text message displayed // in the dialog. masterwin is a pointer to a widget belonging to the window // you want this message dialog to be a child of (or the window directly). static void PopupMessage(vtkKWApplication *app, vtkKWWidget *masterWin, const char* title, const char* message, int options = 0); static int PopupYesNo(vtkKWApplication *app, vtkKWWidget *masterWin, const char* title, const char* message, int options = 0); static int PopupYesNo(vtkKWApplication *app, vtkKWWidget *masterWin, const char* name, const char* title, const char* message, int options = 0); static int PopupOkCancel(vtkKWApplication *app, vtkKWWidget *masterWin, const char* title, const char* message, int options = 0); // Description: // Retrieve the frame where the message is. vtkGetObjectMacro(TopFrame, vtkKWFrame); vtkGetObjectMacro(MessageDialogFrame, vtkKWFrame); vtkGetObjectMacro(BottomFrame, vtkKWFrame); vtkGetObjectMacro(Icon, vtkKWLabel); // Description: // Accessor for OK and cancel button vtkGetObjectMacro(OKButton, vtkKWPushButton); vtkGetObjectMacro(CancelButton, vtkKWPushButton); vtkGetObjectMacro(OtherButton, vtkKWPushButton); // Description: // Set or get the message dialog name. This name is use to save/restore // information about this specific dialog in the registry (for example, // bypass the dialog altogether by clicking on a specific button // automatically). // This should not be confused with // the message dialog title that can be set using the superclass // SetTitle() method. vtkSetStringMacro(DialogName); vtkGetStringMacro(DialogName); // Description: // Store/retrieve a message dialog response for a given application // in/from the registry. // This can be used to prevent the user from answering the same question // again and again (for ex: "Are you sure you want to exit the application"). // 'dialogname' is the name of a dialog (most likely its DialogName ivar). // The 'response' is arbitrary but most likely the value returned by a // call to Invoke() on the dialog. static int RestoreMessageDialogResponseFromRegistry( vtkKWApplication *app, const char *dialogname); static void SaveMessageDialogResponseToRegistry( vtkKWApplication *app, const char *dialogname, int response); // Description: // Display the dialog. // Override the superclass to set up keybindings and options virtual void Display(); // Description: // Dialog can be also used by performing individual steps of Invoke. These // steps are initialize: PreInvoke(), finalize: PostInvoke(), and check if // user responded IsUserDoneWithDialog(). Use this method only if you // want to bypass the event loop used in Invoke() by creating your own // and checking for IsUserDoneWithDialog(). // Override the superclass to handle DialogName virtual int PreInvoke(); virtual void PostInvoke(); // Description:: // Callback. Close this Dialog (for the third button) virtual void Other(); // Description: // Set the icon on the message dialog. // Legacy. Do not call anymore. Is called automatically by Create(). virtual void SetIcon(); protected: vtkKWMessageDialog(); ~vtkKWMessageDialog(); // Description: // Create the widget. virtual void CreateWidget(); int Style; int Default; int Options; char *DialogName; char *DialogText; vtkSetStringMacro(DialogText); vtkGetStringMacro(DialogText); vtkKWFrame *TopFrame; vtkKWFrame *MessageDialogFrame; vtkKWFrame *BottomFrame; vtkKWMessage *Message; vtkKWFrame *ButtonFrame; vtkKWPushButton *OKButton; vtkKWPushButton *CancelButton; vtkKWPushButton *OtherButton; vtkKWLabel *Icon; vtkKWFrame *OKFrame; vtkKWFrame *CancelFrame; vtkKWFrame *OtherFrame; vtkKWCheckButton *CheckButton; // Description: // Get the value of the check box for remembering the answer from // the user. int GetRememberMessage(); char* OKButtonText; char* CancelButtonText; char* OtherButtonText; // Description: // Update the buttons or message virtual void UpdateButtons(); virtual void PackButtons(); virtual void UpdateMessage(); // Description: // Pack virtual void Pack(); private: vtkKWMessageDialog(const vtkKWMessageDialog&); // Not implemented void operator=(const vtkKWMessageDialog&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWInternationalization.h0000644000175000017500000001051610475052622022434 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWInternationalization.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #ifndef __vtkKWInternationalization_h #define __vtkKWInternationalization_h #include "vtkObject.h" #include "vtkKWWidgets.h" // Needed for export symbols directives /* ---------------------------------------------------------------------- If Internationalization is supported, provide simple macros to map gettext function calls. Some macros rely on the GETTEXT_DOMAIN symbol to be defined as the quoted name of the text domain that applies to the compilation unit. This is done automatically by the KWWidgets_CREATE_GETTEXT_TARGETS macro (KWWidgetsInternationalizationMacros.cmake) so that the below macros can be used directly and expand to the right text domain automatically. */ #ifdef KWWidgets_USE_INTERNATIONALIZATION # include // Bring gettext # undef _ # define _(string) gettext(string) # undef k_ # define k_(string) dgettext(GETTEXT_DOMAIN, string) #else # undef _ # define _(string) string # undef k_ # define k_(string) string # undef gettext # define gettext(string) string # undef dgettext # define dgettext(domain,string) string #endif #ifndef GETTEXT_DOMAIN #define GETTEXT_DOMAIN "" #endif #define gettext_noop(string) string #define N_(string) gettext_noop(string) /* ---------------------------------------------------------------------- Declare some gettext functions that support enlengthen strings. Enlengthen strings make use of a special *separator* as a mean to provide more context and disambiguate short GUI strings. Example: "Menu|File|Open" instead of "Open" See gettext "10.2.6 How to use gettext in GUI programs". */ //BTX KWWidgets_EXTERN KWWidgets_EXPORT char* kww_sgettext(const char *msgid); KWWidgets_EXTERN KWWidgets_EXPORT char* kww_sdgettext(const char *domain_name, const char *msgid); //ETX #define s_(string) kww_sgettext(string) #define ks_(string) kww_sdgettext(GETTEXT_DOMAIN, string) /* ---------------------------------------------------------------------- */ class KWWidgets_EXPORT vtkKWInternationalization : public vtkObject { public: static vtkKWInternationalization* New(); vtkTypeRevisionMacro(vtkKWInternationalization,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the current global domain of the LC_MESSAGES category. // This domain specifies where the internationalized/translated strings // are coming from. // The argument is a null-terminated string, whose characters must be legal // in the use in filenames. static void SetCurrentTextDomain(const char *domain_name); static const char* GetCurrentTextDomain(); // Description: // Set/Get the binding between a domain and a message catalog directory. // The directory should be top-most directory containing the sub-directories // for each locale/language (ex: fr, zh_CN). Each language subdirectory has // a LC_MESSAGES subdirectory where the message catalog for that specific // domain can be found (ex: dir/fr/LC_MESSAGES/myapp.mo). static void SetTextDomainBinding(const char *domain_name, const char *dir); static const char* GetTextDomainBinding(const char *domain_name); // Description: // This method tries *really* hard to find *and* set a message catalog // directory for a specific domain. // Another signature accepts a semi-colon separated list of directories // to search message catalogs for. // Returns catalog directory if it was found, NULL otherwise. static const char* FindTextDomainBinding(const char *domain_name); static const char* FindTextDomainBinding( const char *domain_name, const char *dirs_to_search); protected: vtkKWInternationalization() {}; ~vtkKWInternationalization() {}; private: vtkKWInternationalization(const vtkKWInternationalization&); // Not implemented void operator=(const vtkKWInternationalization&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWStateMachineInput.h0000644000175000017500000000403610522464403021611 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWStateMachineInput.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWStateMachineInput - a state machine input. // .SECTION Description // This class is the basis for a state machine input. // A state machine is defined by a set of states, a set of inputs and a // transition matrix that defines for each pair of (state,input) what is // the next state to assume. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWStateMachine vtkKWStateMachineState vtkKWStateMachineTransition #ifndef __vtkKWStateMachineInput_h #define __vtkKWStateMachineInput_h #include "vtkKWObject.h" class KWWidgets_EXPORT vtkKWStateMachineInput : public vtkKWObject { public: static vtkKWStateMachineInput* New(); vtkTypeRevisionMacro(vtkKWStateMachineInput, vtkKWObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get id. vtkGetMacro(Id, vtkIdType); // Description: // Set/Get simple name. vtkGetStringMacro(Name); vtkSetStringMacro(Name); protected: vtkKWStateMachineInput(); ~vtkKWStateMachineInput(); vtkIdType Id; char *Name; private: static vtkIdType IdCounter; vtkKWStateMachineInput(const vtkKWStateMachineInput&); // Not implemented void operator=(const vtkKWStateMachineInput&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWTree.cxx0000644000175000017500000013270311245053776017513 0ustar domibeldomibel/*========================================================================= Copyright (c) 1998-2003 Kitware Inc. 469 Clifton Corporate Parkway, Clifton Park, NY, 12065, USA. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Kitware nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. * Modified source versions must be plainly marked as such, and must not be misrepresented as being the original software. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =========================================================================*/ #include "vtkKWTree.h" #include "vtkKWApplication.h" #include "vtkKWOptions.h" #include "vtkKWInternationalization.h" #include "vtkObjectFactory.h" #include "vtkKWTkUtilities.h" #include "vtkKWIcon.h" #include #include #include #include #include "Utilities/BWidgets/vtkKWBWidgetsInit.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWTree ); vtkCxxRevisionMacro(vtkKWTree, "$Revision: 1.49 $"); //---------------------------------------------------------------------------- class vtkKWTreeInternals { public: // Some temporary storage var that do not need to be exposed in the .h // This is used so that method that are wrapped can return a pointer // to a safer location than a static buffer. double SelectionBackgroundColorTemp[3]; double SelectionForegroundColorTemp[3]; vtkKWWidget *TreeCanvas; vtkKWTreeInternals() { this->TreeCanvas = NULL; } ~vtkKWTreeInternals() { if (this->TreeCanvas) { this->TreeCanvas->Delete(); } } }; //---------------------------------------------------------------------------- vtkKWTree::vtkKWTree() { this->SelectionMode = vtkKWOptions::SelectionModeSingle; this->EnableReparenting = 0; this->UseRawNodeUserData = 0; this->UseRawNodeText = 0; this->SelectionChangedCommand = NULL; this->NodeParentChangedCommand = NULL; this->Internals = new vtkKWTreeInternals; } //---------------------------------------------------------------------------- vtkKWTree::~vtkKWTree() { if (this->SelectionChangedCommand) { delete [] this->SelectionChangedCommand; this->SelectionChangedCommand = NULL; } if (this->NodeParentChangedCommand) { delete [] this->NodeParentChangedCommand; this->NodeParentChangedCommand = NULL; } delete this->Internals; } //---------------------------------------------------------------------------- void vtkKWTree::CreateWidget() { // Use BWidget's Tree class: // http://aspn.activestate.com/ASPN/docs/ActiveTcl/bwidget/contents.html vtkKWApplication *app = this->GetApplication(); vtkKWBWidgetsInit::Initialize(app ? app->GetMainInterp() : NULL); // Call the superclass to create the widget and set the appropriate flags if (!vtkKWWidget::CreateSpecificTkWidget(this, "Tree", "-relief flat -bd 0 -highlightthickness 0 -padx 2 -deltay 17 -dragenabled 0 -dropenabled 0 -dragevent 1 -dropovermode n -background #ffffff")) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } // Store the internal canvas as a vtkKWWidget, for convenience this->Internals->TreeCanvas = vtkKWWidget::New(); this->Internals->TreeCanvas->SetParent(this); vtksys_stl::string name(this->GetWidgetName()); name += ".c"; this->Internals->TreeCanvas->SetWidgetName(name.c_str()); this->Internals->TreeCanvas->Create(); // Bindings this->SetBinding("<>", this, "SelectionCallback"); this->SetRightClickOnNodeCommand(this, "RightClickOnNodeCallback"); char *command = NULL; this->SetObjectMethodCommand(&command, this, "DropOverNodeCallback"); this->SetConfigurationOption("-dropcmd", command); delete [] command; // Key shortcuts const char *context = k_("Tree Widget"); this->SetKeyBinding( "", this, "KeyNavigationCallback Next", context, ks_("Tree Widget|Go to next item")); this->SetKeyBinding( "", this, "KeyNavigationCallback Prior", context, ks_("Tree Widget|Go to previous item")); this->SetKeyBinding( "", this, "KeyNavigationCallback Home", context, ks_("Tree Widget|Go to first item")); this->SetKeyBinding( "", this, "KeyNavigationCallback End", context, ks_("Tree Widget|Go to last item")); this->UpdateDragAndDrop(); } //---------------------------------------------------------------------------- void vtkKWTree::SetBinding(const char *event, vtkObject *object, const char *method) { this->Superclass::SetBinding(event, object, method); if (this->IsCreated()) { this->Internals->TreeCanvas->SetBinding(event, object, method); } } //---------------------------------------------------------------------------- void vtkKWTree::SetBinding(const char *event, const char *command) { this->Superclass::SetBinding(event, command); } //---------------------------------------------------------------------------- void vtkKWTree::AddBinding(const char *event, vtkObject *object, const char *method) { this->Superclass::AddBinding(event, object, method); if (this->IsCreated()) { this->Internals->TreeCanvas->AddBinding(event, object, method); } } //---------------------------------------------------------------------------- void vtkKWTree::AddBinding(const char *event, const char *command) { this->Superclass::AddBinding(event, command); } //---------------------------------------------------------------------------- void vtkKWTree::RemoveBinding(const char *event, vtkObject *object, const char *method) { this->Superclass::RemoveBinding(event, object, method); if (this->IsCreated()) { this->Internals->TreeCanvas->RemoveBinding(event, object, method); } } //---------------------------------------------------------------------------- void vtkKWTree::RemoveBinding(const char *event) { this->Superclass::RemoveBinding(event); if (this->IsCreated()) { this->Internals->TreeCanvas->RemoveBinding(event); } } //---------------------------------------------------------------------------- void vtkKWTree::UpdateDragAndDrop() { if (!this->IsCreated()) { return; } if (this->EnableReparenting) { this->SetConfigurationOptionAsInt("-dragenabled", 1); this->SetConfigurationOptionAsInt("-dropenabled", 1); } else { this->SetConfigurationOptionAsInt("-dragenabled", 0); this->SetConfigurationOptionAsInt("-dropenabled", 0); } } //---------------------------------------------------------------------------- void vtkKWTree::Focus() { this->Superclass::Focus(); if (this->IsCreated()) { this->Internals->TreeCanvas->Focus(); } } //---------------------------------------------------------------------------- int vtkKWTree::HasFocus() { if (this->IsCreated()) { return this->Internals->TreeCanvas->HasFocus(); } return 0; } //---------------------------------------------------------------------------- void vtkKWTree::SelectionCallback() { // This widget does not support multiple or single selection mode // natively. Let's take care of that. static int in_SelectionCallback = 0; if (in_SelectionCallback) { return; } in_SelectionCallback = 1; if (this->SelectionMode == vtkKWOptions::SelectionModeSingle) { vtksys_stl::vector sel_nodes; vtksys::SystemTools::Split(this->GetSelection(), sel_nodes, ' '); if (sel_nodes.size() > 1) { this->SelectSingleNode(sel_nodes[sel_nodes.size() - 1].c_str()); // We need to return now actually. A selection event will // still go through as we select that single node, and will // call that callback again, triggering InvokeSelectionChangedCommand. // It does not seem to be possible to avoid that event to be triggered in_SelectionCallback = 0; return; } } // We need to process the idle tasks here, since redrawing the tree // is only done on 'idle': we want redrawing to happen before our callback // otherwise it will appear as the selection itself is refreshed after // our callback. this->GetApplication()->ProcessIdleTasks(); this->InvokeSelectionChangedCommand(); in_SelectionCallback = 0; } //---------------------------------------------------------------------------- void vtkKWTree::RightClickOnNodeCallback(const char *node) { if (node) { this->InvokeEvent(vtkKWTree::RightClickOnNodeEvent, (void*)node); } } //---------------------------------------------------------------------------- //Reference: "proc Tree::_keynav {which win}" in tree.tcl // "proc Tree::_see { path idn } in tree.tcl void vtkKWTree::KeyNavigationCallback(const char* key) { if (this->IsCreated() && this->HasSelection() && key && *key) { vtksys_ios::ostringstream tk_cmd; //Get all visible and seletable nodes tk_cmd << "set nodes {}" << endl; tk_cmd << "foreach nodeItem [" << this->GetWidgetName() << ".c find withtag node] {" << endl; tk_cmd << "set node [Tree::_get_node_name " <GetWidgetName() << " $nodeItem 2]" << endl; tk_cmd << "if { [Widget::cget " << this->GetWidgetName() << ".$node -selectable] } {" << endl; tk_cmd << "lappend nodes $node}}" << endl; if(strcmp(key, "Next")==0 || strcmp(key, "Prior")==0) { //Get current node tk_cmd << "set node [Tree::_get_current_node " << this->GetWidgetName() << "]" << endl; //Figure out how many units in each page tk_cmd << "set scrl [" << this->GetWidgetName() <<".c cget -scrollregion]" << endl; tk_cmd << "set ymax [lindex $scrl 3]" << endl; tk_cmd << "set dy [" << this->GetWidgetName() << ".c cget -yscrollincrement]" << endl; tk_cmd << "set yv [" << this->GetWidgetName() << " yview]" << endl; tk_cmd << "set yv0 [expr {round([lindex $yv 0]*$ymax/$dy)}]" << endl; tk_cmd << "set yv1 [expr {round([lindex $yv 1]*$ymax/$dy)}]" << endl; tk_cmd << "set pageunits [expr {$yv1-$yv0}]" << endl; // Find out position of current node tk_cmd << "set y [expr {int([lindex [" << this->GetWidgetName() << ".c coords n:$node] 1]/$dy)}]" << endl; if(strcmp(key, "Prior")==0) { tk_cmd << "set index [expr {$y-$pageunits}]" << endl; tk_cmd << "if { $index < 0 } {set index 0}" << endl; } else { tk_cmd << "set index [expr {$y+$pageunits}]" << endl; tk_cmd << "set len [llength $nodes]" << endl; tk_cmd << "if { $index >= $len} {set index [expr {$len-1}]}" << endl; } } else if(strcmp(key, "Home")==0 || strcmp(key, "End")==0) { if(strcmp(key, "Home") == 0) { tk_cmd << "set index 0" << endl; } else { tk_cmd << "set index [expr {[llength $nodes] - 1}]" << endl; } } else { return; } // Select and see the new node tk_cmd << this->GetWidgetName() << " selection set [lindex $nodes $index]" << endl; tk_cmd << "Tree::_set_current_node " << this->GetWidgetName() << " [lindex $nodes $index]" << endl; tk_cmd << this->GetWidgetName() << " see [lindex $nodes $index]" << endl; this->Script(tk_cmd.str().c_str()); } } //---------------------------------------------------------------------------- void vtkKWTree::SetSelectionMode(int arg) { if ((arg != vtkKWOptions::SelectionModeSingle && arg != vtkKWOptions::SelectionModeMultiple) || arg == this->SelectionMode) { return; } this->SelectionMode = arg; // If we are switching to single mode, select the first node only if (this->SelectionMode == vtkKWOptions::SelectionModeSingle && this->HasSelection()) { vtksys_stl::vector sel_nodes; vtksys::SystemTools::Split(this->GetSelection(), sel_nodes, ' '); this->SelectSingleNode(sel_nodes[0].c_str()); } } void vtkKWTree::SetSelectionModeToSingle() { this->SetSelectionMode(vtkKWOptions::SelectionModeSingle); }; void vtkKWTree::SetSelectionModeToMultiple() { this->SetSelectionMode(vtkKWOptions::SelectionModeMultiple); }; //---------------------------------------------------------------------------- void vtkKWTree::SetSelectionChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->SelectionChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWTree::InvokeSelectionChangedCommand() { this->InvokeObjectMethodCommand(this->SelectionChangedCommand); this->InvokeEvent(vtkKWTree::SelectionChangedEvent, NULL); } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeParentChangedCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand(&this->NodeParentChangedCommand, object, method); } //---------------------------------------------------------------------------- void vtkKWTree::InvokeNodeParentChangedCommand( const char *node, const char *new_parent, const char *previous_parent) { if (this->NodeParentChangedCommand && *this->NodeParentChangedCommand && this->IsCreated()) { this->Script("%s {%s} {%s} {%s}", this->NodeParentChangedCommand, node, new_parent, previous_parent); } const char *args[3]; args[0] = node; args[1] = new_parent; args[2] = previous_parent; this->InvokeEvent(vtkKWTree::NodeParentChangedEvent, args); } //---------------------------------------------------------------------------- void vtkKWTree::SelectNode(const char *node) { if (this->IsCreated() && node && *node) { this->Script("%s selection add %s", this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- void vtkKWTree::DeselectNode(const char *node) { if (this->IsCreated() && node && *node) { this->Script("%s selection remove %s", this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- void vtkKWTree::SelectNodeChildren(const char *node) { vtksys_stl::vector children; vtksys::SystemTools::Split(this->GetNodeChildren(node), children, ' '); vtksys_stl::vector::iterator it = children.begin(); vtksys_stl::vector::iterator end = children.end(); for (; it != end; it++) { this->SelectNode((*it).c_str()); this->SelectNodeChildren((*it).c_str()); } } //---------------------------------------------------------------------------- void vtkKWTree::DeselectNodeChildren(const char *node) { vtksys_stl::vector children; vtksys::SystemTools::Split(this->GetNodeChildren(node), children, ' '); vtksys_stl::vector::iterator it = children.begin(); vtksys_stl::vector::iterator end = children.end(); for (; it != end; it++) { this->DeselectNode((*it).c_str()); this->DeselectNodeChildren((*it).c_str()); } } //---------------------------------------------------------------------------- void vtkKWTree::SelectSingleNode(const char *node) { if (this->IsCreated() && node && *node) { this->Script("%s selection set %s", this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- void vtkKWTree::ClearSelection() { if (this->IsCreated()) { this->Script("%s selection clear", this->GetWidgetName()); } } //---------------------------------------------------------------------------- const char* vtkKWTree::GetSelection() { if (this->IsCreated()) { return this->Script("%s selection get", this->GetWidgetName()); } return NULL; } //---------------------------------------------------------------------------- int vtkKWTree::HasSelection() { const char *sel = this->GetSelection(); return (sel && *sel ? 1 : 0); } //---------------------------------------------------------------------------- void vtkKWTree::AddNode(const char *parent, const char *node, const char *text) { if (!this->IsCreated() || !node) { return; } vtksys_stl::string cmd; cmd.append(this->GetWidgetName()).append(" insert end ").append(parent && *parent ? parent : "root").append(" ").append(node); if (text && *text) { const char *val = this->ConvertInternalStringToTclString( text, vtkKWCoreWidget::ConvertStringEscapeInterpretable); cmd.append(" -text \"").append(val).append("\""); } vtkKWTkUtilities::EvaluateSimpleString( this->GetApplication(), cmd.c_str()); } //---------------------------------------------------------------------------- void vtkKWTree::DeleteNode(const char *node) { if (this->IsCreated() && node && *node) { this->Script("%s delete %s", this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- void vtkKWTree::SeeNode(const char *node) { if (this->IsCreated() && node && *node) { this->Script("%s see %s", this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- void vtkKWTree::OpenNode(const char *node) { if (this->IsCreated() && node && *node) { this->Script("%s opentree %s 0", this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- void vtkKWTree::CloseNode(const char *node) { if (this->IsCreated() && node && *node) { this->Script("%s closetree %s 0", this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- int vtkKWTree::IsNodeOpen(const char *node) { if (this->IsCreated() && node && *node) { return atoi( this->Script("%s itemcget %s -open", this->GetWidgetName(), node)); } return 0; } //---------------------------------------------------------------------------- void vtkKWTree::OpenFirstNode() { if (this->IsCreated()) { this->Script("catch {%s opentree [lindex [%s nodes root] 0]}", this->GetWidgetName(), this->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWTree::CloseFirstNode() { if (this->IsCreated()) { this->Script("catch {%s closetree [lindex [%s nodes root] 0]}", this->GetWidgetName(), this->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWTree::OpenTree(const char *node) { if (this->IsCreated() && node && *node) { this->Script("%s opentree %s 1", this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- void vtkKWTree::DisplayChildNodes(const char* node) { if (this->IsCreated() && this->HasSelection() && node && *node) { const char* nodeChildren = this->GetNodeChildren(node); if(!nodeChildren || !(*nodeChildren)) { return; } vtksys_ios::ostringstream tk_cmd; //Figure out how many units in each page tk_cmd << "set scrl [" << this->GetWidgetName() <<".c cget -scrollregion]" << endl; tk_cmd << "set ymax [lindex $scrl 3]" << endl; tk_cmd << "set dy [" << this->GetWidgetName() << ".c cget -yscrollincrement]" << endl; tk_cmd << "set yv [" << this->GetWidgetName() << " yview]" << endl; tk_cmd << "set yv0 [expr {round([lindex $yv 0]*$ymax/$dy)}]" << endl; tk_cmd << "set yv1 [expr {round([lindex $yv 1]*$ymax/$dy)}]" << endl; tk_cmd << "set pageunits [expr {$yv1-$yv0}]" << endl; // Find out whether we want to scroll to display all child nodes tk_cmd << "set nodes [" << this->GetWidgetName() << " nodes " << node << "]" << endl; tk_cmd << "set len [llength $nodes]" << endl; tk_cmd << "set index [expr {$len-1}]" << endl; tk_cmd << "if { $len > $pageunits } {set index $pageunits}" << endl; tk_cmd << "Tree::_set_current_node " << this->GetWidgetName() << " [lindex $nodes $index]" << endl; tk_cmd << this->GetWidgetName() << " see [lindex $nodes $index]" << endl; this->Script(tk_cmd.str().c_str()); } } //---------------------------------------------------------------------------- void vtkKWTree::CloseTree(const char *node) { if (this->IsCreated() && node && *node) { this->Script("%s closetree %s 1", this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- int vtkKWTree::HasNode(const char *node) { if (this->IsCreated() && node && *node) { return atoi(this->Script("%s exists %s", this->GetWidgetName(), node)); } return 0; } //---------------------------------------------------------------------------- void vtkKWTree::DeleteAllNodes() { if (this->IsCreated()) { this->Script("%s delete [%s nodes root]", this->GetWidgetName(), this->GetWidgetName()); } } //---------------------------------------------------------------------------- void vtkKWTree::DeleteNodeChildren(const char *node) { if (this->IsCreated()) { this->Script("%s delete [%s nodes %s]", this->GetWidgetName(), this->GetWidgetName(), node); } } //---------------------------------------------------------------------------- const char* vtkKWTree::GetNodeChildren(const char *node) { if (this->IsCreated() && node && *node) { return this->Script("%s nodes %s", this->GetWidgetName(), node); } return NULL; } //---------------------------------------------------------------------------- const char* vtkKWTree::GetNodeParent(const char *node) { if (this->IsCreated() && node && *node) { return this->Script("%s parent %s", this->GetWidgetName(), node); } return NULL; } //---------------------------------------------------------------------------- int vtkKWTree::IsNodeAncestor(const char *ancestor, const char *node) { if (this->IsCreated() && ancestor && *ancestor && node && *node) { vtksys_stl::string parent(this->GetNodeParent(node)); if (!strcmp(parent.c_str(), ancestor)) { return 1; } return this->IsNodeAncestor(ancestor, parent.c_str()); } return 0; } //---------------------------------------------------------------------------- void vtkKWTree::MoveNode(const char *node, const char *new_parent, int pos) { if (this->IsCreated() && node && *node && new_parent && *new_parent) { this->Script("%s move %s %s %d", this->GetWidgetName(), new_parent, node, pos); } } //---------------------------------------------------------------------------- const char* vtkKWTree::GetNodeUserData(const char *node) { if (this->IsCreated() && node && *node) { const char *data = this->Script("%s itemcget %s -data", this->GetWidgetName(), node); return this->UseRawNodeUserData ? data : this->ConvertTclStringToInternalString(data); } return NULL; } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeUserData(const char *node, const char *data) { if (this->IsCreated() && node && *node && data) { const char *val = this->UseRawNodeUserData ? data : this->ConvertInternalStringToTclString( data, vtkKWCoreWidget::ConvertStringEscapeInterpretable); this->Script("%s itemconfigure %s -data \"%s\"", this->GetWidgetName(), node, val); } } //---------------------------------------------------------------------------- int vtkKWTree::GetNodeUserDataAsInt(const char *node) { return atoi(this->GetNodeUserData(node)); } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeUserDataAsInt(const char *node, int data) { char buffer[256]; sprintf(buffer, "%d", data); this->SetNodeUserData(node, buffer); } //---------------------------------------------------------------------------- const char* vtkKWTree::FindNodeWithUserData( const char *parent, const char *data) { if (!data) { return NULL; } const char *children = this->GetNodeChildren(parent && *parent ? parent : "root"); if (!children || !*children) { return NULL; } vtksys_stl::vector children_list; vtksys::SystemTools::Split(children, children_list, ' '); vtksys_stl::vector::iterator end = children_list.end(); vtksys_stl::vector::iterator it = children_list.begin(); for (; it != end; it++) { const char *child_data = this->GetNodeUserData((*it).c_str()); if (child_data && !strcmp(child_data, data)) { Tcl_SetResult( this->GetApplication()->GetMainInterp(), (char*)(*it).c_str(), TCL_VOLATILE); return Tcl_GetStringResult(this->GetApplication()->GetMainInterp()); } } it = children_list.begin(); for (; it != end; it++) { const char *found = this->FindNodeWithUserData((*it).c_str(), data); if (found) { return found; } } return NULL; } //---------------------------------------------------------------------------- const char* vtkKWTree::FindNodeWithUserDataAsInt( const char *parent, int data) { char buffer[256]; sprintf(buffer, "%d", data); return this->FindNodeWithUserData(parent, buffer); } //---------------------------------------------------------------------------- const char* vtkKWTree::GetNodeText(const char *node) { if (this->IsCreated() && node && *node) { const char *text = this->Script("%s itemcget %s -text", this->GetWidgetName(), node); return this->UseRawNodeText ? text : this->ConvertTclStringToInternalString(text); } return NULL; } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeText(const char *node, const char *text) { if (this->IsCreated() && node && *node && text) { const char *val = this->UseRawNodeText ? text : this->ConvertInternalStringToTclString( text, vtkKWCoreWidget::ConvertStringEscapeInterpretable); this->Script("%s itemconfigure %s -text \"%s\"", this->GetWidgetName(), node, val); } } //---------------------------------------------------------------------------- const char* vtkKWTree::GetNodeFont(const char *node) { if (this->IsCreated() && node && *node) { return this->ConvertTclStringToInternalString( this->Script("%s itemcget %s -font", this->GetWidgetName(), node)); } return NULL; } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeFont(const char *node, const char *font) { if (this->IsCreated() && node && *node && font) { const char *val = this->ConvertInternalStringToTclString( font, vtkKWCoreWidget::ConvertStringEscapeInterpretable); this->Script("%s itemconfigure %s -font \"%s\"", this->GetWidgetName(), node, val); } } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeFontWeightToBold(const char *node) { if (this->IsCreated() && node && *node) { char new_font[1024]; vtksys_stl::string font(this->GetNodeFont(node)); vtkKWTkUtilities::ChangeFontWeightToBold( this->GetApplication()->GetMainInterp(), font.c_str(), new_font); this->SetNodeFont(node, new_font); } } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeFontWeightToNormal(const char *node) { if (this->IsCreated() && node && *node) { char new_font[1024]; vtksys_stl::string font(this->GetNodeFont(node)); vtkKWTkUtilities::ChangeFontWeightToNormal( this->GetApplication()->GetMainInterp(), font.c_str(), new_font); this->SetNodeFont(node, new_font); } } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeFontSlantToItalic(const char *node) { if (this->IsCreated() && node && *node) { char new_font[1024]; vtksys_stl::string font(this->GetNodeFont(node)); vtkKWTkUtilities::ChangeFontSlantToItalic( this->GetApplication()->GetMainInterp(), font.c_str(), new_font); this->SetNodeFont(node, new_font); } } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeFontSlantToRoman(const char *node) { if (this->IsCreated() && node && *node) { char new_font[1024]; vtksys_stl::string font(this->GetNodeFont(node)); vtkKWTkUtilities::ChangeFontSlantToRoman( this->GetApplication()->GetMainInterp(), font.c_str(), new_font); this->SetNodeFont(node, new_font); } } //---------------------------------------------------------------------------- int vtkKWTree::GetNodeSelectableFlag(const char *node) { if (this->IsCreated() && node && *node) { return atoi(this->Script("%s itemcget %s -selectable", this->GetWidgetName(), node)); } return 0; } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeSelectableFlag(const char *node, int flag) { if (this->IsCreated() && node && *node) { this->Script("%s itemconfigure %s -selectable %d", this->GetWidgetName(), node, flag); } } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeWindow(const char *node, vtkKWWidget *w) { if (this->IsCreated() && node && *node && w && w->IsCreated()) { this->Script("%s itemconfigure %s -window %s", this->GetWidgetName(), node, w->GetWidgetName()); } } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWTree::GetNodeWindow(const char *node) { if (this->IsCreated() && node && *node) { const char *window = this->Script("%s itemcget %s -window", this->GetWidgetName(), node); return this->GetChildWidgetWithName(window); } return NULL; } //---------------------------------------------------------------------------- void vtkKWTree::DeleteAllNodeWindows(const char *parent) { const char *children = this->GetNodeChildren(parent && *parent ? parent : "root"); if (!children || !*children) { return; } vtksys_stl::vector children_list; vtksys::SystemTools::Split(children, children_list, ' '); vtksys_stl::vector::iterator end = children_list.end(); vtksys_stl::vector::iterator it = children_list.begin(); for (; it != end; it++) { const char *node = (*it).c_str(); vtkKWWidget *window = this->GetNodeWindow(node); if (window) { this->SetNodeWindow(node, NULL); window->SetParent(NULL); } this->DeleteAllNodeWindows(node); } } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeImageToPredefinedIcon(const char *node, int icon_index) { vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImage(icon_index); this->SetNodeImageToIcon(node, icon); icon->Delete(); } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeImageToIcon(const char *node, vtkKWIcon* icon) { if (icon) { this->SetNodeImageToPixels( node, icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize()); } } //---------------------------------------------------------------------------- void vtkKWTree::SetNodeImageToPixels(const char *node, const unsigned char* pixels, int width, int height, int pixel_size, unsigned long buffer_length) { if (!this->IsCreated() || !node || !*node || !pixels) { return; } // Use the prev pic, or create a new one int had_no_image = 0; vtksys_stl::string image_name( this->Script("%s itemcget %s -image", this->GetWidgetName(), node)); if (!image_name.size()) { image_name = this->GetWidgetName(); image_name += "_"; image_name += node; had_no_image = 1; } if (!vtkKWTkUtilities::UpdatePhoto(this->GetApplication(), image_name.c_str(), pixels, width, height, pixel_size, buffer_length)) { vtkWarningMacro( << "Error updating Tk photo " << image_name.c_str()); } if (had_no_image) { this->Script("%s itemconfigure %s -image {%s}", this->GetWidgetName(), node, image_name.c_str()); } } //---------------------------------------------------------------------------- int vtkKWTree::GetNodePadX(const char *node) { if (this->IsCreated() && node && *node) { return atoi(this->Script("%s itemcget %s -padx", this->GetWidgetName(), node)); } return 0; } //---------------------------------------------------------------------------- void vtkKWTree::SetNodePadX(const char *node, int arg) { if (this->IsCreated() && node && *node) { this->Script("%s itemconfigure %s -padx %d", this->GetWidgetName(), node, arg); } } //---------------------------------------------------------------------------- void vtkKWTree::SetWidth(int width) { this->SetConfigurationOptionAsInt("-width", width); } //---------------------------------------------------------------------------- int vtkKWTree::GetWidth() { return this->GetConfigurationOptionAsInt("-width"); } //---------------------------------------------------------------------------- void vtkKWTree::SetHeight(int height) { this->SetConfigurationOptionAsInt("-height", height); } //---------------------------------------------------------------------------- int vtkKWTree::GetHeight() { return this->GetConfigurationOptionAsInt("-height"); } //---------------------------------------------------------------------------- void vtkKWTree::SetEnableReparenting(int flag) { if (this->EnableReparenting == flag) { return; } this->EnableReparenting = flag; this->UpdateDragAndDrop(); this->Modified(); } //---------------------------------------------------------------------------- void vtkKWTree::SetRedrawOnIdle(int redraw) { this->SetConfigurationOptionAsInt("-redraw", redraw); } //---------------------------------------------------------------------------- int vtkKWTree::GetRedrawOnIdle() { return this->GetConfigurationOptionAsInt("-redraw"); } //---------------------------------------------------------------------------- void vtkKWTree::SetLinesVisibility(int arg) { this->SetConfigurationOptionAsInt("-showlines", arg); } //---------------------------------------------------------------------------- int vtkKWTree::GetLinesVisibility() { return this->GetConfigurationOptionAsInt("-showlines"); } //---------------------------------------------------------------------------- void vtkKWTree::SetSelectionFill(int arg) { this->SetConfigurationOptionAsInt("-selectfill", arg); } //---------------------------------------------------------------------------- int vtkKWTree::GetSelectionFill() { return this->GetConfigurationOptionAsInt("-selectfill"); } //---------------------------------------------------------------------------- void vtkKWTree::GetBackgroundColor(double *r, double *g, double *b) { this->GetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWTree::GetBackgroundColor() { return this->GetConfigurationOptionAsColor("-background"); } //---------------------------------------------------------------------------- void vtkKWTree::SetBackgroundColor(double r, double g, double b) { this->SetConfigurationOptionAsColor("-background", r, g, b); } //---------------------------------------------------------------------------- void vtkKWTree::SetHighlightThickness(int width) { this->SetConfigurationOptionAsInt("-highlightthickness", width); } //---------------------------------------------------------------------------- int vtkKWTree::GetHighlightThickness() { return this->GetConfigurationOptionAsInt("-highlightthickness"); } //---------------------------------------------------------------------------- void vtkKWTree::SetBorderWidth(int width) { this->SetConfigurationOptionAsInt("-bd", width); } //---------------------------------------------------------------------------- int vtkKWTree::GetBorderWidth() { return this->GetConfigurationOptionAsInt("-bd"); } //---------------------------------------------------------------------------- void vtkKWTree::SetRelief(int relief) { this->SetConfigurationOption( "-relief", vtkKWOptions::GetReliefAsTkOptionValue(relief)); } void vtkKWTree::SetReliefToRaised() { this->SetRelief(vtkKWOptions::ReliefRaised); }; void vtkKWTree::SetReliefToSunken() { this->SetRelief(vtkKWOptions::ReliefSunken); }; void vtkKWTree::SetReliefToFlat() { this->SetRelief(vtkKWOptions::ReliefFlat); }; void vtkKWTree::SetReliefToRidge() { this->SetRelief(vtkKWOptions::ReliefRidge); }; void vtkKWTree::SetReliefToSolid() { this->SetRelief(vtkKWOptions::ReliefSolid); }; void vtkKWTree::SetReliefToGroove() { this->SetRelief(vtkKWOptions::ReliefGroove); }; //---------------------------------------------------------------------------- int vtkKWTree::GetRelief() { return vtkKWOptions::GetReliefFromTkOptionValue( this->GetConfigurationOption("-relief")); } //---------------------------------------------------------------------------- void vtkKWTree::SetPadX(int arg) { this->SetConfigurationOptionAsInt("-padx", arg); } //---------------------------------------------------------------------------- int vtkKWTree::GetPadX() { return this->GetConfigurationOptionAsInt("-padx"); } //---------------------------------------------------------------------------- void vtkKWTree::SetDeltaX(int arg) { this->SetConfigurationOptionAsInt("-deltax", arg); } //---------------------------------------------------------------------------- int vtkKWTree::GetDeltaX() { return this->GetConfigurationOptionAsInt("-deltax"); } //---------------------------------------------------------------------------- void vtkKWTree::SetDeltaY(int arg) { this->SetConfigurationOptionAsInt("-deltay", arg); } //---------------------------------------------------------------------------- int vtkKWTree::GetDeltaY() { return this->GetConfigurationOptionAsInt("-deltay"); } //---------------------------------------------------------------------------- void vtkKWTree::GetSelectionBackgroundColor(double *r, double *g, double *b) { vtkKWTkUtilities::GetOptionColor(this, "-selectbackground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWTree::GetSelectionBackgroundColor() { double *rgb = &this->Internals->SelectionBackgroundColorTemp[0]; this->GetSelectionBackgroundColor(rgb, rgb + 1, rgb + 2); return rgb; } //---------------------------------------------------------------------------- void vtkKWTree::SetSelectionBackgroundColor(double r, double g, double b) { vtkKWTkUtilities::SetOptionColor(this, "-selectbackground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWTree::GetSelectionForegroundColor(double *r, double *g, double *b) { vtkKWTkUtilities::GetOptionColor(this, "-selectforeground", r, g, b); } //---------------------------------------------------------------------------- double* vtkKWTree::GetSelectionForegroundColor() { double *rgb = &this->Internals->SelectionForegroundColorTemp[0]; this->GetSelectionForegroundColor(rgb, rgb + 1, rgb + 2); return rgb; } //---------------------------------------------------------------------------- void vtkKWTree::SetSelectionForegroundColor(double r, double g, double b) { vtkKWTkUtilities::SetOptionColor(this, "-selectforeground", r, g, b); } //---------------------------------------------------------------------------- void vtkKWTree::SetOpenCommand(vtkObject *object, const char *method) { if (!this->IsCreated()) { return; } char *command = NULL; this->SetObjectMethodCommand(&command, object, method); this->SetConfigurationOption("-opencmd", command); delete [] command; } //---------------------------------------------------------------------------- void vtkKWTree::SetCloseCommand(vtkObject *object, const char *method) { if (!this->IsCreated()) { return; } char *command = NULL; this->SetObjectMethodCommand(&command, object, method); this->SetConfigurationOption("-closecmd", command); delete [] command; } //---------------------------------------------------------------------------- void vtkKWTree::SetBindText(const char *event, vtkObject *object, const char *method) { if (!this->IsCreated() || !event) { return; } char *command = NULL; this->SetObjectMethodCommand(&command, object, method); this->Script("%s bindText %s {%s}", this->GetWidgetName(), event, command); delete [] command; } //---------------------------------------------------------------------------- void vtkKWTree::SetDoubleClickOnNodeCommand(vtkObject *object, const char *method) { this->SetBindText("", object, method); } //---------------------------------------------------------------------------- void vtkKWTree::SetSingleClickOnNodeCommand(vtkObject *object, const char *method) { this->SetBindText("", object, method); } //---------------------------------------------------------------------------- void vtkKWTree::SetRightClickOnNodeCommand(vtkObject *object, const char *method) { this->SetBindText("", object, method); #ifdef __APPLE__ this->SetBindText("", object, method); #endif } //---------------------------------------------------------------------------- void vtkKWTree::DropOverNodeCallback( const char *treepath, const char *dragsourcepath, const char *where, const char *op, const char *datatype, const char *data) { // Check that we are really dropping on our own widget if (!treepath || strcmp(treepath, this->GetWidgetName())) { return; } // Check that we are really dragging from our own widget if (!dragsourcepath || strcmp(dragsourcepath, this->Internals->TreeCanvas->GetWidgetName())) { return; } // Ignore the operation type (could be default, copy, move) (void)op; // Check that we are manipulating a tree node if (!datatype || strcmp(datatype, "TREE_NODE")) { return; } // Check that the location of the drop is a node vtksys_stl::vector where_elems; vtksys::SystemTools::Split(where, where_elems, ' '); if (where_elems.size() != 2 || strcmp(where_elems[0].c_str(), "node")) { return; } vtksys_stl::string node(data); vtksys_stl::string new_parent(where_elems[1]); vtksys_stl::string previous_parent(this->GetNodeParent(node.c_str())); if (this->EnableReparenting && !this->IsNodeAncestor(node.c_str(), new_parent.c_str())) { this->MoveNode(node.c_str(), new_parent.c_str(), 0); this->OpenNode(new_parent.c_str()); this->SeeNode(node.c_str()); this->InvokeNodeParentChangedCommand( node.c_str(), new_parent.c_str(), previous_parent.c_str()); } } //---------------------------------------------------------------------------- void vtkKWTree::UpdateEnableState() { this->Superclass::UpdateEnableState(); this->SetState(this->GetEnabled()); } //---------------------------------------------------------------------------- void vtkKWTree::PrintSelf(ostream& os, vtkIndent indent) { os << indent << "EnableReparenting: " << (this->EnableReparenting ? "On" : "Off") << endl; os << indent << "UseRawNodeUserData: " << (this->UseRawNodeUserData ? "On" : "Off") << endl; os << indent << "UseRawNodeText: " << (this->UseRawNodeText ? "On" : "Off") << endl; this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWGenericRenderWindowInteractor.cxx0000644000175000017500000000540310303344160024527 0ustar domibeldomibel/*========================================================================= Copyright (c) 1998-2003 Kitware Inc. 469 Clifton Corporate Parkway, Clifton Park, NY, 12065, USA. All rights reserved. No part of this software may be reproduced, distributed, or modified, in any form or by any means, without permission in writing from Kitware Inc. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. =========================================================================*/ #include "vtkKWGenericRenderWindowInteractor.h" #include "vtkKWRenderWidget.h" #include "vtkObjectFactory.h" #include "vtkRenderWindow.h" //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWGenericRenderWindowInteractor); vtkCxxRevisionMacro(vtkKWGenericRenderWindowInteractor, "$Revision: 1.8 $"); //---------------------------------------------------------------------------- vtkKWGenericRenderWindowInteractor::vtkKWGenericRenderWindowInteractor() { this->RenderWidget = NULL; } //---------------------------------------------------------------------------- vtkKWGenericRenderWindowInteractor::~vtkKWGenericRenderWindowInteractor() { this->SetRenderWidget(NULL); } //---------------------------------------------------------------------------- void vtkKWGenericRenderWindowInteractor::SetRenderWidget( vtkKWRenderWidget *widget) { if (this->RenderWidget != widget) { // to avoid circular references this->RenderWidget = widget; if (this->RenderWidget != NULL) { this->SetRenderWindow(this->RenderWidget->GetRenderWindow()); } else { this->SetRenderWindow(NULL); } } } //---------------------------------------------------------------------------- void vtkKWGenericRenderWindowInteractor::Render() { if (this->RenderWidget) { this->RenderWidget->Render(); } else { this->Superclass::Render(); } } //---------------------------------------------------------------------------- void vtkKWGenericRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "RenderWidget: " << this->RenderWidget << endl; } kwwidgets-1.0.0~cvs20100930/vtkKWStateMachineWriter.h0000644000175000017500000000444410522464403021771 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWStateMachineWriter.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWStateMachineWriter - a state machine writer base-class. // .SECTION Description // This class is the basis for a state machine writer. // A state machine is defined by a set of states, a set of inputs and a // transition matrix that defines for each pair of (state,input) what is // the next state to assume. // .SECTION Thanks // This work is part of the National Alliance for Medical Image // Computing (NAMIC), funded by the National Institutes of Health // through the NIH Roadmap for Medical Research, Grant U54 EB005149. // Information on the National Centers for Biomedical Computing // can be obtained from http://nihroadmap.nih.gov/bioinformatics. // .SECTION See Also // vtkKWStateMachineDOTWriter vtkKWStateMachine #ifndef __vtkKWStateMachineWriter_h #define __vtkKWStateMachineWriter_h #include "vtkObject.h" #include "vtkKWWidgets.h" // Needed for export symbols directives class vtkKWStateMachine; class KWWidgets_EXPORT vtkKWStateMachineWriter : public vtkObject { public: vtkTypeRevisionMacro(vtkKWStateMachineWriter, vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get state machine to write. vtkGetObjectMacro(Input, vtkKWStateMachine); virtual void SetInput(vtkKWStateMachine*); // Description: // Set/Get if the writer should output transitions originating and leading // to the same node (self loops). vtkSetMacro(WriteSelfLoop, int); vtkGetMacro(WriteSelfLoop, int); vtkBooleanMacro(WriteSelfLoop, int); protected: vtkKWStateMachineWriter(); ~vtkKWStateMachineWriter(); vtkKWStateMachine *Input; int WriteSelfLoop; private: vtkKWStateMachineWriter(const vtkKWStateMachineWriter&); // Not implemented void operator=(const vtkKWStateMachineWriter&); // Not implemented }; #endif kwwidgets-1.0.0~cvs20100930/vtkKWComboBox.cxx0000644000175000017500000001621211076173717020320 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWComboBox.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWComboBox.h" #include "vtkObjectFactory.h" #include "vtkKWApplication.h" #include "Utilities/BWidgets/vtkKWBWidgetsInit.h" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWComboBox); vtkCxxRevisionMacro(vtkKWComboBox, "$Revision: 1.22 $"); //---------------------------------------------------------------------------- vtkKWComboBox::vtkKWComboBox() { this->Width = 20; } //---------------------------------------------------------------------------- vtkKWComboBox::~vtkKWComboBox() { } //---------------------------------------------------------------------------- void vtkKWComboBox::CreateWidget() { // Use BWidget's ComboBox class: // http://aspn.activestate.com/ASPN/docs/ActiveTcl/bwidget/contents.html vtkKWApplication *app = this->GetApplication(); vtkKWBWidgetsInit::Initialize(app ? app->GetMainInterp() : NULL); // Call the superclass to set the appropriate flags then create manually if (!vtkKWWidget::CreateSpecificTkWidget(this, "ComboBox", "-highlightthickness 0 -entrybg #ffffff")) { vtkErrorMacro("Failed creating widget " << this->GetClassName()); return; } // Design choice: we assume a keypress is meant for this widget only this->SetGenericBinding( "BwEntry", "", NULL, "::tk::CancelRepeat ; ::tk::EntryInsert %W %A; break"); this->Configure(); } //---------------------------------------------------------------------------- void vtkKWComboBox::SetValue(const char *s) { if (!this->IsAlive()) { return; } int old_state = this->GetState(); this->SetStateToNormal(); this->SetTextOption("-text", s); this->SetState(old_state); } //---------------------------------------------------------------------------- void vtkKWComboBox::AddValue(const char* value) { if (!this->IsCreated() || !value || this->HasValue(value)) { return; } this->Script("%s configure -values [concat [%s cget -values] {\"%s\"}]", this->GetWidgetName(), this->GetWidgetName(), value); } //---------------------------------------------------------------------------- void vtkKWComboBox::AddValueAsInt(int value) { char buffer[256]; sprintf(buffer, "%d", value); this->AddValue(buffer); } //---------------------------------------------------------------------------- void vtkKWComboBox::ReplaceNthValue( int idx, const char *value ) { if (!this->IsCreated() || !value || this->HasValue(value)) { return; } if (idx < 0 || idx >= this->GetNumberOfValues()) { vtkErrorMacro( "This combobox has only " << this->GetNumberOfValues() << " elements. Index " << idx << " is out of range"); return; } this->Script("%s configure -values [lreplace [%s cget -values] %d %d %s]", this->GetWidgetName(), this->GetWidgetName(), idx, idx, value); } //---------------------------------------------------------------------------- int vtkKWComboBox::GetNumberOfValues() { if (!this->IsCreated()) { return 0; } return atoi( this->Script("llength [%s cget -values]", this->GetWidgetName())); } //---------------------------------------------------------------------------- void vtkKWComboBox::DeleteAllValues() { if (!this->IsCreated()) { return; } this->Script("%s configure -values {}", this->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWComboBox::DeleteValue(int idx) { if (!this->IsCreated()) { return; } if (idx < 0 || idx >= this->GetNumberOfValues()) { vtkErrorMacro( "This combobox has only " << this->GetNumberOfValues() << " elements. Index " << idx << " is out of range"); return; } this->Script("%s configure -values [lreplace [%s cget -values] %d %d]", this->GetWidgetName(), this->GetWidgetName(), idx, idx); } //---------------------------------------------------------------------------- const char* vtkKWComboBox::GetValueFromIndex(int idx) { if (!this->IsCreated()) { return NULL; } if (idx < 0 || idx >= this->GetNumberOfValues()) { vtkErrorMacro( "This combobox has only " << this->GetNumberOfValues() << " elements. Index " << idx << " is out of range"); return NULL; } return this->Script("lindex [%s cget -values] %d", this->GetWidgetName(), idx); } //---------------------------------------------------------------------------- int vtkKWComboBox::HasValue(const char* value) { return this->GetValueIndex(value) < 0 ? 0 : 1; } //---------------------------------------------------------------------------- int vtkKWComboBox::GetValueIndex(const char* value) { if (!this->IsCreated() || !value) { return -1; } return atoi(this->Script("lsearch [%s cget -values] {%s}", this->GetWidgetName(), value)); } //---------------------------------------------------------------------------- void vtkKWComboBox::SetCommand(vtkObject *object, const char *method) { this->Superclass::SetCommand(object, method); if (this->IsCreated()) { char *command = NULL; this->SetObjectMethodCommand(&command, this, "ValueCallback"); this->SetConfigurationOption("-command", command); this->SetConfigurationOption("-modifycmd", command); delete [] command; } } //---------------------------------------------------------------------------- void vtkKWComboBox::UpdateEnableState() { // We need to bypass the superclass (vtkKWEntry) UpdateEnableState // because it sets up Tk options that are not supported by this Tk widget. this->vtkKWCoreWidget::UpdateEnableState(); this->SetState(this->GetEnabled()); if (this->IsCreated()) { this->SetConfigurationOptionAsInt("-editable", this->ReadOnly ? 0 : 1); } } //---------------------------------------------------------------------------- void vtkKWComboBox::SetListboxWidth(int n) { if (this->IsCreated()) { this->SetConfigurationOptionAsInt("-listboxwidth", n); } } //---------------------------------------------------------------------------- int vtkKWComboBox::GetListboxWidth() { if (this->IsCreated()) { return this->GetConfigurationOptionAsInt("-listboxwidth"); } return 0; } //---------------------------------------------------------------------------- void vtkKWComboBox::SetBackgroundColor(double r, double g, double b) { this->Superclass::SetBackgroundColor(r, g, b); this->SetConfigurationOptionAsColor("-entrybg", r, g, b); } //---------------------------------------------------------------------------- void vtkKWComboBox::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWRadioButtonSet.cxx0000644000175000017500000000521210414053200021467 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWRadioButtonSet.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWRadioButtonSet.h" #include "vtkKWRadioButton.h" #include "vtkObjectFactory.h" //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWRadioButtonSet); vtkCxxRevisionMacro(vtkKWRadioButtonSet, "$Revision: 1.23 $"); //---------------------------------------------------------------------------- vtkKWRadioButton* vtkKWRadioButtonSet::GetWidget(int id) { return static_cast(this->GetWidgetInternal(id)); } //---------------------------------------------------------------------------- vtkKWRadioButton* vtkKWRadioButtonSet::AddWidget(int id) { return static_cast(this->InsertWidgetInternal( id, this->GetNumberOfWidgets())); } //---------------------------------------------------------------------------- vtkKWRadioButton* vtkKWRadioButtonSet::InsertWidget(int id, int pos) { return static_cast(this->InsertWidgetInternal( id, pos)); } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWRadioButtonSet::InsertWidgetInternal( int id, int pos) { vtkKWRadioButton *widget = static_cast( this->Superclass::InsertWidgetInternal(id, pos)); if (widget) { widget->SetValueAsInt(id); } return widget; } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWRadioButtonSet::AllocateAndCreateWidget() { vtkKWRadioButton *widget = vtkKWRadioButton::New(); widget->SetParent(this); widget->Create(); // For convenience, all radiobuttons share the same var name if (this->GetNumberOfWidgets()) { vtkKWRadioButton *first = this->GetWidget(this->GetIdOfNthWidget(0)); if (first) { widget->SetVariableName(first->GetVariableName()); } } return static_cast(widget); } //---------------------------------------------------------------------------- void vtkKWRadioButtonSet::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/vtkKWTkUtilities.cxx0000644000175000017500000030117111205023030021033 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTkUtilities.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWTkUtilities.h" #include "vtkKWCoreWidget.h" #include "vtkKWApplication.h" #include "vtkKWResourceUtilities.h" #include "vtkKWIcon.h" #include "vtkKWColorPickerDialog.h" #include "vtkKWColorPickerWidget.h" #include "vtkObjectFactory.h" #include "vtkTclUtil.h" #include "vtkWindows.h" #include "X11/Xutil.h" #include "vtkConfigure.h" #include #include // This has to be here because on HP varargs are included in // tcl.h and they have different prototypes for va_start so // the build fails. Defining HAS_STDARG prevents that. #if defined(__hpux) && !defined(HAS_STDARG) # define HAS_STDARG #endif #include "vtkTk.h" #if defined(VTK_USE_CARBON) || defined(VTK_USE_COCOA) #elif !defined(_WIN32) #include "vtkXOpenGLRenderWindow.h" #endif //---------------------------------------------------------------------------- vtkStandardNewMacro(vtkKWTkUtilities); vtkCxxRevisionMacro(vtkKWTkUtilities, "$Revision: 1.103 $"); //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::GetTclNameFromPointer( Tcl_Interp *interp, vtkObject *obj) { if (!interp || !obj) { return NULL; } vtkTclGetObjectFromPointer(interp, (void *)obj, obj->GetClassName()); return Tcl_GetStringResult(interp); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::GetTclNameFromPointer( vtkKWApplication *app, vtkObject *obj) { if (!app) { return NULL; } return vtkKWTkUtilities::GetTclNameFromPointer( app->GetMainInterp(), obj); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::EvaluateString( Tcl_Interp *interp, const char* format, ...) { va_list var_args1, var_args2; va_start(var_args1, format); va_start(var_args2, format); const char* result = vtkKWTkUtilities::EvaluateStringFromArgs( interp, format, var_args1, var_args2); va_end(var_args1); va_end(var_args2); return result; } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::EvaluateString( vtkKWApplication *app, const char* format, ...) { va_list var_args1, var_args2; va_start(var_args1, format); va_start(var_args2, format); const char* result = vtkKWTkUtilities::EvaluateStringFromArgs( app, format, var_args1, var_args2); va_end(var_args1); va_end(var_args2); return result; } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::EvaluateStringFromArgs( vtkKWApplication *app, const char* format, va_list var_args1, va_list var_args2) { if (!app) { return NULL; } return vtkKWTkUtilities::EvaluateStringFromArgsInternal( app->GetMainInterp(), app, format, var_args1, var_args2); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::EvaluateStringFromArgs( Tcl_Interp *interp, const char* format, va_list var_args1, va_list var_args2) { return vtkKWTkUtilities::EvaluateStringFromArgsInternal( interp, NULL, format, var_args1, var_args2); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::EvaluateStringFromArgsInternal( Tcl_Interp *interp, vtkObject *obj, const char* format, va_list var_args1, va_list var_args2) { const int buffer_on_stack_length = 1600; char buffer_on_stack[buffer_on_stack_length]; char* buffer = buffer_on_stack; // Estimate the length of the result string. Never underestimates. int length = vtksys::SystemTools::EstimateFormatLength(format, var_args1); // If our stack-allocated buffer is too small, allocate on one on // the heap that will be large enough. if(length > buffer_on_stack_length - 1) { buffer = new char[length + 1]; } // Print to the buffer. vsprintf(buffer, format, var_args2); // Evaluate the string in Tcl. const char *res = vtkKWTkUtilities::EvaluateSimpleStringInternal(interp, obj, buffer); // Free the buffer from the heap if we allocated it. if (buffer != buffer_on_stack) { delete [] buffer; } // Convert the Tcl result to its string representation. return res; } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::EvaluateSimpleString( vtkKWApplication *app, const char* str) { if (!app) { return NULL; } return vtkKWTkUtilities::EvaluateSimpleStringInternal( app->GetMainInterp(), app, str); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::EvaluateSimpleString( Tcl_Interp *interp, const char* str) { return vtkKWTkUtilities::EvaluateSimpleStringInternal( interp, NULL, str); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::EvaluateSimpleStringInternal( Tcl_Interp *interp, vtkObject *obj, const char *str) { static vtksys_stl::string err; static vtksys_stl::string errInfo; if (Tcl_GlobalEval(interp, str) != TCL_OK && obj) { err = Tcl_GetStringResult(interp); // need to save now errInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG ); // get the error message too vtkErrorWithObjectMacro( obj, "\n Script: \n" << str << "\n Returned Error on line " << interp->errorLine << ": \n" << err.c_str() << "\nStack trace: \n" << errInfo.c_str() << endl); return err.c_str(); } // Convert the Tcl result to its string representation. return Tcl_GetStringResult(interp); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::EvaluateEncodedString( Tcl_Interp *interp, const unsigned char *buffer, unsigned long length, unsigned long decoded_length) { // Is the data encoded (zlib and/or base64) ? unsigned char *decoded_buffer = NULL; if (length && length != decoded_length) { if (!vtkKWResourceUtilities::DecodeBuffer( buffer, length, &decoded_buffer, decoded_length)) { vtkGenericWarningMacro(<<"Error while decoding library"); return "Error while decoding library"; } buffer = decoded_buffer; length = decoded_length; } if (buffer && Tcl_EvalEx(interp, (const char*)buffer, length, TCL_EVAL_GLOBAL)!=TCL_OK) { vtkGenericWarningMacro( << " Failed to initialize. Error:" << Tcl_GetStringResult(interp)); } if (decoded_buffer) { delete [] decoded_buffer; } return Tcl_GetStringResult(interp); } //---------------------------------------------------------------------------- void vtkKWTkUtilities::CreateObjectMethodCommand( Tcl_Interp *interp, char **command, vtkObject *object, const char *method) { if (*command) { delete [] *command; *command = NULL; } const char *object_name = NULL; if (object) { vtkKWObject *kw_object = vtkKWObject::SafeDownCast(object); if (kw_object) { object_name = kw_object->GetTclName(); } else { if (!interp) { vtkErrorWithObjectMacro( object, "Attempt to create a Tcl instance without a Tcl interpreter!"); } else { object_name = vtkKWTkUtilities::GetTclNameFromPointer(interp, object); } } } size_t object_len = object_name ? strlen(object_name) + 1 : 0; size_t method_len = method ? strlen(method) : 0; *command = new char[object_len + method_len + 1]; if (object_name && method) { sprintf(*command, "%s %s", object_name, method); } else if (object_name) { sprintf(*command, "%s", object_name); } else if (method) { sprintf(*command, "%s", method); } (*command)[object_len + method_len] = '\0'; } //---------------------------------------------------------------------------- void vtkKWTkUtilities::CreateObjectMethodCommand( vtkKWApplication *, char **command, vtkObject *object, const char *method) { vtkKWTkUtilities::CreateObjectMethodCommand( vtkKWApplication::GetMainInterp(), command, object, method); } //---------------------------------------------------------------------------- void vtkKWTkUtilities::GetRGBColor(Tcl_Interp *interp, const char *widget, const char *color, double *r, double *g, double *b) { if (!interp || !widget || !color || !*color || !r || !g || !b) { return; } vtksys_ios::ostringstream command; command << "winfo rgb " << widget << " " << color; if (Tcl_GlobalEval(interp, command.str().c_str()) != TCL_OK) { vtkGenericWarningMacro( << "Unable to get RGB color: " << Tcl_GetStringResult(interp)); return; } int rr, gg, bb; if (sscanf(Tcl_GetStringResult(interp), "%d %d %d", &rr, &gg, &bb) == 3) { *r = static_cast(rr) / 65535.0; *g = static_cast(gg) / 65535.0; *b = static_cast(bb) / 65535.0; } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::GetRGBColor(vtkKWWidget *widget, const char *color, double *r, double *g, double *b) { if (!widget || !widget->IsCreated()) { return; } vtkKWTkUtilities::GetRGBColor(widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), color, r, g, b); } //---------------------------------------------------------------------------- void vtkKWTkUtilities::GetOptionColor(Tcl_Interp *interp, const char *widget, const char *option, double *r, double *g, double *b) { if (!interp || !widget || !option || !r || !g || !b) { return; } vtksys_ios::ostringstream command; command << widget << " cget " << option; if (Tcl_GlobalEval(interp, command.str().c_str()) != TCL_OK) { vtkGenericWarningMacro( << "Unable to get " << option << " option: " << Tcl_GetStringResult(interp)); return; } vtkKWTkUtilities::GetRGBColor( interp, widget, Tcl_GetStringResult(interp), r, g, b); } //---------------------------------------------------------------------------- void vtkKWTkUtilities::GetOptionColor(vtkKWWidget *widget, const char *option, double *r, double *g, double *b) { if (!widget || !widget->IsCreated()) { return; } vtkKWTkUtilities::GetOptionColor( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), option, r, g, b); } //---------------------------------------------------------------------------- double* vtkKWTkUtilities::GetOptionColor(vtkKWWidget *widget, const char *option) { static double rgb[3]; vtkKWTkUtilities::GetOptionColor( widget, option, rgb, rgb + 1, rgb + 2); return rgb; } //---------------------------------------------------------------------------- void vtkKWTkUtilities::GetDefaultOptionColor(Tcl_Interp *interp, const char *widget, const char *option, double *r, double *g, double *b) { if (!interp || !widget || !option || !r || !g || !b) { return; } vtksys_ios::ostringstream command; command << "lindex [" << widget << " config " << option << "] 3"; if (Tcl_GlobalEval(interp, command.str().c_str()) != TCL_OK) { vtkGenericWarningMacro( << "Unable to get " << option << " option: " << Tcl_GetStringResult(interp)); return; } vtkKWTkUtilities::GetRGBColor( interp, widget, Tcl_GetStringResult(interp), r, g, b); } //---------------------------------------------------------------------------- void vtkKWTkUtilities::GetDefaultOptionColor(vtkKWWidget *widget, const char *option, double *r, double *g, double *b) { if (!widget || !widget->IsCreated()) { return; } vtkKWTkUtilities::GetDefaultOptionColor( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), option, r, g, b); } //---------------------------------------------------------------------------- double* vtkKWTkUtilities::GetDefaultOptionColor(vtkKWWidget *widget, const char *option) { static double rgb[3]; vtkKWTkUtilities::GetDefaultOptionColor( widget, option, rgb, rgb + 1, rgb + 2); return rgb; } //---------------------------------------------------------------------------- void vtkKWTkUtilities::SetOptionColor(Tcl_Interp *interp, const char *widget, const char *option, double r, double g, double b) { if (!interp || !widget || !option || !(r >= 0.0 && r <= 1.0 && g >= 0.0 && g <= 1.0 && b >= 0.0 && b <= 1.0)) { return; } char color[10]; sprintf(color, "#%02x%02x%02x", (int)(r * 255.0), (int)(g * 255.0), (int)(b * 255.0)); vtksys_ios::ostringstream command; command << widget << " configure " << option << " " << color; if (Tcl_GlobalEval(interp, command.str().c_str()) != TCL_OK) { vtkGenericWarningMacro( << "Unable to set " << option << " option: " << Tcl_GetStringResult(interp)); } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::SetOptionColor(vtkKWWidget *widget, const char *option, double r, double g, double b) { if (!widget || !widget->IsCreated()) { return; } vtkKWTkUtilities::SetOptionColor(widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), option, r, g, b); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::QueryUserForColor( vtkKWApplication *app, vtkKWWidget *dialog_parent, const char *dialog_title, double in_r, double in_g, double in_b, double *out_r, double *out_g, double *out_b) { if (!app) { return 0; } Tcl_Interp *interp = app->GetMainInterp(); vtkKWColorPickerDialog *dlg = app->GetColorPickerDialog(); if (!dlg) { return 0; } dlg->SetTitle(dialog_title); dlg->SetDisplayPositionToPointer(); dlg->GetColorPickerWidget()->SetCurrentColorAsRGB(in_r, in_g, in_b); dlg->GetColorPickerWidget()->SetNewColorAsRGB(in_r, in_g, in_b); double r, g, b; int ok = dlg->Invoke(); if (ok) { dlg->GetColorPickerWidget()->GetNewColorAsRGB(r, g, b); } else { r = in_r; g = in_g; b = in_b; } if (out_r) { *out_r = r; } if (out_g) { *out_g = g; } if (out_b) { *out_b = b; } return ok; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetGeometry(Tcl_Interp *interp, const char *widget, int *width, int *height, int *x, int *y) { if (!interp || !widget) { return 0; } vtksys_stl::string geometry("winfo geometry "); geometry += widget; if (Tcl_GlobalEval(interp, geometry.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query widget geometry! " << widget); return 0; } int ww, wh, wx, wy; if (sscanf( Tcl_GetStringResult(interp), "%dx%d+%d+%d", &ww, &wh, &wx, &wy) != 4) { vtkGenericWarningMacro(<< "Unable to parse geometry!"); return 0; } // For some unknown reasons, "winfo geometry" can return the wrong // position for the window, if it is a toplevel (it will return (0, 0). // Check for it, and try "wm geometry" instead. if ((x || y) && (wx == 0 && wy == 0) && vtkKWTkUtilities::IsTopLevel(interp, widget)) { geometry = "wm geometry "; geometry += widget; if (Tcl_GlobalEval(interp, geometry.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query widget geometry! " << widget); return 0; } if (sscanf( Tcl_GetStringResult(interp), "%dx%d+%d+%d", &ww, &wh, &wx, &wy) != 4) { vtkGenericWarningMacro(<< "Unable to parse geometry!"); return 0; } } if (width) { *width = ww; } if (height) { *height = wh; } if (x) { *x = wx; } if (y) { *y = wy; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetGeometry(vtkKWWidget *widget, int *width, int *height, int *x, int *y) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::GetGeometry( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), width, height, x, y); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ContainsCoordinates(Tcl_Interp *interp, const char *widget, int x, int y) { if (!interp || !widget) { return 0; } int ww, wh, wx, wy; if (!vtkKWTkUtilities::GetWidgetCoordinates(interp, widget, &wx, &wy) || !vtkKWTkUtilities::GetWidgetSize(interp, widget, &ww, &wh)) { return 0; } return (x >= wx && x < (wx + ww) && y >= wy && y < (wy + wh)) ? 1 : 0; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ContainsCoordinates(vtkKWWidget *widget, int x, int y) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::ContainsCoordinates( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), x, y); } //---------------------------------------------------------------------------- vtkKWWidget* vtkKWTkUtilities::ContainsCoordinatesForSpecificType( vtkKWWidget *widget, int x, int y, const char *classname) { if (!widget || !widget->IsCreated() || !classname || !vtkKWTkUtilities::ContainsCoordinates(widget, x, y)) { return NULL; } if (widget->IsA(classname)) { return widget; } int i, nb_children = widget->GetNumberOfChildren(); for (i = 0; i < nb_children; i++) { vtkKWWidget *child = widget->GetNthChild(i); if (vtkKWTkUtilities::ContainsCoordinatesForSpecificType( child, x, y, classname)) { return child; } } return NULL; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::UpdatePhoto(Tcl_Interp *interp, const char *photo_name, const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length, int update_options) { // Check params if (!interp) { vtkGenericWarningMacro(<< "Empty interpreter"); return 0; } if (!photo_name || !photo_name[0]) { vtkGenericWarningMacro(<< "Empty photo name"); return 0; } if (!pixels) { vtkGenericWarningMacro(<< "No pixel data"); return 0; } if (width <= 0 || height <= 0) { vtkGenericWarningMacro(<< "Invalid size: " << width << "x" << height); return 0; } if (pixel_size != 3 && pixel_size != 4) { vtkGenericWarningMacro(<< "Unsupported pixel size: " << pixel_size); return 0; } // Find the photo (create it if not found) Tk_PhotoHandle photo = Tk_FindPhoto(interp, const_cast(photo_name)); if (!photo) { vtksys_ios::ostringstream create_photo; create_photo << "image create photo " << photo_name; int res = Tcl_GlobalEval(interp, create_photo.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro( << "Unable to create photo " << photo_name << ": " << Tcl_GetStringResult(interp)); return 0; } photo = Tk_FindPhoto(interp, const_cast(photo_name)); if (!photo) { vtkGenericWarningMacro(<< "Error looking up Tk photo:" << photo_name); return 0; } } Tk_PhotoSetSize( #if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION <= 4) #else interp, #endif photo, width, height); unsigned long nb_of_raw_bytes = width * height * pixel_size; // Is the data encoded (zlib and/or base64) ? unsigned char *decoded_data = NULL; if (buffer_length && buffer_length != nb_of_raw_bytes) { if (!vtkKWResourceUtilities::DecodeBuffer( pixels, buffer_length, &decoded_data, nb_of_raw_bytes)) { vtkGenericWarningMacro( << "Error while decoding pixels for photo:" << photo_name); return 0; } pixels = decoded_data; } // Tk does not seem to support transparency blending, only // Set block struct Tk_PhotoImageBlock sblock; sblock.width = width; sblock.height = height; sblock.offset[0] = 0; sblock.offset[1] = 1; sblock.offset[2] = 2; sblock.offset[3] = pixel_size > 3 ? 3 : 0; sblock.pixelSize = pixel_size; sblock.pitch = sblock.width * sblock.pixelSize; unsigned long sblock_size = sblock.pitch * sblock.height; sblock.pixelPtr = const_cast(pixels); // Tcl/Tk 8.4.8 and before still do not support transparency correctly, // they will handle only fully transparent (0) or opaque (255) // Let's blend manually over a light-gray background unsigned char *blended_pixels = NULL; int tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); if (pixel_size == 4 && (tcl_major < 8 || (tcl_major == 8 && (tcl_minor < 4 || (tcl_minor == 4 && tcl_patch_level <= 8))))) { int need_blend = 0; unsigned char *pixels_ptr = const_cast(pixels); unsigned char *pixels_ptr_end = pixels_ptr + (long)width * (long)height * (long)pixel_size; pixels_ptr += 3; while (pixels_ptr < pixels_ptr_end) { if (*pixels_ptr && *pixels_ptr != 255) { need_blend = 1; break; } pixels_ptr += pixel_size; } if (need_blend) { blended_pixels = sblock.pixelPtr = new unsigned char[sblock_size]; unsigned char *blended_pixels_ptr = blended_pixels; pixels_ptr = const_cast(pixels); while (pixels_ptr < pixels_ptr_end) { unsigned char alpha_char = *(pixels_ptr + 3); if (alpha_char && alpha_char != 255) { double alpha = static_cast(alpha_char) / 255.0; *blended_pixels_ptr++ = static_cast(212*(1-alpha) + *pixels_ptr++ * alpha); *blended_pixels_ptr++ = static_cast(208*(1-alpha) + *pixels_ptr++ * alpha); *blended_pixels_ptr++ = static_cast(200*(1-alpha) + *pixels_ptr++ * alpha); *blended_pixels_ptr++ = 255; pixels_ptr++; } else { *blended_pixels_ptr++ = *pixels_ptr++; *blended_pixels_ptr++ = *pixels_ptr++; *blended_pixels_ptr++ = *pixels_ptr++; *blended_pixels_ptr++ = *pixels_ptr++; } } } } if (update_options & vtkKWTkUtilities::UpdatePhotoOptionFlipVertical) { sblock.pitch = -sblock.pitch; sblock.pixelPtr += sblock_size + sblock.pitch; } Tk_PhotoPutBlock( #if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION <= 4) #else interp, #endif photo, &sblock, 0, 0, width, height #if !defined(USE_COMPOSITELESS_PHOTO_PUT_BLOCK) , TK_PHOTO_COMPOSITE_SET #endif ); // Free mem if (blended_pixels) { delete [] blended_pixels; } if (decoded_data) { delete [] decoded_data; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::UpdatePhoto(vtkKWApplication *app, const char *photo_name, const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length, int update_options) { if (!app) { return 0; } return vtkKWTkUtilities::UpdatePhoto( app->GetMainInterp(), photo_name, pixels, width, height, pixel_size, buffer_length, update_options); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::UpdatePhotoFromIcon(vtkKWApplication *app, const char *photo_name, vtkKWIcon *icon, int update_options) { if (!app || !icon) { return 0; } return vtkKWTkUtilities::UpdatePhoto( app->GetMainInterp(), photo_name, icon->GetData(), icon->GetWidth(), icon->GetHeight(), icon->GetPixelSize(), 0, update_options); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::UpdatePhotoFromPredefinedIcon( vtkKWApplication *app, const char *photo_name, int icon_index, int update_options) { if (!app) { return 0; } vtkKWIcon *icon = vtkKWIcon::New(); icon->SetImage(icon_index); int res = vtkKWTkUtilities::UpdatePhotoFromIcon( app, photo_name, icon, update_options); icon->Delete(); return res; } //---------------------------------------------------------------------------- void vtkKWTkUtilities::SetImageOptionToPixels( vtkKWCoreWidget *widget, const unsigned char* pixels, int width, int height, int pixel_size, unsigned long buffer_length, const char *image_option) { if (!widget->IsCreated()) { vtkWarningWithObjectMacro(widget, "Widget is not created yet !"); return; } if (!image_option || !*image_option) { image_option = "-image"; } /* if (!widget->HasConfigurationOption(image_option)) { return; } */ vtksys_stl::string image_name(widget->GetWidgetName()); image_name += "."; image_name += &image_option[1]; if (!vtkKWTkUtilities::UpdatePhoto(widget->GetApplication(), image_name.c_str(), pixels, width, height, pixel_size, buffer_length)) { vtkWarningWithObjectMacro( widget, "Error updating Tk photo " << image_name.c_str()); return; } widget->SetConfigurationOption(image_option, image_name.c_str()); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::UpdateOrLoadPhoto(Tcl_Interp *interp, const char *photo_name, const char *file_name, const char *directory, const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length) { // Try to find a PNG file with the same name in directory // or directory/Resources unsigned char *png_buffer = NULL; if (directory && file_name) { char buffer[1024]; sprintf(buffer, "%s/%s.png", directory, file_name); int found = vtksys::SystemTools::FileExists(buffer); if (!found) { sprintf(buffer, "%s/Resources/%s.png", directory, file_name); found = vtksys::SystemTools::FileExists(buffer); } if (found && vtkKWResourceUtilities::ReadPNGImage( buffer, &width, &height, &pixel_size, &png_buffer)) { pixels = png_buffer; buffer_length = 0; } } // Otherwise use the provided data int res = vtkKWTkUtilities::UpdatePhoto( interp, (photo_name ? photo_name : file_name), pixels, width, height, pixel_size, buffer_length); if (png_buffer) { delete [] png_buffer; } return res; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::UpdateOrLoadPhoto(vtkKWApplication *app, const char *photo_name, const char *file_name, const char *directory, const unsigned char *pixels, int width, int height, int pixel_size, unsigned long buffer_length) { if (!app) { return 0; } return vtkKWTkUtilities::UpdateOrLoadPhoto( app->GetMainInterp(), photo_name, file_name, directory, pixels, width, height, pixel_size, buffer_length); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::FindPhoto(Tcl_Interp *interp, const char *photo_name) { return Tk_FindPhoto(interp,const_cast(photo_name)) ? 1 : 0; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::FindPhoto(vtkKWApplication *app, const char *photo_name) { if (!app) { return 0; } return vtkKWTkUtilities::FindPhoto(app->GetMainInterp(), photo_name); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetPhotoHeight(Tcl_Interp *interp, const char *photo_name) { // Find the photo Tk_PhotoHandle photo = Tk_FindPhoto(interp, const_cast(photo_name)); if (!photo) { vtkGenericWarningMacro(<< "Error looking up Tk photo:" << photo_name); return 0; } // Return height int width, height; Tk_PhotoGetSize(photo, &width, &height); return height; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetPhotoHeight(vtkKWApplication *app, const char *photo_name) { if (!app) { return 0; } return vtkKWTkUtilities::GetPhotoHeight( app->GetMainInterp(), photo_name); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetPhotoHeight(vtkKWWidget *widget) { if (!widget || !widget->IsCreated()) { return 0; } Tcl_Interp *interp = widget->GetApplication()->GetMainInterp(); // Retrieve -image option vtksys_stl::string cmd(widget->GetWidgetName()); cmd += " cget -image"; if (Tcl_GlobalEval(interp, cmd.c_str()) != TCL_OK) { vtkGenericWarningMacro( << "Unable to get -image option: " << Tcl_GetStringResult(interp)); return 0; } // No -image ? const char *result = Tcl_GetStringResult(interp); if (!result || !*result) { return 0; } // Get size vtksys_stl::string image_name(result); return vtkKWTkUtilities::GetPhotoHeight(interp, image_name.c_str()); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetPhotoWidth(Tcl_Interp *interp, const char *photo_name) { // Find the photo Tk_PhotoHandle photo = Tk_FindPhoto(interp, const_cast(photo_name)); if (!photo) { vtkGenericWarningMacro(<< "Error looking up Tk photo:" << photo_name); return 0; } // Return width int width, height; Tk_PhotoGetSize(photo, &width, &height); return width; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetPhotoWidth(vtkKWApplication *app, const char *photo_name) { if (!app) { return 0; } return vtkKWTkUtilities::GetPhotoWidth( app->GetMainInterp(), photo_name); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetRealActualFont(Tcl_Interp *interp, const char *font, char *real_font) { vtksys_stl::string script; int res, tcl_major, tcl_minor, tcl_patch_level; Tcl_GetVersion(&tcl_major, &tcl_minor, &tcl_patch_level, NULL); if (tcl_major < 8 || (tcl_major == 8 && tcl_minor < 5)) { script = "font actual \""; script += font; script += "\""; res = Tcl_GlobalEval(interp, script.c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to get actual font! (" << Tcl_GetStringResult(interp) << ")"); return 0; } } else { // This is a fix for Tcl/Tk 8.5 // "font actual" does not retrieve *exactly* the right font size, // whereas "font configure" does but fails at retrieving the proper font // family! Let's mix both. script = "if {[lsearch -exact [font names] \""; script += font; script += "\"] >= 0} { unset -nocomplain __tmp__; eval array set __tmp__ [list [font actual \""; script += font; script += "\"]]; set __tmp__(-size) [font configure \""; script += font; script += "\" -size]; array get __tmp__ } else { if {[llength \""; script += font; script += "\"] != 12} { font actual \""; script += font; script += "\" } else { unset -nocomplain __tmp__; set __tmp__ \""; script += font; script += "\" }}"; res = Tcl_GlobalEval(interp, script.c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to fix -size attribute! (" << Tcl_GetStringResult(interp) << ")"); return 0; } } strcpy(real_font, Tcl_GetStringResult(interp)); return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontWeight(Tcl_Interp *interp, const char *font, int weight, char *new_font) { int res; // First try to modify the old -foundry-family-weigth-*-*-... form // Catch the weight field, replace it with bold or medium. vtksys_ios::ostringstream regsub; regsub << "unset -nocomplain __tmp__; regsub -- {(-[^-]*\\S-[^-]*\\S-)([^-]*)(-.*)} \"" << font << "\" {\\1" << (weight ? "bold" : "medium") << "\\3} __tmp__"; res = Tcl_GlobalEval(interp, regsub.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to regsub!"); return 0; } if (atoi(Tcl_GetStringResult(interp)) == 1) { res = Tcl_GlobalEval(interp, "set __tmp__"); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to replace result of regsub! (" << Tcl_GetStringResult(interp) << ")"); return 0; } strcpy(new_font, Tcl_GetStringResult(interp)); return 1; } // Otherwise replace the -weight parameter with either bold or normal char real_font[1024]; if (!vtkKWTkUtilities::GetRealActualFont(interp, font, real_font)) { vtkGenericWarningMacro(<< "Unable to get real actual font from font! (" << font << ")"); return 0; } vtksys_stl::string script("unset -nocomplain __tmp__; array set __tmp__ \""); script += real_font; script += "\" ; set __tmp__(-weight) "; script += (weight ? "bold" : "normal"); script += "; array get __tmp__"; res = Tcl_GlobalEval(interp, script.c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to replace -weight attribute! (" << Tcl_GetStringResult(interp) << ")"); return 0; } strcpy(new_font, Tcl_GetStringResult(interp)); return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontWeightToBold(Tcl_Interp *interp, const char *font, char *new_font) { return vtkKWTkUtilities::ChangeFontWeight(interp, font, 1, new_font); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontWeightToNormal(Tcl_Interp *interp, const char *font, char *new_font) { return vtkKWTkUtilities::ChangeFontWeight(interp, font, 0, new_font); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontWeight(Tcl_Interp *interp, const char *widget, int weight) { char font[1024], new_font[1024]; int res; // Get the font vtksys_ios::ostringstream getfont; getfont << widget << " cget -font"; res = Tcl_GlobalEval(interp, getfont.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to getfont!"); return 0; } strcpy(font, Tcl_GetStringResult(interp)); // Change the font weight if (!vtkKWTkUtilities::ChangeFontWeight(interp, font, weight, new_font)) { return 0; } // Set the font vtksys_ios::ostringstream setfont; setfont << widget << " configure -font \"" << new_font << "\""; res = Tcl_GlobalEval(interp, setfont.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to replace font ! (" << Tcl_GetStringResult(interp) << ")"); return 0; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontWeightToBold(Tcl_Interp *interp, const char *widget) { return vtkKWTkUtilities::ChangeFontWeight(interp, widget, 1); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontWeightToBold(vtkKWWidget *widget) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::ChangeFontWeightToBold( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName()); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontWeightToNormal(Tcl_Interp *interp, const char *widget) { return vtkKWTkUtilities::ChangeFontWeight(interp, widget, 0); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontWeightToNormal(vtkKWWidget *widget) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::ChangeFontWeightToNormal( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName()); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSlant(Tcl_Interp *interp, const char *font, int slant, char *new_font) { int res; // First try to modify the old -foundry-family-weigth-slant-*-*-... form // Catch the slant field, replace it with i (italic) or r (roman). vtksys_ios::ostringstream regsub; regsub << "unset -nocomplain __tmp__; regsub -- {(-[^-]*\\S-[^-]*\\S-[^-]*\\S-)([^-]*)(-.*)} \"" << font << "\" {\\1" << (slant ? "i" : "r") << "\\3} __tmp__"; res = Tcl_GlobalEval(interp, regsub.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to regsub!"); return 0; } if (atoi(Tcl_GetStringResult(interp)) == 1) { res = Tcl_GlobalEval(interp, "set __tmp__"); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to replace result of regsub! (" << Tcl_GetStringResult(interp) << ")"); return 0; } strcpy(new_font, Tcl_GetStringResult(interp)); return 1; } // Otherwise replace the -slant parameter with either bold or normal char real_font[1024]; if (!vtkKWTkUtilities::GetRealActualFont(interp, font, real_font)) { vtkGenericWarningMacro(<< "Unable to get real actual font from font! (" << font << ")"); return 0; } vtksys_stl::string script("unset -nocomplain __tmp__; array set __tmp__ \""); script += real_font; script += "\" ; set __tmp__(-slant) "; script += (slant ? "italic" : "roman"); script += "; array get __tmp__"; res = Tcl_GlobalEval(interp, script.c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to replace -slant attribute! (" << Tcl_GetStringResult(interp) << ")"); return 0; } strcpy(new_font, Tcl_GetStringResult(interp)); return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSlantToItalic(Tcl_Interp *interp, const char *font, char *new_font) { return vtkKWTkUtilities::ChangeFontSlant(interp, font, 1, new_font); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSlantToRoman(Tcl_Interp *interp, const char *font, char *new_font) { return vtkKWTkUtilities::ChangeFontSlant(interp, font, 0, new_font); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSlant(Tcl_Interp *interp, const char *widget, int slant) { char font[1024], new_font[1024]; int res; // Get the font vtksys_ios::ostringstream getfont; getfont << widget << " cget -font"; res = Tcl_GlobalEval(interp, getfont.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to getfont!"); return 0; } strcpy(font, Tcl_GetStringResult(interp)); // Change the font slant if (!vtkKWTkUtilities::ChangeFontSlant(interp, font, slant, new_font)) { return 0; } // Set the font vtksys_ios::ostringstream setfont; setfont << widget << " configure -font \"" << new_font << "\""; res = Tcl_GlobalEval(interp, setfont.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to replace font ! (" << Tcl_GetStringResult(interp) << ")"); return 0; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSlantToItalic(Tcl_Interp *interp, const char *widget) { return vtkKWTkUtilities::ChangeFontSlant(interp, widget, 1); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSlantToItalic(vtkKWWidget *widget) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::ChangeFontSlantToItalic( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName()); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSlantToRoman(Tcl_Interp *interp, const char *widget) { return vtkKWTkUtilities::ChangeFontSlant(interp, widget, 0); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSlantToRoman(vtkKWWidget *widget) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::ChangeFontSlantToRoman( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName()); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSize(Tcl_Interp *interp, const char *font, int new_size, char *new_font) { int res; // Update the -size parameter char real_font[1024]; if (!vtkKWTkUtilities::GetRealActualFont(interp, font, real_font)) { vtkGenericWarningMacro(<< "Unable to get real actual font from font! (" << font << ")"); return 0; } char script[1024]; sprintf(script, "unset -nocomplain __tmp__; array set __tmp__ \"%s\" ; set __tmp__(-size) %d; array get __tmp__", real_font, new_size); res = Tcl_GlobalEval(interp, script); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to replace -size attribute! (" << Tcl_GetStringResult(interp) << ")"); return 0; } strcpy(new_font, Tcl_GetStringResult(interp)); return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSize(Tcl_Interp *interp, const char *widget, int new_size) { char font[1024], new_font[1024]; int res; // Get the font vtksys_ios::ostringstream getfont; getfont << widget << " cget -font"; res = Tcl_GlobalEval(interp, getfont.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to getfont!"); return 0; } strcpy(font, Tcl_GetStringResult(interp)); // Change the font size if (!vtkKWTkUtilities::ChangeFontSize(interp, font, new_size, new_font)) { return 0; } // Set the font vtksys_ios::ostringstream setfont; setfont << widget << " configure -font \"" << new_font << "\""; res = Tcl_GlobalEval(interp, setfont.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to replace font ! (" << Tcl_GetStringResult(interp) << ")"); return 0; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::ChangeFontSize(vtkKWWidget *widget, int new_size) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::ChangeFontSize( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), new_size); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetGridSize(Tcl_Interp *interp, const char *widget, int *nb_of_cols, int *nb_of_rows) { vtksys_ios::ostringstream size; size << "grid size " << widget; int res = Tcl_GlobalEval(interp, size.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query grid size!"); return 0; } if (sscanf( Tcl_GetStringResult(interp), "%d %d", nb_of_cols, nb_of_rows) != 2) { return 0; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetGridSize(vtkKWWidget *widget, int *nb_of_cols, int *nb_of_rows) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::GetGridSize( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), nb_of_cols, nb_of_rows); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetPositionInGrid(Tcl_Interp *interp, const char *widget, int *col, int *row) { vtksys_ios::ostringstream info; info << "grid info " << widget ; int res = Tcl_GlobalEval(interp, info.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query grid info!"); return 0; } const char *pos; int ok = 1; const char *result = Tcl_GetStringResult(interp); pos = strstr(result, "-column "); if (pos) { if (sscanf(pos, "-column %d", col) != 1) { ok = 0; } } pos = strstr(result, "-row "); if (pos) { if (sscanf(pos, "-row %d", row) != 1) { ok = 0; } } return ok; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetPositionInGrid(vtkKWWidget *widget, int *col, int *row) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::GetWidgetPositionInGrid( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), col, row); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetPaddingInPack(Tcl_Interp *interp, const char *widget, int *ipadx, int *ipady, int *padx, int *pady) { vtksys_ios::ostringstream packinfo; packinfo << "pack info " << widget; int res = Tcl_GlobalEval(interp, packinfo.str().c_str()); const char *result = Tcl_GetStringResult(interp); if (res != TCL_OK || !result || !result[0]) { vtkGenericWarningMacro(<< "Unable to get pack info!"); return 0; } // Parse (ex: -ipadx 0 -ipady 0 -padx 0 -pady 0) int ok = 1; const char *ptr; if (ipadx) { ptr = strstr(result, "-ipadx "); if (ptr) { if (sscanf(ptr + 7, "%d", ipadx) != 1) { ok = 0; } } } if (ipady) { ptr = strstr(result, "-ipady "); if (ptr) { if (sscanf(ptr + 7, "%d", ipady) != 1) { ok = 0; } } } if (padx) { ptr = strstr(result, "-padx "); if (ptr) { if (sscanf(ptr + 6, "%d", padx) != 1) { ok = 0; } } } if (pady) { ptr = strstr(result, "-pady "); if (ptr) { if (sscanf(ptr + 6, "%d", pady) != 1) { ok = 0; } } } return ok; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetMasterInPack(Tcl_Interp *interp, const char *widget, ostream &in) { vtksys_ios::ostringstream packinfo; packinfo << "pack info " << widget; int res = Tcl_GlobalEval(interp, packinfo.str().c_str()); const char *result = Tcl_GetStringResult(interp); if (res != TCL_OK || !result || !result[0]) { vtkGenericWarningMacro(<< "Unable to get pack info!"); return 0; } // Parse for -in const char *pack_in = strstr(result, "-in "); if (!pack_in) { return 0; } pack_in += 4; const char *pack_in_end = strchr(pack_in, ' '); if (pack_in_end) { char *pack_in_buffer = new char [strlen(pack_in) + 1]; strncpy(pack_in_buffer, pack_in, pack_in_end - pack_in); pack_in_buffer[pack_in_end - pack_in] = '\0'; in << pack_in_buffer; delete [] pack_in_buffer; } else { in << pack_in; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetMasterInPack(vtkKWWidget *widget, ostream &in) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::GetMasterInPack( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), in); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetSlavesBoundingBoxInPack(Tcl_Interp *interp, const char *widget, int *width, int *height) { vtksys_ios::ostringstream slaves; slaves << "pack slaves " << widget; int res = Tcl_GlobalEval(interp, slaves.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to get pack slaves!"); return 0; } // No slaves const char *result = Tcl_GetStringResult(interp); if (!result || !result[0]) { return 1; } // Browse each slave for its requested width/height int buffer_length = (int)strlen(result); char *buffer = new char [buffer_length + 1]; strcpy(buffer, result); char *buffer_end = buffer + buffer_length; char *ptr = buffer, *word_end; while (ptr < buffer_end) { // Get the slave name word_end = strchr(ptr + 1, ' '); if (word_end == NULL) { word_end = buffer_end; } else { *word_end = 0; } // Get width / height int w, h; if (!vtkKWTkUtilities::GetWidgetRequestedSize(interp, ptr, &w, &h)) { vtkGenericWarningMacro(<< "Unable to query slave geometry!"); } else { // If w == h == 1 then again it might not have been packed, so call // recursively if (w == 1 && h == 1) { vtkKWTkUtilities::GetSlavesBoundingBoxInPack(interp, ptr, &w, &h); } // Don't forget the padding int ipadx = 0, ipady = 0, padx = 0, pady = 0; vtkKWTkUtilities::GetWidgetPaddingInPack(interp, ptr, &ipadx, &ipady, &padx, &pady); w += 2 * (padx + ipadx); h += 2 * (pady + ipady); if (w > *width) { *width = w; } if (h > *height) { *height = h; } } ptr = word_end + 1; } delete [] buffer; return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetSlavesBoundingBoxInPack(vtkKWWidget *widget, int *width, int *height) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::GetSlavesBoundingBoxInPack( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), width, height); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetSlaveHorizontalPositionInPack(Tcl_Interp *interp, const char *widget, const char *slave, int *x) { vtksys_ios::ostringstream slaves; slaves << "pack slaves " << widget; int res = Tcl_GlobalEval(interp, slaves.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to get pack slaves!"); return 0; } // No slaves const char *result = Tcl_GetStringResult(interp); if (!result || !result[0]) { vtkGenericWarningMacro(<< "Unable to find slaves!"); return 0; } // Browse each slave until the right one if found int buffer_length = (int)strlen(result); char *buffer = new char [buffer_length + 1]; strcpy(buffer, result); char *buffer_end = buffer + buffer_length; char *ptr = buffer, *word_end; int pos = 0; while (ptr < buffer_end) { // Get the slave name word_end = strchr(ptr + 1, ' '); if (word_end == NULL) { word_end = buffer_end; } else { *word_end = 0; } // If slave found, add one padx and leave if (!strcmp(ptr, slave)) { int padx = 0; vtkKWTkUtilities::GetWidgetPaddingInPack(interp, ptr, 0, 0, &padx, 0); pos += padx; break; } // Get width int w; if (!vtkKWTkUtilities::GetWidgetRequestedSize(interp, ptr, &w, NULL)) { vtkGenericWarningMacro(<< "Unable to query slave geometry!"); } else { // If w == 1 then again it might not have been packed, so get bbox if (w == 1) { int h = 0; vtkKWTkUtilities::GetSlavesBoundingBoxInPack(interp, ptr, &w, &h); } // Don't forget the padding int ipadx = 0, padx = 0; vtkKWTkUtilities::GetWidgetPaddingInPack(interp, ptr, &ipadx, 0, &padx, 0); pos += w + 2 * (padx + ipadx); } ptr = word_end + 1; } delete [] buffer; *x = pos; return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetSlaveHorizontalPositionInPack(vtkKWWidget *widget, vtkKWWidget *slave, int *x) { if (!widget || !widget->IsCreated() || !slave || !slave->IsCreated()) { return 0; } return vtkKWTkUtilities::GetSlaveHorizontalPositionInPack( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), slave->GetWidgetName(), x); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetGridColumnWidths(Tcl_Interp *interp, const char *widget, int *nb_of_cols, int **col_widths, int allocate) { // First get grid size int nb_of_rows; if (!vtkKWTkUtilities::GetGridSize(interp, widget, nb_of_cols, &nb_of_rows)) { vtkGenericWarningMacro(<< "Unable to query grid size!"); return 0; } // Iterate over the columns and get the largest widget // (I'm expecting only one widget per cell here) if (allocate) { *col_widths = new int[*nb_of_cols]; } int col, row; for (col = 0; col < *nb_of_cols; col++) { (*col_widths)[col] = 0; for (row = 0; row < nb_of_rows; row++) { // Get the slave vtksys_ios::ostringstream slave; slave << "grid slaves " << widget << " -column " << col << " -row " << row; int res = Tcl_GlobalEval(interp, slave.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to get grid slave!"); continue; } // No slave, let's process the next row const char *result = Tcl_GetStringResult(interp); if (!result || !result[0]) { continue; } // Get the slave reqwidth int width; if (!vtkKWTkUtilities::GetWidgetRequestedSize( interp, result, &width, NULL)) { vtkGenericWarningMacro(<< "Unable to query slave width!"); continue; } if (width > (*col_widths)[col]) { (*col_widths)[col] = width; } } } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::SynchroniseGridsColumnMinimumSize( Tcl_Interp *interp, int nb_of_widgets, const char **widgets, const float *factors, const int *weights) { // Allocate mem for nb of colums and widths int *nb_of_cols = new int [nb_of_widgets]; int **col_widths = new int* [nb_of_widgets]; int widget; // Collect column widths int min_nb_of_cols = 10000; for (widget = 0; widget < nb_of_widgets; widget++) { if (!vtkKWTkUtilities::GetGridColumnWidths( interp, widgets[widget], &nb_of_cols[widget], &col_widths[widget], 1)) { nb_of_cols[widget] = 0; col_widths[widget] = NULL; } if (nb_of_cols[widget] < min_nb_of_cols) { min_nb_of_cols = nb_of_cols[widget]; } } // Synchronize columns (for each column, configure -minsize to the largest // column width for all grids) vtksys_ios::ostringstream minsize; for (int col = 0; col < min_nb_of_cols; col++) { int col_width_max = 0; for (widget = 0; widget < nb_of_widgets; widget++) { if (col_widths[widget][col] > col_width_max) { col_width_max = col_widths[widget][col]; } } if (factors) { col_width_max = (int)((float)col_width_max * factors[col]); } for (widget = 0; widget < nb_of_widgets; widget++) { minsize << "grid columnconfigure " << widgets[widget] << " " << col << " -minsize " << col_width_max; if (weights) { minsize << " -weight " << weights[col]; } minsize << endl; } } int ok = 1; if (Tcl_GlobalEval(interp, minsize.str().c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to synchronize grid columns!"); ok = 0; } // Free mem delete [] nb_of_cols; for (widget = 0; widget < nb_of_widgets; widget++) { delete [] col_widths[widget]; } delete [] col_widths; return ok; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::SynchroniseLabelsMaximumWidth( Tcl_Interp *interp, int nb_of_widgets, const char **widgets, const char *options) { // Get the maximum width int width, length, maxwidth = 0; int widget; for (widget = 0; widget < nb_of_widgets; widget++) { // Get the -width vtksys_ios::ostringstream getwidth; getwidth << widgets[widget] << " cget -width"; int res = Tcl_GlobalEval(interp, getwidth.str().c_str()); const char *result = Tcl_GetStringResult(interp); if (res != TCL_OK || !result || !result[0]) { vtkGenericWarningMacro(<< "Unable to get label -width! " < maxwidth) { maxwidth = width; } if (length > maxwidth) { maxwidth = length; } } // Synchronize labels vtksys_ios::ostringstream setwidth; for (widget = 0; widget < nb_of_widgets; widget++) { setwidth << widgets[widget] << " configure -width " << maxwidth; if (options) { setwidth << " " << options; } setwidth << endl; } int res = Tcl_GlobalEval(interp, setwidth.str().c_str()); if (res != TCL_OK) { vtkGenericWarningMacro(<< "Unable to synchronize labels width! " << Tcl_GetStringResult(interp)); } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::SynchroniseLabelsMaximumWidth(vtkKWApplication *app, int nb_of_widgets, const char **widgets, const char *options) { if (!app) { return 0; } return vtkKWTkUtilities::SynchroniseLabelsMaximumWidth( app->GetMainInterp(), nb_of_widgets, widgets, options); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetSlavesInPack( Tcl_Interp *interp, const char *widget, char ***slaves) { int res; // Get number of slaves vtksys_ios::ostringstream nb_slaves_str; nb_slaves_str << "llength [pack slaves " << widget << "]"; res = Tcl_GlobalEval(interp, nb_slaves_str.str().c_str()); const char *result = Tcl_GetStringResult(interp); if (res != TCL_OK || !result || !result[0]) { vtkGenericWarningMacro(<< "Unable to get number of packed slaves!"); return 0; } int nb_slaves = atoi(result); if (!nb_slaves) { return 0; } // Get the slaves as a space-separated list vtksys_ios::ostringstream slaves_str; slaves_str << "pack slaves " << widget; res = Tcl_GlobalEval(interp, slaves_str.str().c_str()); result = Tcl_GetStringResult(interp); if (res != TCL_OK || !result || !result[0]) { vtkGenericWarningMacro(<< "Unable to get packed slaves!"); return 0; } // Allocate slaves *slaves = new char* [nb_slaves]; // Browse each slave and store it int buffer_length = (int)strlen(result); char *buffer = new char [buffer_length + 1]; strcpy(buffer, result); char *buffer_end = buffer + buffer_length; char *ptr = buffer, *word_end; int i = 0; while (ptr < buffer_end && i < nb_slaves) { word_end = strchr(ptr + 1, ' '); if (word_end == NULL) { word_end = buffer_end; } else { *word_end = 0; } (*slaves)[i] = new char [strlen(ptr) + 1]; strcpy((*slaves)[i], ptr); i++; ptr = word_end + 1; } delete [] buffer; return nb_slaves; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetSlavesInPack(vtkKWWidget *widget, char ***slaves) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::GetSlavesInPack( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), slaves); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetPreviousAndNextSlaveInPack( Tcl_Interp *interp, const char *widget, const char *slave, ostream &previous_slave, ostream &next_slave) { // Search (and allocate) the slaves char **slaves = 0; int nb_slaves = vtkKWTkUtilities::GetSlavesInPack(interp, widget, &slaves); if (!nb_slaves) { return 0; } // Browse each of them int i, found = 0; for (i = 0; i < nb_slaves; i++) { if (!strcmp(slaves[i], slave)) { if (i > 0) { previous_slave << slaves[i - 1]; } if (i < nb_slaves - 1) { next_slave << slaves[i + 1]; } found = 1; break; } } // Deallocate slaves for (i = 0 ; i < nb_slaves; i++) { delete [] slaves[i]; } delete [] slaves; return found; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetPreviousAndNextSlaveInPack( vtkKWWidget *widget, vtkKWWidget *slave, ostream &previous_slave, ostream &next_slave) { if (!widget || !widget->IsCreated() || !slave || !slave->IsCreated()) { return 0; } return vtkKWTkUtilities::GetPreviousAndNextSlaveInPack( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), slave->GetWidgetName(), previous_slave, next_slave); } /* *-------------------------------------------------------------- * * TkImageGetColor -- * * This procedure converts a pixel value to three floating * point numbers, representing the amount of red, green, and * blue in that pixel on the screen. It makes use of colormap * data passed as an argument, and should work for all Visual * types. * * This implementation is bogus on Windows because the colormap * data is never filled in. Instead all postscript generated * data coming through here is expected to be RGB color data. * To handle lower bit-depth images properly, XQueryColors * must be implemented for Windows. * * Results: * Returns red, green, and blue color values in the range * 0 to 1. There are no error returns. * * Side effects: * None. * *-------------------------------------------------------------- */ /* * The following definition is used in generating postscript for images * and windows. */ struct vtkKWTkUtilitiesTkColormapData { /* Hold color information for a window */ int separated; /* Whether to use separate color bands */ int color; /* Whether window is color or black/white */ int ncolors; /* Number of color values stored */ XColor *colors; /* Pixel value -> RGB mappings */ int red_mask, green_mask, blue_mask; /* Masks and shifts for each */ int red_shift, green_shift, blue_shift; /* color band */ }; static void vtkKWTkUtilitiesTkImageGetColor(vtkKWTkUtilitiesTkColormapData* #ifdef WIN32 #else cdata #endif , unsigned long pixel, double *red, double *green, double *blue) #ifdef WIN32 /* * We could just define these instead of pulling in windows.h. #define GetRValue(rgb) ((BYTE)(rgb)) #define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8)) #define GetBValue(rgb) ((BYTE)((rgb)>>16)) */ { *red = (double) GetRValue(pixel) / 255.0; *green = (double) GetGValue(pixel) / 255.0; *blue = (double) GetBValue(pixel) / 255.0; } #else { if (cdata->separated) { int r = (pixel & cdata->red_mask) >> cdata->red_shift; int g = (pixel & cdata->green_mask) >> cdata->green_shift; int b = (pixel & cdata->blue_mask) >> cdata->blue_shift; *red = cdata->colors[r].red / 65535.0; *green = cdata->colors[g].green / 65535.0; *blue = cdata->colors[b].blue / 65535.0; } else { *red = cdata->colors[pixel].red / 65535.0; *green = cdata->colors[pixel].green / 65535.0; *blue = cdata->colors[pixel].blue / 65535.0; } } #endif //---------------------------------------------------------------------------- int vtkKWTkUtilities::TakeScreenDump(Tcl_Interp *interp, const char* widget, const char* fname, int top, int bottom, int left, int right) { if (!interp || !fname || !widget) { return 0; } int ww, hh, xx, yy; if (!vtkKWTkUtilities::GetWidgetCoordinates(interp, widget, &xx, &yy) || !vtkKWTkUtilities::GetWidgetSize(interp, widget, &ww, &hh)) { return 0; } xx -= left; yy -= top; ww += left + right; hh += top + bottom; Tk_Window image_window; image_window = Tk_MainWindow(interp); Display *dpy = Tk_Display(image_window); int screen = DefaultScreen(dpy); Window win=RootWindow(dpy, screen); XImage *ximage = XGetImage(dpy, win, xx, yy, (unsigned int)ww, (unsigned int)hh, AllPlanes, XYPixmap); if ( !ximage ) { return 0; } /* unsigned int buffer_size = ximage->bytes_per_line * ximage->height; if (ximage->format != ZPixmap) { buffer_size = ximage->bytes_per_line * ximage->height * ximage->depth; } */ vtkKWTkUtilitiesTkColormapData cdata; Colormap cmap; Visual *visual; int i, ncolors; cmap = Tk_Colormap(image_window); visual = Tk_Visual(image_window); /* * Obtain information about the colormap, ie the mapping between * pixel values and RGB values. The code below should work * for all Visual types. */ ncolors = visual->map_entries; cdata.colors = (XColor *) ckalloc(sizeof(XColor) * ncolors); cdata.ncolors = ncolors; cdata.red_mask = 0; cdata.green_mask = 0; cdata.blue_mask = 0; cdata.red_shift = 0; cdata.green_shift = 0; cdata.blue_shift = 0; if (visual->c_class == DirectColor || visual->c_class == TrueColor) { cdata.separated = 1; cdata.red_mask = visual->red_mask; cdata.green_mask = visual->green_mask; cdata.blue_mask = visual->blue_mask; while ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0) cdata.red_shift ++; while ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0) cdata.green_shift ++; while ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0) cdata.blue_shift ++; for (i = 0; i < ncolors; i ++) cdata.colors[i].pixel = ((i << cdata.red_shift) & cdata.red_mask) | ((i << cdata.green_shift) & cdata.green_mask) | ((i << cdata.blue_shift) & cdata.blue_mask); } else { cdata.separated=0; for (i = 0; i < ncolors; i ++) cdata.colors[i].pixel = i; } if (visual->c_class == StaticGray || visual->c_class == GrayScale) { cdata.color = 0; } else { cdata.color = 1; } XQueryColors(Tk_Display(image_window), cmap, cdata.colors, ncolors); /* * Figure out which color level to use (possibly lower than the * one specified by the user). For example, if the user specifies * color with monochrome screen, use gray or monochrome mode instead. */ int level = 2; if (!cdata.color && level == 2) { level = 1; } if (!cdata.color && cdata.ncolors == 2) { level = 0; } unsigned long stride = ww * 3; unsigned long buffer_length = stride * hh; unsigned char *buffer = new unsigned char [buffer_length]; unsigned char *ptr = buffer + buffer_length - stride; int x, y; for (y = 0; y < hh; y++) { for (x = 0; x < ww; x++) { double red, green, blue; vtkKWTkUtilitiesTkImageGetColor( &cdata, XGetPixel(ximage, x, hh - y - 1), &red, &green, &blue); *ptr++ = (unsigned char)(255 * red); *ptr++ = (unsigned char)(255 * green); *ptr++ = (unsigned char)(255 * blue); } ptr -= stride; ptr -= stride; } vtkKWResourceUtilities::WritePNGImage(fname, ww, hh, 3, buffer); delete [] buffer; XDestroyImage(ximage); return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::TakeScreenDump(vtkKWWidget *widget, const char* fname, int top, int bottom, int left, int right) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::TakeScreenDump( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), fname, top, bottom, left, right); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::SetTopLevelMouseCursor(Tcl_Interp *interp, const char* widget, const char *cursor) { if (!interp || !widget) { return 0; } vtksys_stl::string cmd("[winfo toplevel "); cmd += widget; cmd += "] configure -cursor {"; if (cursor) { cmd += cursor; } cmd += "}"; if (Tcl_GlobalEval(interp, cmd.c_str()) != TCL_OK) { vtkGenericWarningMacro( << "Unable to change toplevel mouse cursor: " << Tcl_GetStringResult(interp)); return 0; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::SetTopLevelMouseCursor(vtkKWWidget *widget, const char *cursor) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::SetTopLevelMouseCursor( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), cursor); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::IsTopLevel(Tcl_Interp *interp, const char* widget) { if (!interp || !widget) { return 0; } vtksys_stl::string cmd("winfo toplevel "); cmd += widget; if (Tcl_GlobalEval(interp, cmd.c_str()) != TCL_OK) { vtkGenericWarningMacro( << "Unable to query toplevel: " << Tcl_GetStringResult(interp)); return 0; } return (!strcmp(Tcl_GetStringResult(interp), widget) ? 1 : 0); } //---------------------------------------------------------------------------- int vtkKWTkUtilities::IsTopLevel(vtkKWWidget *widget) { if (!widget || !widget->IsCreated()) { return 0; } return vtkKWTkUtilities::IsTopLevel( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWTkUtilities::WithdrawTopLevel(Tcl_Interp *interp, const char* widget) { if (!interp || !widget) { return; } vtksys_stl::string cmd("wm withdraw "); cmd += widget; if (Tcl_GlobalEval(interp, cmd.c_str()) != TCL_OK) { vtkGenericWarningMacro( << "Unable to withdraw toplevel: " << Tcl_GetStringResult(interp)); } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::WithdrawTopLevel(vtkKWWidget *widget) { if (!widget || !widget->IsCreated()) { return; } vtkKWTkUtilities::WithdrawTopLevel( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName()); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::GetCurrentScript( Tcl_Interp *interp) { if (interp) { if (Tcl_GlobalEval(interp, "info script") == TCL_OK) { return Tcl_GetStringResult(interp); } vtkGenericWarningMacro( << "Unable to get current script: " << Tcl_GetStringResult(interp)); } return NULL; } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::GetCurrentScript( vtkKWApplication *app) { if (!app) { return NULL; } return vtkKWTkUtilities::GetCurrentScript(app->GetMainInterp()); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::CreateTimerHandler( Tcl_Interp *interp, unsigned long ms, vtkObject *object, const char *method) { if (!interp) { return NULL; } char *command = NULL; vtkKWTkUtilities::CreateObjectMethodCommand( interp, &command, object, method); char *after_command = new char[strlen(command) + 50]; sprintf(after_command, "after %ld {%s}", ms, command); if (Tcl_GlobalEval(interp, after_command) != TCL_OK) { vtkGenericWarningMacro( << "Unable to create timer handler " << Tcl_GetStringResult(interp)); } delete [] after_command; delete [] command; return Tcl_GetStringResult(interp); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::CreateTimerHandler( vtkKWApplication *, unsigned long ms, vtkObject *object, const char *method) { return vtkKWTkUtilities::CreateTimerHandler( vtkKWApplication::GetMainInterp(), ms, object, method); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::CreateIdleTimerHandler( Tcl_Interp *interp, vtkObject *object, const char *method) { if (!interp) { return NULL; } char *command = NULL; vtkKWTkUtilities::CreateObjectMethodCommand(interp, &command, object, method); char *after_command = new char[strlen(command) + 50]; sprintf(after_command, "after idle {%s}", command); if (Tcl_GlobalEval(interp, after_command) != TCL_OK) { vtkGenericWarningMacro( << "Unable to create timer handler " << Tcl_GetStringResult(interp)); } delete [] after_command; delete [] command; return Tcl_GetStringResult(interp); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::CreateIdleTimerHandler( vtkKWApplication *, vtkObject *object, const char *method) { return vtkKWTkUtilities::CreateIdleTimerHandler( vtkKWApplication::GetMainInterp(), object, method); } //---------------------------------------------------------------------------- void vtkKWTkUtilities::CancelTimerHandler(Tcl_Interp *interp, const char *id) { if (interp && id) { char cmd[256]; sprintf(cmd, "after cancel %s", id); if (Tcl_GlobalEval(interp, cmd) != TCL_OK) { vtkGenericWarningMacro( << "Unable to cancel timer handler " << id << ": " << Tcl_GetStringResult(interp)); } } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::CancelTimerHandler(vtkKWApplication *app, const char *id) { if (app) { vtkKWTkUtilities::CancelTimerHandler(app->GetMainInterp(), id); } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::CancelAllTimerHandlers(Tcl_Interp *interp) { if (interp) { if (Tcl_GlobalEval( interp, "foreach a [after info] {after cancel $a}") != TCL_OK) { vtkGenericWarningMacro( << "Unable to cancel all timer handlers: " << Tcl_GetStringResult(interp)); } } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::CancelAllTimerHandlers(vtkKWApplication *app) { if (app) { vtkKWTkUtilities::CancelAllTimerHandlers(app->GetMainInterp()); } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::Bell(Tcl_Interp *interp) { if (interp) { if (Tcl_GlobalEval(interp, "bell") != TCL_OK) { vtkGenericWarningMacro( << "Unable to ring a bell: " << Tcl_GetStringResult(interp)); } } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::Bell(vtkKWApplication *app) { if (app) { vtkKWTkUtilities::Bell(app->GetMainInterp()); } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::ProcessPendingEvents(Tcl_Interp *interp) { if (interp) { if (Tcl_GlobalEval(interp, "update") != TCL_OK) { vtkGenericWarningMacro( << "Unable to process pending events: " <GetMainInterp()); } } //---------------------------------------------------------------------------- void vtkKWTkUtilities::ProcessIdleTasks(Tcl_Interp *interp) { if (interp) { if (Tcl_GlobalEval(interp, "update idletasks") != TCL_OK) { vtkGenericWarningMacro( << "Unable to process pending events: " <GetMainInterp()); } } //--------------------------------------------------------------------------- #if defined(VTK_USE_CARBON) || defined(VTK_USE_COCOA) #elif !defined(_WIN32) int vtkKWTkUtilities_InteractionEventFound; extern "C" Bool vtkKWTkUtilities_CheckForPendingInteractionEvents( Display *vtkNotUsed(disp), XEvent *event, XPointer vtkNotUsed(arg)) { if (event->type == Expose) { vtkKWTkUtilities_InteractionEventFound = 1; } if (event->type == ConfigureNotify) { vtkKWTkUtilities_InteractionEventFound = 2; } else if (event->type == ButtonPress) { vtkKWTkUtilities_InteractionEventFound = 2; } else if (event->type == KeyPress) { vtkKWTkUtilities_InteractionEventFound = 2; } return 0; } #endif //---------------------------------------------------------------------------- int vtkKWTkUtilities::CheckForPendingInteractionEvents(vtkRenderWindow *win) { int flag = 0; #ifdef _WIN32 (void)win; MSG msg; // Check all four - can't get the range right in one call without // including events we don't want if (PeekMessage(&msg,NULL,WM_LBUTTONDOWN,WM_LBUTTONDOWN,PM_NOREMOVE)) { flag = 2; } else if (PeekMessage( &msg,NULL,WM_NCLBUTTONDOWN,WM_NCLBUTTONDOWN,PM_NOREMOVE)) { flag = 2; } else if (PeekMessage(&msg,NULL,WM_MBUTTONDOWN,WM_MBUTTONDOWN,PM_NOREMOVE)) { flag = 2; } else if (PeekMessage(&msg,NULL,WM_RBUTTONDOWN,WM_RBUTTONDOWN,PM_NOREMOVE)) { flag = 2; } else if (PeekMessage( &msg,NULL,WM_WINDOWPOSCHANGING,WM_WINDOWPOSCHANGING,PM_NOREMOVE)) { flag = 2; } else if (PeekMessage( &msg,NULL,WM_WINDOWPOSCHANGED,WM_WINDOWPOSCHANGED,PM_NOREMOVE)) { flag = 2; } else if (PeekMessage(&msg,NULL,WM_SIZE,WM_SIZE,PM_NOREMOVE)) { flag = 2; } else if (PeekMessage(&msg,NULL,WM_CHAR,WM_CHAR,PM_NOREMOVE) || PeekMessage(&msg,NULL,WM_KEYDOWN,WM_KEYDOWN,PM_NOREMOVE)) { // Do not abort if we are only pressing a modifier // Sorry, had to use hard-coded value, I do not know if there is a // constant in Win32 API to check the vcode // (see vtkWin32RenderWindowInteractor) if (msg.wParam != 16 && msg.wParam != 17) { flag = 2; } } if ( !flag ) { // Check some other events to make sure UI isn't being updated if (PeekMessage(&msg,NULL,WM_SYNCPAINT,WM_SYNCPAINT,PM_NOREMOVE)) { flag = 1; } else if (PeekMessage(&msg,NULL,WM_NCPAINT,WM_NCPAINT,PM_NOREMOVE)) { flag = 1; } else if (PeekMessage(&msg,NULL,WM_PAINT,WM_PAINT,PM_NOREMOVE)) { flag = 1; } else if (PeekMessage(&msg,NULL,WM_ERASEBKGND,WM_ERASEBKGND,PM_NOREMOVE)) { flag = 1; } else if (PeekMessage(&msg,NULL,WM_ACTIVATE,WM_ACTIVATE,PM_NOREMOVE)) { flag = 1; } else if (PeekMessage(&msg,NULL,WM_NCACTIVATE,WM_NCACTIVATE,PM_NOREMOVE)) { flag = 1; } } #elif !defined(VTK_USE_CARBON) && !defined(VTK_USE_COCOA) XEvent report; vtkKWTkUtilities_InteractionEventFound = 0; Display *dpy = vtkXOpenGLRenderWindow::SafeDownCast(win)->GetDisplayId(); // XSync(dpy,False); XCheckIfEvent(dpy, &report, vtkKWTkUtilities_CheckForPendingInteractionEvents, NULL); // XSync(dpy,False); flag = vtkKWTkUtilities_InteractionEventFound; #endif return flag; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetMousePointerCoordinates( Tcl_Interp *interp, const char *widget, int *x, int *y) { if (!interp) { return 0; } vtksys_stl::string pointerxy("winfo pointerxy "); pointerxy += widget; if (Tcl_GlobalEval(interp, pointerxy.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query mouse coordinates! " << Tcl_GetStringResult(interp)); return 0; } int px, py; if (sscanf( Tcl_GetStringResult(interp), "%d %d", &px, &py) != 2) { vtkGenericWarningMacro(<< "Unable to parse mouse coordinates!"); return 0; } if (x) { *x = px; } if (y) { *y = py; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetMousePointerCoordinates( vtkKWWidget *widget, int *x, int *y) { if (widget && widget->IsCreated()) { return vtkKWTkUtilities::GetMousePointerCoordinates( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), x, y); } return 0; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetCoordinates( Tcl_Interp *interp, const char *widget, int *x, int *y) { if (!interp) { return 0; } vtksys_stl::string widgetxy("concat [winfo rootx "); widgetxy += widget; widgetxy += "] [winfo rooty "; widgetxy += widget; widgetxy += "]"; if (Tcl_GlobalEval(interp, widgetxy.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query widget coordinates! " << Tcl_GetStringResult(interp)); return 0; } int wx, wy; if (sscanf(Tcl_GetStringResult(interp), "%d %d", &wx, &wy) != 2) { vtkGenericWarningMacro(<< "Unable to parse widget coordinates!"); return 0; } if (x) { *x = wx; } if (y) { *y = wy; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetCoordinates( vtkKWWidget *widget, int *x, int *y) { if (widget && widget->IsCreated()) { return vtkKWTkUtilities::GetWidgetCoordinates( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), x, y); } return 0; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetRelativeCoordinates( Tcl_Interp *interp, const char *widget, int *x, int *y) { if (!interp) { return 0; } vtksys_stl::string widgetxy("concat [winfo x "); widgetxy += widget; widgetxy += "] [winfo y "; widgetxy += widget; widgetxy += "]"; if (Tcl_GlobalEval(interp, widgetxy.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query widget relative coordinates! " << Tcl_GetStringResult(interp)); return 0; } int wx, wy; if (sscanf(Tcl_GetStringResult(interp), "%d %d", &wx, &wy) != 2) { vtkGenericWarningMacro(<< "Unable to parse widget relative coordinates!"); return 0; } if (x) { *x = wx; } if (y) { *y = wy; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetRelativeCoordinates( vtkKWWidget *widget, int *x, int *y) { if (widget && widget->IsCreated()) { return vtkKWTkUtilities::GetWidgetRelativeCoordinates( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), x, y); } return 0; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetSize( Tcl_Interp *interp, const char *widget, int *w, int *h) { if (!interp) { return 0; } vtksys_stl::string widgetwh("concat [winfo width "); widgetwh += widget; widgetwh += "] [winfo height "; widgetwh += widget; widgetwh += "]"; if (Tcl_GlobalEval(interp, widgetwh.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query widget size! " << Tcl_GetStringResult(interp)); return 0; } int ww, wh; if (sscanf(Tcl_GetStringResult(interp), "%d %d", &ww, &wh) != 2) { vtkGenericWarningMacro(<< "Unable to parse widget size!"); return 0; } if (w) { *w = ww; } if (h) { *h = wh; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetSize( vtkKWWidget *widget, int *w, int *h) { if (widget && widget->IsCreated()) { return vtkKWTkUtilities::GetWidgetSize( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), w, h); } return 0; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetRequestedSize( Tcl_Interp *interp, const char *widget, int *w, int *h) { if (!interp) { return 0; } vtksys_stl::string widgetwh("concat [winfo reqwidth "); widgetwh += widget; widgetwh += "] [winfo reqheight "; widgetwh += widget; widgetwh += "]"; if (Tcl_GlobalEval(interp, widgetwh.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query widget requested size! " << Tcl_GetStringResult(interp)); return 0; } int ww, wh; if (sscanf(Tcl_GetStringResult(interp), "%d %d", &ww, &wh) != 2) { vtkGenericWarningMacro(<< "Unable to parse widget requested size!"); return 0; } if (w) { *w = ww; } if (h) { *h = wh; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetWidgetRequestedSize( vtkKWWidget *widget, int *w, int *h) { if (widget && widget->IsCreated()) { return vtkKWTkUtilities::GetWidgetRequestedSize( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), w, h); } return 0; } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::GetWidgetClass( Tcl_Interp *interp, const char *widget) { if (!interp) { return NULL; } vtksys_stl::string widgetclass("winfo class "); widgetclass += widget; if (Tcl_GlobalEval(interp, widgetclass.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query widget class! " << Tcl_GetStringResult(interp)); return NULL; } return Tcl_GetStringResult(interp); } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::GetWidgetClass( vtkKWWidget *widget) { if (widget && widget->IsCreated()) { return vtkKWTkUtilities::GetWidgetClass( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName()); } return NULL; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetScreenSize( Tcl_Interp *interp, const char *widget, int *w, int *h) { if (!interp) { return 0; } vtksys_stl::string widgetwh("concat [winfo screenwidth "); widgetwh += widget; widgetwh += "] [winfo screenheight "; widgetwh += widget; widgetwh += "]"; if (Tcl_GlobalEval(interp, widgetwh.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query screen size! " << Tcl_GetStringResult(interp)); return 0; } int ww, wh; if (sscanf(Tcl_GetStringResult(interp), "%d %d", &ww, &wh) != 2) { vtkGenericWarningMacro(<< "Unable to parse screen size!"); return 0; } if (w) { *w = ww; } if (h) { *h = wh; } return 1; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetScreenSize( vtkKWWidget *widget, int *w, int *h) { if (widget && widget->IsCreated()) { return vtkKWTkUtilities::GetScreenSize( widget->GetApplication()->GetMainInterp(), widget->GetWidgetName(), w, h); } return 0; } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::GetWindowingSystem(vtkKWApplication *app) { if (app) { return vtkKWTkUtilities::GetWindowingSystem(app->GetMainInterp()); } return NULL; } //---------------------------------------------------------------------------- const char* vtkKWTkUtilities::GetWindowingSystem(Tcl_Interp *interp) { if (interp) { if (Tcl_GlobalEval(interp, "tk windowingsystem") != TCL_OK) { vtkGenericWarningMacro(<< "Unable to query windowing system! " << Tcl_GetStringResult(interp)); return NULL; } return Tcl_GetStringResult(interp); } return NULL; } //---------------------------------------------------------------------------- int vtkKWTkUtilities::GetFontMeasure( vtkKWWidget *widget, const char *txt, int *w) { // Invalid args if (!widget || !widget->IsCreated() || !w) { return 0; } // Empty txt *w = 0; if (!txt || !*txt) { return 1; } Tcl_Interp *interp = widget->GetApplication()->GetMainInterp(); const char *widget_name = widget->GetWidgetName(); vtksys_stl::string fontm("font measure ["); fontm += widget_name; fontm += " cget -font] -displayof "; fontm += widget_name; fontm += " {"; fontm += txt; fontm += "}"; if (Tcl_GlobalEval(interp, fontm.c_str()) != TCL_OK) { vtkGenericWarningMacro(<< "Unable to compute font measure! " << Tcl_GetStringResult(interp)); return 0; } int ww; if (sscanf(Tcl_GetStringResult(interp), "%d", &ww) != 1) { vtkGenericWarningMacro(<< "Unable to parse font measure!"); return 0; } *w = ww; return 1; } //---------------------------------------------------------------------------- void vtkKWTkUtilities::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } kwwidgets-1.0.0~cvs20100930/Utilities/0000755000175000017500000000000011461110203017021 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/CMakeLists.txt0000644000175000017500000000023711006107370021571 0ustar domibeldomibeladd_executable(KWConvertImageToHeader KWConvertImageToHeader.cxx) target_link_libraries(KWConvertImageToHeader ${KWWidgets_LIBRARIES}) subdirs( Doxygen ) kwwidgets-1.0.0~cvs20100930/Utilities/KWConvertImageToHeader.cxx0000644000175000017500000000722411073734044024031 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: KWConvertImageToHeader.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWResourceUtilities.h" #include "vtkOutputWindow.h" #include #include //---------------------------------------------------------------------------- int unknown_argument_handler(const char *, void *) { return 0; }; //---------------------------------------------------------------------------- void display_usage(vtksys::CommandLineArguments &args) { vtksys_stl::string exe_basename = vtksys::SystemTools::GetFilenameName(args.GetArgv0()); cerr << "Usage: " << exe_basename.c_str() << " [--update] [--zlib] [--base64] header.h image.png [image.png image.png...]" << endl; cerr << args.GetHelp(); } //---------------------------------------------------------------------------- int main(int argc, char **argv) { vtkOutputWindow::GetInstance()->PromptUserOn(); vtksys::CommandLineArguments args; int option_update = 0; int option_zlib = 0; int option_base64 = 0; int option_append = 0; int option_use_path_in_name = 0; vtksys_stl::string var_prefix; args.Initialize(argc, argv); args.SetUnknownArgumentCallback(unknown_argument_handler); args.AddArgument( "--update", vtksys::CommandLineArguments::NO_ARGUMENT, &option_update, "Update header only if one of the image is more recent than the header."); args.AddArgument( "--zlib", vtksys::CommandLineArguments::NO_ARGUMENT, &option_zlib, "Compress the image buffer using zlib."); args.AddArgument( "--base64", vtksys::CommandLineArguments::NO_ARGUMENT, &option_base64, "Convert the image buffer to base64."); args.AddArgument( "--append", vtksys::CommandLineArguments::NO_ARGUMENT, &option_append, "Append to the header."); args.AddArgument( "--use_path_in_name", vtksys::CommandLineArguments::NO_ARGUMENT, &option_use_path_in_name, "Use the full path to generate variable names."); args.AddArgument( "--var_prefix", vtksys::CommandLineArguments::SPACE_ARGUMENT, &var_prefix, "Prefix each variable with a specific string."); args.Parse(); // Process the remaining args (note that rem_argv[0] is still the prog name) int res = 1; int rem_argc; char **rem_argv; args.GetRemainingArguments(&rem_argc, &rem_argv); if (rem_argc < 3) { cerr << "Invalid or missing arguments" << endl; display_usage(args); res = 0; } else { option_update *= vtkKWResourceUtilities::ConvertImageToHeaderOptionUpdate; option_zlib *= vtkKWResourceUtilities::ConvertImageToHeaderOptionZlib; option_base64 *= vtkKWResourceUtilities::ConvertImageToHeaderOptionBase64; option_append *= vtkKWResourceUtilities::ConvertImageToHeaderOptionAppend; option_use_path_in_name *= vtkKWResourceUtilities::ConvertImageToHeaderOptionUsePathInName; cout << "- " << rem_argv[1] << endl; vtkKWResourceUtilities::ConvertImageToHeader( rem_argv[1], (const char **)&rem_argv[2], rem_argc - 2, option_update | option_zlib | option_base64 | option_append | option_use_path_in_name, var_prefix.c_str()); } delete [] rem_argv; return res; } kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/0000755000175000017500000000000011461110203020125 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/0000755000175000017500000000000011461110203021110 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/tkXDND.c0000644000175000017500000020604011357653613022377 0ustar domibeldomibel/* * tkXDND.cpp -- * * This file implements the unix portion of the drag&drop mechanish * for the tk toolkit. The protocol in use under unix is the * XDND protocol. * Also, partial support for Motif drops exists. * * This software is copyrighted by: * George Petasis, * Software and Knowledge Engineering Laboratory, * Institute of Informatics and Telecommunications, * National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * and * Laurent Riesterer, Rennes, France. * e-mail: laurent.riesterer@free.fr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ #include #include #include #include #include "vtkTcl.h" #include "vtkTk.h" #include #include #include "tkDND.h" #include "XDND.h" #include "Cursors.h" /* * For C++ compilers, use extern "C" */ #ifdef __cplusplus extern "C" { #endif void TkDND_DestroyEventProc(ClientData clientData, XEvent *eventPtr); static int TkDND_WidgetExists (DndClass *dnd, Window window); static int TkDND_WidgetApplyEnter(DndClass *dnd, Window widgets_window, Window from, Atom action, int x, int y, Time t, Atom * typelist); static int TkDND_WidgetApplyPosition(DndClass *dnd, Window widgets_window, Window from, Atom action, Atom *actionList, int x, int y, Time t, Atom * typelist, int *want_position, Atom *supported_action, Atom *desired_type, XRectangle * rectangle); static int TkDND_WidgetApplyLeave(DndClass *dnd, Window widgets_window); static int TkDND_WidgetInsertDrop(DndClass *dnd, unsigned char *data, int length, int remaining, Window into, Window from, Atom type); static int TkDND_WidgetAsk(DndClass *dnd, Window source, Window target, Atom *action); static int TkDND_WidgetGetData(DndClass *dnd, Window source, unsigned char **data, int *length, Atom type); static void TkDND_HandleEvents (DndClass *dnd, XEvent *xevent); static Atom *TkDND_GetCurrentAtoms(XDND *dnd, Window window); static int TkDND_SetCursor(DndClass *dnd, int cursor); static int TkDND_XDNDHandler(Tk_Window winPtr, XEvent *eventPtr); static int TkDND_LocalErrorHandler(Display *display, XErrorEvent *error); #ifdef __cplusplus } #endif extern Tcl_HashTable TkDND_TargetTable; extern Tcl_HashTable TkDND_SourceTable; DndClass *dnd; static XErrorHandler PreviousErrorHandler = NULL; static unsigned long FirstProtectRequest; static Tk_Window ProtectionOwnerWindow; extern int TkDND_DelHandler(DndInfo *infoPtr, char *typeStr, unsigned long eventType, unsigned long eventMask); extern int TkDND_DelHandlerByName(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask); extern int TkDND_FindMatchingScript(Tcl_HashTable *table, char *windowPath, char *typeStr, Atom typelist[], unsigned long eventType, unsigned long eventMask, int matchExactly, DndType **typePtrPtr, DndInfo **infoPtrPtr); extern int TkDND_GetCurrentTypes(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath); extern void TkDND_ExpandPercents(DndInfo *infoPtr, DndType *typePtr, char *before, Tcl_DString *dsPtr, LONG x, LONG y); extern int TkDND_ExecuteBinding(Tcl_Interp *interp, char *script, int numBytes, Tcl_Obj *data); extern char *TkDND_GetDataAccordingToType(DndInfo *info, Tcl_Obj *ResultObj, DndType *typePtr, int *length); extern Tcl_Obj *TkDND_CreateDataObjAccordingToType(DndType *typePtr, void *info, unsigned char *data, int length); extern int TkDND_Update(Display *display, int idle); #ifndef Tk_CreateClientMessageHandler extern int Tk_CreateClientMessageHandler(int (*proc) (Tk_Window tkwin, XEvent *eventPtr)); #endif /* Tk_CreateClientMessageHandler */ /* * Forward declarations for procedures defined later in this file: */ static int TkDND_ParseAction(DndClass *dnd, DndInfo *infoPtr, DndType *typePtr, Atom default_action, Atom *supported_action, Atom *desired_type); /* Laurent Riesterer 06/07/2000 */ int TkDND_AddHandler(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask, char *script, int isDropTarget, int priority); char *TkDND_GetCurrentActionName(void); int TkDND_DndDrag(Tcl_Interp *interp, char *windowPath, int button, Tcl_Obj *Actions, char *Descriptions, Tk_Window cursor_window, char *cursor_callback); static void TkDND_StartProtectedSection(Display *display, Tk_Window window); static void TkDND_EndProtectedSection(Display *display); #ifdef TKDND_ENABLE_SHAPE_EXTENSION int Shape_Init(Tcl_Interp *interp); #endif /* TKDND_ENABLE_SHAPE_EXTENSION */ Cursor noDropCursor = 0, moveCursor = 0, copyCursor = 0, linkCursor = 0, askCursor = 0; /* *---------------------------------------------------------------------- * * TkDND_TypeToString -- * * Returns a string corresponding to the given type atom. * * Results: * A string in a static memory area holding the string. * Should never be freed or modified. * * Side effects: * - * *---------------------------------------------------------------------- */ char *TkDND_TypeToString(int type) { return (char *) Tk_GetAtomName(dnd->MainWindow, (Atom) type); } /* TkDND_TypeToString */ /* *---------------------------------------------------------------------- * * TkDND_StringToType -- * * Returns a type code corresponding to the given type string. * * Results: * * Side effects: * - * *---------------------------------------------------------------------- */ Atom TkDND_StringToType(char *typeStr) { return Tk_InternAtom(dnd->MainWindow, typeStr); } /* TkDND_StringToType */ /* *---------------------------------------------------------------------- * * TkDND_Init -- * * Initialize the drag and drop platform specific protocol. * Under unix, this is the XDND protocol. * * Results: * A structure that holds platform specific information. * * Side effects: * A set of new cursors is created and a ClientMessage handler * for the XDND protocol is registered... * *---------------------------------------------------------------------- */ void *TkDND_Init(Tcl_Interp *interp, Tk_Window topwin) { DndClass *dndp; XColor black, white; Pixmap image_pixmap, mask_pixmap; dndp = XDND_Init(Tk_Display(topwin)); if (dndp == NULL) return NULL; dndp->MainWindow = topwin; /* Register the callback functions... */ dndp->WidgetExistsCallback = &TkDND_WidgetExists; dndp->WidgetApplyEnterCallback = &TkDND_WidgetApplyEnter; dndp->WidgetApplyPositionCallback = &TkDND_WidgetApplyPosition; dndp->WidgetApplyLeaveCallback = &TkDND_WidgetApplyLeave; dndp->WidgetInsertDropDataCallback = &TkDND_WidgetInsertDrop; dndp->Ask = &TkDND_WidgetAsk; dndp->GetData = &TkDND_WidgetGetData; dndp->HandleEvents = &TkDND_HandleEvents; dndp->GetDragAtoms = &TkDND_GetCurrentAtoms; dndp->SetCursor = &TkDND_SetCursor; /* Create DND Cursors... */ dndp->cursors = (XDNDCursor *) Tcl_Alloc(sizeof(XDNDCursor)*6); black.pixel = BlackPixel(dndp->display, DefaultScreen(dndp->display)); white.pixel = WhitePixel(dndp->display, DefaultScreen(dndp->display)); XQueryColor(dndp->display, DefaultColormap(dndp->display, DefaultScreen(dndp->display)), &black); XQueryColor(dndp->display, DefaultColormap(dndp->display, DefaultScreen(dndp->display)), &white); /* No Drop Cursor */ image_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) noDropCurBits, noDropCursorWidth, noDropCursorHeight); mask_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) noDropCurMask, noDropCursorWidth, noDropCursorHeight); noDropCursor = XCreatePixmapCursor (dndp->display, image_pixmap, mask_pixmap, &black, &white, noDropCursorX, noDropCursorY); XFreePixmap (dndp->display, image_pixmap); XFreePixmap (dndp->display, mask_pixmap); dndp->cursors[0].cursor = noDropCursor; /* Copy Cursor */ image_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) CopyCurBits, CopyCursorWidth, CopyCursorHeight); mask_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) CopyCurMask, CopyCursorWidth, CopyCursorHeight); copyCursor = XCreatePixmapCursor (dndp->display, image_pixmap, mask_pixmap, &black, &white, CopyCursorX, CopyCursorY); XFreePixmap (dndp->display, image_pixmap); XFreePixmap (dndp->display, mask_pixmap); dndp->cursors[1].cursor = copyCursor; /* Move Cursor */ image_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) MoveCurBits, MoveCursorWidth, MoveCursorHeight); mask_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) MoveCurMask, MoveCursorWidth, MoveCursorHeight); moveCursor = XCreatePixmapCursor (dndp->display, image_pixmap, mask_pixmap, &black, &white, MoveCursorX, MoveCursorY); XFreePixmap (dndp->display, image_pixmap); XFreePixmap (dndp->display, mask_pixmap); dndp->cursors[2].cursor = moveCursor; /* Link Cursor */ image_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) LinkCurBits, LinkCursorWidth, LinkCursorHeight); mask_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) LinkCurMask, LinkCursorWidth, LinkCursorHeight); linkCursor = XCreatePixmapCursor (dndp->display, image_pixmap, mask_pixmap, &black, &white, LinkCursorX, LinkCursorY); XFreePixmap (dndp->display, image_pixmap); XFreePixmap (dndp->display, mask_pixmap); dndp->cursors[3].cursor = linkCursor; /* Ask Cursor */ image_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) AskCurBits, AskCursorWidth, AskCursorHeight); mask_pixmap = XCreateBitmapFromData(dndp->display, dndp->RootWindow, (char *) AskCurMask, AskCursorWidth, AskCursorHeight); askCursor = XCreatePixmapCursor (dndp->display, image_pixmap, mask_pixmap, &black, &white, AskCursorX, AskCursorY); XFreePixmap (dndp->display, image_pixmap); XFreePixmap (dndp->display, mask_pixmap); dndp->cursors[4].cursor = askCursor; /* Register Cursors... */ /* Finally, register the XDND Handler... */ Tk_CreateClientMessageHandler(&TkDND_XDNDHandler); #ifdef TKDND_ENABLE_SHAPE_EXTENSION /* Load the shape extension... */ if (Shape_Init(interp) != TCL_OK) { /* TODO: Provide the shape command, even if does not work... */ } #endif /* TKDND_ENABLE_SHAPE_EXTENSION */ dnd = dndp; return dndp; } /* TkDND_Init */ /* *---------------------------------------------------------------------- * * TkDND_WidgetExists -- * * Check if the given window belongs to this application or is a foreign * window. * * Results: * Returns 1 if the specified window belongs to this application. * Else, returns 0. * * Side effects: * Forces window creation if belonging to this application. * *---------------------------------------------------------------------- */ static int TkDND_WidgetExists (DndClass * dnd, Window window) { Tk_Window tkwin; tkwin = Tk_IdToWindow(dnd->display, window); if (tkwin == NULL) { XDND_DEBUG2("++++ TkDND_WidgetExists: NOT OUR OWN WIDGET: %ld!\n", window); return False; } /* * Force the creation of the X-window... */ Tk_MakeWindowExist(tkwin); #ifdef DND_DEBUG { char *name; name = Tk_PathName(tkwin); if (name == NULL) name = "(tk internal/hidden window)"; XDND_DEBUG3("++++ TkDND_WidgetExists: widget %s: %ld\n", name, window); } #endif /* DND_DEBUG */ return True; } /* TkDND_WidgetExists */ /* *---------------------------------------------------------------------- * * TkDND_WidgetApplyEnter -- * * Executes the binding script for the event, if such a * binding exists for the specified window. * * Results: * Returns True upon succesful execution. * Else, returns False. * * Side effects: * Whatever the binding script does :-) * *---------------------------------------------------------------------- */ static int TkDND_WidgetApplyEnter(DndClass *dnd, Window widgets_window, Window from, Atom action, int x, int y, Time t, Atom *typelist) { Tk_Window tkwin; Tcl_DString dString; DndInfo *infoPtr; DndType *typePtr; char *pathName; int ret; XDND_DEBUG(" #### #### (TkDND_WidgetApplyEnter)\n"); /* * Unless said otherwise, result is OK */ dnd->CallbackStatus = TCL_OK; /* Has the previous window received a DragLeave event? */ if (dnd->LastEnterDeliveredWindow != None) { tkwin = Tk_IdToWindow(dnd->display, dnd->LastEnterDeliveredWindow); if (tkwin != NULL) { pathName = Tk_PathName(tkwin); if (pathName != NULL) { XDND_DEBUG3(": Delivering missed to " "window: %s %ld\n", pathName, dnd->LastEnterDeliveredWindow); TkDND_WidgetApplyLeave(dnd, dnd->LastEnterDeliveredWindow); /* Now, dnd->LastEnterDeliveredWindow should be none...*/ if (dnd->LastEnterDeliveredWindow != None) { XDND_DEBUG3(": We missed a on " "window \"%s\" (%ld)\n", pathName, dnd->LastEnterDeliveredWindow); } /* * Check we are still in the target window after processing * event. By Colin McDonald * (14/12/2000) */ if (dnd->MouseWindow != widgets_window) { XDND_DEBUG2("TkDND_WidgetApplyEnter: Left window %ld" " before executing script\n", widgets_window); return False; } } } dnd->LastEnterDeliveredWindow = None; } /* * Bug reported by Colin McDonald : There * is a problem with the call to this routine. It is passed the address * of a typelist. In the calling routines * (e.g. MotifDND_HandleClientMessage) this address is passed from * dnd->DraggerTypeList. The first thing TkDND_WidgetApplyEnter does is * process any missed leave event for dnd->LastEnterDeliveredWindow. If * the script causes more events to be received (e.g. it does * an "update") then the dnd->DraggerTypeList can change, or most likely * is freed and set to a NULL pointer. But the typelist argument in * TkDND_WidgetApplyEnter is still pointing to the old memory location, * now invalid. This can cause Bad Atom errors when debugging, or a crash * in TkDND_FindMatchingScript due to looping through an invalid Atom list * with no terminating null. */ typelist = dnd->DraggerTypeList; if (typelist == NULL) { XDND_DEBUG(": Called with an empty typelist?\n"); return False; } /* Get window path... */ tkwin = Tk_IdToWindow(dnd->display, widgets_window); if (tkwin == NULL) { XDND_DEBUG(": not a TK window!\n"); return False; } pathName = Tk_PathName(tkwin); if (pathName == NULL) { /* * This is a tk "hidden" window... */ XDND_DEBUG(": This is a tk HIDDEN window\n"); return False; } XDND_DEBUG2(": state = %08X\n", dnd->state); /* Laurent Riesterer 06/07/2000: support for extended bindings */ if (TkDND_FindMatchingScript(&TkDND_TargetTable, pathName, NULL, typelist, TKDND_DRAGENTER, dnd->state, False, &typePtr, &infoPtr) != TCL_OK) { goto error; } dnd->SupportedAction = action; if (infoPtr == NULL || typePtr == NULL) { XDND_DEBUG3(": Script not found, info=%p, type=%p\n", infoPtr, typePtr); if (typePtr == NULL) { dnd->DesiredType = typelist[0]; } else { dnd->DesiredType = typePtr->type; } if (dnd->DesiredType == None && typePtr) { /* This is a "string match" type... */ dnd->DesiredType = typePtr->matchedType; } return True; } /* Send the event... */ dnd->interp = infoPtr->interp; if (dnd->DesiredType == 0 && typePtr) { dnd->DesiredType = typePtr->matchedType; } Tcl_DStringInit(&dString); TkDND_ExpandPercents(infoPtr, typePtr, typePtr->script, &dString, x, y); XDND_DEBUG2(": %s\n", Tcl_DStringValue(&dString)); ret = TkDND_ExecuteBinding(dnd->interp, Tcl_DStringValue(&dString), -1, NULL); XDND_DEBUG2(": Return status: %d\n", ret); Tcl_DStringFree(&dString); if (ret == TCL_ERROR) { goto error; } typePtr->EnterEventSent = True; /* TODO */ dnd->LastEnterDeliveredWindow = widgets_window; TkDND_ParseAction(dnd, infoPtr, typePtr, action, &(dnd->SupportedAction), &(dnd->DesiredType)); return True; error: dnd->CallbackStatus = TCL_ERROR; XUngrabPointer(dnd->display, CurrentTime); Tk_BackgroundError(infoPtr->interp); while (Tcl_DoOneEvent(TCL_IDLE_EVENTS) != 0) { XDND_DEBUG("######## INSIDE LOOP - TkDND_WidgetApplyEnter!\n"); /* Empty loop body */ } return False; } /* TkDND_WidgetApplyEnter */ /* *---------------------------------------------------------------------- * * TkDND_WidgetApplyPosition -- * * Executes the binding script for the event, if such a * binding exists for the specified window. * * Results: * Returns True when script returns TCL_OK. * Else (i.e. TCL_ERROR or TCL_BREAK), returns False, meaning that widget * does not want the drop over THIS PARTICULAR coordinates. * * Side effects: * Whatever the binding script does :-) * *---------------------------------------------------------------------- */ static int TkDND_WidgetApplyPosition(DndClass *dnd, Window widgets_window, Window from, Atom action, Atom *actionList, int x, int y, Time t, Atom *typelist, int *want_position, Atom *supported_action, Atom *desired_type, XRectangle *rectangle) { Tk_Window tkwin; Tcl_DString dString; DndType *typePtr; DndInfo *infoPtr; char *pathName; int ret; dnd->CallbackStatus = TCL_OK; if (dnd->SupportedAction == None) dnd->SupportedAction = action; /* Get window path... */ tkwin = Tk_IdToWindow(dnd->display, widgets_window); if (tkwin == NULL) { XDND_DEBUG(": not a TK window!\n"); return False; } pathName = Tk_PathName(tkwin); if (pathName == NULL) { /* * This is a tk "hidden" window... */ XDND_DEBUG(": This is a tk HIDDEN window\n"); return False; } XDND_DEBUG2(": state = %08X\n", dnd->state); if (TkDND_FindMatchingScript(&TkDND_TargetTable, pathName, NULL, typelist, TKDND_DRAG, dnd->state, False, &typePtr, &infoPtr) != TCL_OK) { goto error; } if (infoPtr == NULL || typePtr == NULL) { XDND_DEBUG3(": Script not found, info=%p, type=%p\n", infoPtr, typePtr); if (typePtr == NULL) return False; if (infoPtr == NULL && typePtr == NULL) return False; /* * Petasis, 10/07/2000: Bug where there was an X error when dragging * among different applications and the drop target did not have a * binding script for the event... */ if (*supported_action != dnd->DNDActionCopyXAtom && *supported_action != dnd->DNDActionMoveXAtom && *supported_action != dnd->DNDActionLinkXAtom && *supported_action != dnd->DNDActionAskXAtom && *supported_action != dnd->DNDActionPrivateXAtom) { *supported_action = dnd->DNDActionCopyXAtom; } *desired_type = typePtr->type; return True; } dnd->interp = infoPtr->interp; dnd->DesiredType = typePtr->type; if (dnd->DesiredType == None && typePtr) { /* This is a "string match" type... */ dnd->DesiredType = typePtr->matchedType; } Tcl_DStringInit(&dString); TkDND_ExpandPercents(infoPtr, typePtr, typePtr->script, &dString, x, y); #ifdef DND_DEBUG XDND_DEBUG2(": %s\n", Tcl_DStringValue(&dString)); XDND_DEBUG3(" Supported type: \"%s\" (0x%08x)\n", Tk_GetAtomName(tkwin, dnd->DesiredType), dnd->DesiredType); #endif ret = TkDND_ExecuteBinding(infoPtr->interp, Tcl_DStringValue(&dString), -1, NULL); Tcl_DStringFree(&dString); if (ret == TCL_ERROR) { goto error; } else if (ret == TCL_OK || ret == TCL_RETURN) { *want_position = True; return TkDND_ParseAction(dnd, infoPtr, typePtr, action, supported_action, desired_type); } return False; error: dnd->CallbackStatus = TCL_ERROR; XUngrabPointer (dnd->display, CurrentTime); Tk_BackgroundError(infoPtr->interp); while (Tcl_DoOneEvent(TCL_IDLE_EVENTS) != 0) { XDND_DEBUG("######## INSIDE LOOP - TkDND_WidgetApplyPosition!\n"); /* Empty loop body */ } return False; } /* TkDND_WidgetApplyPosition */ /* *---------------------------------------------------------------------- * * TkDND_ParseAction -- (Laurent Riesterer 06/07/2000) * * Analyze the result of a script to find the requested action * * Results: * True if OK / False else. * *---------------------------------------------------------------------- */ static int TkDND_ParseAction(DndClass *dnd, DndInfo *infoPtr, DndType *typePtr, Atom default_action, Atom *supported_action, Atom *desired_type) { static const char *Actions[] = { "none", "default", "copy", "move", "link", "ask", "private", (char *) NULL }; enum actions {NONE, DEFAULT, COPY, MOVE, LINK, ASK, PRIVATE}; Atom *atomPtr; Tcl_Obj *objPtr; int index, action_ok = False; objPtr = Tcl_DuplicateObj(Tcl_GetObjResult(infoPtr->interp)); Tcl_IncrRefCount(objPtr); XDND_DEBUG2("<>: Wanted Action = '%s'\n", Tcl_GetString(objPtr)); if (Tcl_GetIndexFromObj(infoPtr->interp, objPtr, (CONST84 char **) Actions, "action", 0, &index) == TCL_OK) { switch ((enum actions) index) { case NONE: { dnd->CallbackStatus = TCL_BREAK; return False; } case DEFAULT: { *supported_action = default_action; break; } case COPY: { *supported_action = dnd->DNDActionCopyXAtom; break; } case MOVE: { *supported_action = dnd->DNDActionMoveXAtom; break; } case LINK: { *supported_action = dnd->DNDActionLinkXAtom; break; } case ASK: { *supported_action = dnd->DNDActionAskXAtom; break; } case PRIVATE: { *supported_action = dnd->DNDActionPrivateXAtom; break; } default: { *supported_action = None; } } } else { *supported_action = None; } Tcl_DecrRefCount(objPtr); if (desired_type != NULL) { *desired_type = typePtr->type; if (typePtr->type == None) *desired_type = typePtr->matchedType; } /* * Is the action returned by the script supported by the drag * source? */ if (dnd->DraggerAskActionList != NULL) { for (atomPtr = dnd->DraggerAskActionList; *atomPtr != None; atomPtr++) { if (*supported_action == *atomPtr) { action_ok = True; break; } } /* * We got something not supported by the dragger... */ if (!action_ok) *supported_action = *(dnd->DraggerAskActionList); } else { /* * The dragger does not have an action list. Use the current * action... */ *supported_action = default_action; } if (*supported_action != None) return True; return False; } /* *---------------------------------------------------------------------- * * TkDND_WidgetApplyLeave -- * * Executes the binding script for the event, if such a * binding exists for the specified window. * * Results: * None. * * Side effects: * Whatever the binding script does :-) * *---------------------------------------------------------------------- */ static int TkDND_WidgetApplyLeave(DndClass * dnd, Window widgets_window) { Tk_Window tkwin; Tcl_HashEntry *hPtr; Tcl_DString dString; DndInfo *infoPtr; DndType *curr, *typePtr; char *pathName; int ret; /* Get window path... */ if (widgets_window == None) return TCL_OK; tkwin = Tk_IdToWindow(dnd->display, widgets_window); if (tkwin == NULL) return TCL_OK; pathName = Tk_PathName(tkwin); if (pathName == NULL) { XDND_DEBUG2(": This is a tk HIDDEN window (%ld)\n", widgets_window); return TCL_OK; } XDND_DEBUG2(": Window name: %s\n", pathName); /* See if its a drag source */ hPtr = Tcl_FindHashEntry(&TkDND_TargetTable, pathName); if (hPtr == NULL) { XDND_DEBUG(": can not find source\n"); return TCL_OK; } infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); dnd->interp = infoPtr->interp; dnd->CallbackStatus = TCL_OK; /* * For all types that we have sent a event, send a * event... */ for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { XDND_DEBUG4(": type='%s', what=%ld, EnterEventSent = %d\n", curr->typeStr, curr->eventType, curr->EnterEventSent); if (curr->EnterEventSent) { /* This is a event... */ XDND_DEBUG2(": findind match for type '%s'\n", curr->typeStr); if (TkDND_FindMatchingScript(&TkDND_TargetTable, pathName, curr->typeStr, NULL, TKDND_DRAGLEAVE, dnd->state, False, &typePtr, NULL) == TCL_OK) { if (typePtr == NULL) return TCL_OK; Tcl_DStringInit(&dString); TkDND_ExpandPercents(infoPtr, typePtr, typePtr->script, &dString, dnd->x, dnd->y); XDND_DEBUG2(": %s\n", Tcl_DStringValue(&dString)); ret = TkDND_ExecuteBinding(infoPtr->interp, Tcl_DStringValue(&dString), -1, NULL); Tcl_DStringFree(&dString); if (ret == TCL_ERROR) { dnd->CallbackStatus = TCL_ERROR; XUngrabPointer (dnd->display, CurrentTime); Tk_BackgroundError(infoPtr->interp); while (Tcl_DoOneEvent(TCL_IDLE_EVENTS) != 0) { XDND_DEBUG("######## INSIDE LOOP - TkDND_WidgetApplyLeave!\n"); /* Empty loop body */ } return TCL_ERROR; } curr->EnterEventSent = 0; dnd->LastEnterDeliveredWindow = None; } } } return TCL_OK; } /* TkDND_WidgetApplyLeave */ /* *---------------------------------------------------------------------- * * TkDND_WidgetInsertDrop -- * * Executes the binding script for the event, if such a * binding exists for the specified window. * * Results: * Always 1. * * Side effects: * Whatever the binding script does :-) * *---------------------------------------------------------------------- */ static int TkDND_WidgetInsertDrop(DndClass *dnd, unsigned char *data, int length, int remaining, Window into, Window from, Atom type) { Tk_Window tkwin; Tcl_Obj *dataObj; Tcl_DString dString; DndInfo *infoPtr; DndType *typePtr; Atom typelist[2] = {0, 0}; char *pathName; int ret; typelist[0] = type; /* Get window path... */ XDND_DEBUG(" Starting ...\n"); tkwin = Tk_IdToWindow(dnd->display, into); if (tkwin == NULL) return False; pathName = Tk_PathName(tkwin); if (pathName == NULL) { XDND_DEBUG(": This is a tk HIDDEN window\n"); return False; } XDND_DEBUG2(": state = %08X\n", dnd->state); if (TkDND_FindMatchingScript(&TkDND_TargetTable, pathName, NULL, typelist, TKDND_DROP, dnd->state, False, &typePtr, &infoPtr) != TCL_OK) { goto error; } if (infoPtr == NULL || typePtr == NULL) { if (infoPtr == NULL) return False; XDND_DEBUG(": Not script found ...\n"); return True; } dnd->interp = infoPtr->interp; dnd->CallbackStatus = TCL_OK; XDND_DEBUG3(": Dropped data: (%d) \"%s\"\n", length, data); Tcl_DStringInit(&dString); if (typePtr->matchedType == None) { typePtr->matchedType = dnd->DesiredType; } dataObj = TkDND_CreateDataObjAccordingToType(typePtr, NULL, data, length); typePtr->matchedType = None; if (dataObj == NULL) return False; Tcl_IncrRefCount(dataObj); TkDND_ExpandPercents(infoPtr, typePtr, typePtr->script, &dString, dnd->x, dnd->y); XDND_DEBUG3(":\n script=\"%s\"\n data= \"%s\"\n", Tcl_DStringValue(&dString), Tcl_GetString(dataObj)); ret = TkDND_ExecuteBinding(dnd->interp, Tcl_DStringValue(&dString), -1, dataObj); Tcl_DStringFree(&dString); Tcl_DecrRefCount(dataObj); if (ret == TCL_ERROR) { goto error; } return True; error: dnd->CallbackStatus = TCL_ERROR; XUngrabPointer (dnd->display, CurrentTime); Tk_BackgroundError(infoPtr->interp); while (Tcl_DoOneEvent(TCL_IDLE_EVENTS) != 0) { XDND_DEBUG("######## INSIDE LOOP - TkDND_WidgetInsertDrop!\n"); /* Empty loop body */ } return False; } /* TkDND_WidgetInsertDrop */ /* *---------------------------------------------------------------------- * * TkDND_WidgetAsk -- * * This function is responsible for executing the tcl binding that will * handle the ask action. If not a binding is defined, a default * procedure from the dnd tcl library is used... * * Results: * True on success, False on failure. * * Side effects: * What ever the tcl scrips do... * *---------------------------------------------------------------------- */ static int TkDND_WidgetAsk(DndClass *dnd, Window source, Window target, Atom *action) { Tk_Window tkwin; Tcl_HashEntry *hPtr; Tcl_DString dString; DndInfo *infoPtr; DndType *curr; char *pathName, *script = (char*)"::dnd::ChooseAskAction %W %X %Y %a %d"; int ret; dnd->CallbackStatus = TCL_OK; /* Get window path... */ tkwin = Tk_IdToWindow(dnd->display, target); if (tkwin == NULL) { XDND_DEBUG("TkDND_WidgetAsk: This is a FOREIGN window\n"); return False; } pathName = Tk_PathName(tkwin); if (pathName == NULL) { XDND_DEBUG("TkDND_WidgetAsk: This is a tk HIDDEN window\n"); return False; } /* See if its a drag source */ hPtr = Tcl_FindHashEntry(&TkDND_TargetTable, pathName); if (hPtr == NULL) { XDND_DEBUG2("TkDND_WidgetAsk: Window %s is NOT a DROP TARGET...\n", pathName); return False; } infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { if ( (curr->type != None && curr->type == dnd->DesiredType && curr->eventType == TKDND_ASK) || (curr->type == None && curr->matchedType == dnd->DesiredType && curr->eventType == TKDND_ASK) ) { /* * Simplified after proposal from Laurent Riesterer, * 24/06/2000: */ script = curr->script; break; } } /* Execute the script or default procedure if none was found ... */ Tcl_DStringInit(&dString); TkDND_ExpandPercents(infoPtr, curr, script, &dString, dnd->x, dnd->y); ret = TkDND_ExecuteBinding(infoPtr->interp, Tcl_DStringValue(&dString),-1, NULL); Tcl_DStringFree(&dString); if (ret == TCL_ERROR) { dnd->CallbackStatus = TCL_ERROR; Tk_BackgroundError(dnd->interp); while (Tcl_DoOneEvent(TCL_IDLE_EVENTS) != 0) { XDND_DEBUG("######## INSIDE LOOP - TkDND_WidgetAsk!\n"); /* Empty loop body */ } } else if (ret == TCL_BREAK) { XDND_DEBUG("TkDND_WidgetAsk: Widget refused to post dialog " "(returned TCL_BREAK)\n"); return False; } TkDND_ParseAction(dnd, infoPtr, NULL, dnd->DNDActionCopyXAtom, action, NULL); if (*action == dnd->DNDActionAskXAtom || dnd->CallbackStatus == TCL_BREAK) { /* Returning again Ask is not allowed! */ *action = None; } return True; } /* TkDND_WidgetAsk */ /* *---------------------------------------------------------------------- * * TkDND_WidgetGetData -- * * This function is responsible for executing the tcl binding that will * return the data to be dropped to us... * * Results: * A standart tcl result. * * Side effects: * The data is retrieved from widget and is stored inside the dnd * structure... * *---------------------------------------------------------------------- */ static int TkDND_WidgetGetData(DndClass *dnd, Window source, unsigned char **data, int *length, Atom type) { Tk_Window tkwin; Tcl_HashEntry *hPtr; Tcl_DString dString; DndInfo *infoPtr; DndType *curr; char *pathName; unsigned char *result; int ret; *data = NULL; *length = 0; dnd->CallbackStatus = TCL_OK; /* Get window path... */ tkwin = Tk_IdToWindow(dnd->display, source); if (tkwin == NULL) { XDND_DEBUG("TkDND_WidgetGetData: This is a FOREIGN window\n"); return False; } pathName = Tk_PathName(tkwin); if (pathName == NULL) { XDND_DEBUG("TkDND_WidgetGetData: This is a tk HIDDEN window\n"); return False; } /* See if its a drag source */ hPtr = Tcl_FindHashEntry(&TkDND_SourceTable, pathName); if (hPtr == NULL) { XDND_DEBUG2("TkDND_WidgetGetData: Window %s is NOT a DRAG SOURCE...\n", pathName); return False; } infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { if (curr->type == type) { Tcl_DStringInit(&dString); TkDND_ExpandPercents(infoPtr, curr, curr->script, &dString,dnd->x,dnd->y); XDND_DEBUG2(": %s\n", Tcl_DStringValue(&dString)); ret = TkDND_ExecuteBinding(infoPtr->interp, Tcl_DStringValue(&dString), -1, NULL); Tcl_DStringFree(&dString); dnd->CallbackStatus = ret; if (ret == TCL_ERROR) { XUngrabPointer (dnd->display, CurrentTime); Tk_BackgroundError(infoPtr->interp); } else if (ret == TCL_BREAK) { *data = NULL; *length = 0; XDND_DEBUG("TkDND_WidgetGetData: Widget refused to send data " "(returned TCL_BREAK)\n"); return False; } /* * Petasis, 14/12/2000: * What if infoPtr->inyterp == NULL? */ if (infoPtr->interp != NULL) { if (curr->matchedType == None) { curr->matchedType = dnd->DesiredType; } result = (unsigned char *) TkDND_GetDataAccordingToType(infoPtr, Tcl_GetObjResult(infoPtr->interp), curr, length); curr->matchedType = None; *data = (unsigned char *) result; } return True; } } return False; } /* TkDND_WidgetGetData */ /* *---------------------------------------------------------------------- * * TkDND_HandleEvents -- * * This function passes the given event to tk for processing. * * Results: * None * * Side effects: * - * *---------------------------------------------------------------------- */ static void TkDND_HandleEvents (DndClass *dnd, XEvent *xevent) { Tk_HandleEvent(xevent); } /* TkDND_HandleEvents */ /* *---------------------------------------------------------------------- * * TkDND_GetCurrentAtoms -- * * Returns an allocated Atom array filled with the types the specified * window supports as drag sources. * * Results: * An allocated Atom array. Returned space must be freed... * * Side effects: * - * *---------------------------------------------------------------------- */ static Atom *TkDND_GetCurrentAtoms(XDND *dnd, Window window) { Tcl_HashEntry *hPtr; DndInfo *infoPtr; Tk_Window tkwin; DndType *curr; Atom *TypeList; char *pathName; int length = 0; tkwin = Tk_IdToWindow(dnd->display, window); if (tkwin == NULL) return NULL; pathName = Tk_PathName(tkwin); if (pathName == NULL) return NULL; hPtr = Tcl_FindHashEntry(&TkDND_SourceTable, pathName); if (hPtr == NULL) return NULL; infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { length++; } TypeList = (Atom *) Tcl_Alloc(sizeof(Atom)*(length+1)); length = 0; for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { TypeList[length++] = curr->type; } TypeList[length] = 0; return TypeList; } /* TkDND_GetCurrentAtoms */ /* *---------------------------------------------------------------------- * * TkDND_SetCursor -- * * Changes the current cursor to the given one. * * Results: * Returns 0 on error, 1 otherwise. * * Side effects: * The current cursor is changed. * *---------------------------------------------------------------------- */ static int TkDND_SetCursor(DndClass *dnd, int cursor) { static int current_cursor = -1, x = 0, y = 0; int ret; Tcl_DString dString; DndInfo info; DndType type; /* * Laurent Riesterer 21/06/2000: * Proposed the use of "XChangeActivePointerGrab" instead of * "XGrabPointer"... */ /* * If cursor is -2, reset cache... */ if (cursor == -2) { current_cursor = -1; return True; } if (cursor > -1 && current_cursor != cursor) { XChangeActivePointerGrab(dnd->display, ButtonMotionMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask, dnd->cursors[cursor].cursor, CurrentTime); current_cursor = cursor; } /* * If a cursor window is specified by the user, move it to follow cursor... */ if (dnd->CursorWindow != NULL && (x != dnd->x || y != dnd->y)) { Tk_MoveToplevelWindow(dnd->CursorWindow, dnd->x+10, dnd->y); Tk_RestackWindow(dnd->CursorWindow, Above, NULL); x = dnd->x; y = dnd->y; /* * Has also the user registered a Cursor Callback? */ if (dnd->CursorCallback != NULL && dnd->interp != NULL) { info.tkwin = Tk_IdToWindow(dnd->display, dnd->DraggerWindow); if (current_cursor > XDND_NODROP_CURSOR) { type.typeStr = (char *) Tk_GetAtomName(info.tkwin, dnd->DesiredType); type.script = (char*)""; } else { type.typeStr = (char*)""; type.script = NULL; } Tcl_Preserve((ClientData) dnd->interp); Tcl_DStringInit(&dString); TkDND_ExpandPercents(&info, &type, dnd->CursorCallback, &dString, x, y); ret = TkDND_ExecuteBinding(dnd->interp, Tcl_DStringValue(&dString), -1, NULL); Tcl_DStringFree(&dString); if (ret == TCL_ERROR) { XUngrabPointer(dnd->display, CurrentTime); Tk_BackgroundError(dnd->interp); Tcl_Release((ClientData) dnd->interp); TkDND_Update(dnd->display, 0); dnd->CallbackStatus = TCL_ERROR; return False; } Tcl_Release((ClientData) dnd->interp); } else if (dnd->interp == NULL) { /* * I guess the interp should not be null, but let's ignore * that for now. -- hobbs 05/2002 panic("dnd->interp is null"); * We may instead want to make sure to ungrab the pointer and * change the cursor back. TkDND_Update(dnd->display, 0); return False; */ } } /* Simulate "update"... */ TkDND_Update(dnd->display, 0); return True; } /* TkDND_SetCursor */ /* *---------------------------------------------------------------------- * * TkDND_XDNDHandler -- * * Our XDND ClientMessage handler. * * Results: * Returns 0 if the ClientMessage is not XDND related, 0 otherwise. * * Side effects: * ? * *---------------------------------------------------------------------- */ static int TkDND_XDNDHandler(Tk_Window winPtr, XEvent *eventPtr) { if (eventPtr->type != ClientMessage) return False; return XDND_HandleClientMessage(dnd, eventPtr); } /* TkDND_XDNDHandler */ /* *---------------------------------------------------------------------- * * TkDND_AddHandler -- * * Add a drag&drop handler to a window, freeing up any memory and * objects that need to be cleaned up. * * Arguments: * interp: Tcl interpreter * topwin: The main window * table: Hash table we are adding the window/type to * windowPath: String pathname of window * typeStr: The data type to add. * script: Script to run * isDropTarget: Is this target a drop target? * priority: Priority of this type * * Results: * A standard Tcl result * * Notes: * The table that is passed in must have been initialized. * Inserts a new node in the typelist for the window with the * highest priorities listed first. * *---------------------------------------------------------------------- */ int TkDND_AddHandler(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask, char *script, int isDropTarget, int priority) { Tcl_HashEntry *hPtr; DndInfo *infoPtr; DndType *head, *prev, *curr, *tnew; Tk_Window tkwin; Window win; Atom atom; #define TkDND_ACTUAL_TYPE_NU 15 char *ActualType[TkDND_ACTUAL_TYPE_NU]; int created, len, i, removed = False; tkwin = Tk_NameToWindow(interp, windowPath, topwin); if (tkwin == NULL) return TCL_ERROR; Tk_MakeWindowExist(tkwin); win = Tk_WindowId(tkwin); /* Now we have priorities, event for Drag sources... */ /*if (!isDropTarget) priority = 0;*/ /* * Do we already have a binding script for this type of type/event? * Remember that we have to search all entries in order to remove all of * them that have the same typeStr but different actual types... */ hPtr = Tcl_CreateHashEntry(table, windowPath, &created); if (!created) { infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); for (curr = (&infoPtr->head)->next; curr != NULL; curr = curr->next) { if (strcmp(curr->typeStr, typeStr) == 0 && curr->eventType == eventType && curr->eventMask == eventMask) { /* * Replace older script... */ Tcl_Free(curr->script); len = strlen(script) + 1; curr->script = (char *) Tcl_Alloc(sizeof(char)*len); memcpy(curr->script, script, len); removed = True; } } } if (removed) return TCL_OK; /* * In order to ensure portability among different protocols, we have to * register more than one type for each "platform independed" type * requested by the user... */ i = 0; if (strcmp(typeStr, "text/plain;charset=UTF-8") == 0) { /* * Here we handle our platform independed way to transer UTF strings... */ ActualType[i++] = (char*)"text/plain;charset=UTF-8"; /* XDND Protocol */ ActualType[i++] = (char*)"CF_UNICODETEXT"; /* OLE DND Protocol */ ActualType[i++] = NULL; } else if (strcmp(typeStr, "text/plain") == 0) { /* * Here we handle our platform independed way to pass ASCII strings */ ActualType[i++] = (char*)"text/plain"; /* XDND Protocol */ ActualType[i++] = (char*)"STRING"; /* Motif Protocol */ ActualType[i++] = (char*)"TEXT"; /* Motif Protocol */ ActualType[i++] = (char*)"COMPOUND_TEXT"; /* Motif Protocol */ ActualType[i++] = (char*)"CF_TEXT"; /* OLE DND Protocol */ ActualType[i++] = (char*)"CF_OEMTEXT"; /* OLE DND Protocol */ ActualType[i++] = NULL; } else if (strcmp(typeStr, "text/uri-list") == 0 || strcmp(typeStr, "Files") == 0 ) { /* * Here we handle our platform independed way to transer File Names... */ ActualType[i++] = (char*)"text/uri-list"; /* XDND Protocol */ ActualType[i++] = (char*)"text/file"; /* XDND Protocol */ ActualType[i++] = (char*)"text/url"; /* XDND Protocol */ ActualType[i++] = (char*)"url/url"; /* XDND Protocol */ ActualType[i++] = (char*)"FILE_NAME"; /* Motif Protocol */ ActualType[i++] = (char*)"SGI_FILE"; /* Motif Protocol */ ActualType[i++] = (char*)"_NETSCAPE_URL"; /* Motif Protocol */ ActualType[i++] = (char*)"_MOZILLA_URL"; /* Motif Protocol */ ActualType[i++] = (char*)"_SGI_URL"; /* Motif Protocol */ ActualType[i++] = (char*)"CF_HDROP"; /* OLE DND Protocol */ ActualType[i++] = NULL; } else if (strcmp(typeStr, "Text") == 0) { /* * Here we handle our platform independed way to all supported text * formats... */ ActualType[i++] = (char*)"text/plain;charset=UTF-8"; /* XDND Protocol */ ActualType[i++] = (char*)"text/plain"; /* XDND Protocol */ ActualType[i++] = (char*)"STRING"; /* Motif Protocol */ ActualType[i++] = (char*)"TEXT"; /* Motif Protocol */ ActualType[i++] = (char*)"COMPOUND_TEXT"; /* Motif Protocol */ ActualType[i++] = (char*)"CF_UNICODETEXT"; /* OLE DND Protocol */ ActualType[i++] = (char*)"CF_OEMTEXT"; /* OLE DND Protocol */ ActualType[i++] = (char*)"CF_TEXT"; /* OLE DND Protocol */ ActualType[i++] = NULL; } else if (strcmp(typeStr, "Image") == 0) { /* * Here we handle our platform independed way to all supported text * formats... */ ActualType[i++] = (char*)"CF_DIB"; /* OLE DND Protocol */ ActualType[i++] = NULL; } else { /* * This is a platform specific type. Register it as is... */ ActualType[i++] = typeStr; ActualType[i++] = NULL; } for (i=0; ipriority = priority; tnew->matchedType = None; len = strlen(typeStr) + 1; tnew->typeStr = (char *) Tcl_Alloc(sizeof(char)*len); memcpy(tnew->typeStr, typeStr, len); tnew->eventType = eventType; tnew->eventMask = eventMask; len = strlen(script) + 1; tnew->script = (char *) Tcl_Alloc(sizeof(char)*len); memcpy(tnew->script, script, len); tnew->next = NULL; tnew->EnterEventSent = 0; /* Has the type a wildcard character? */ if (strchr(ActualType[i], '*') == NULL) { atom = Tk_InternAtom(tkwin, ActualType[i]); } else { atom = None; } tnew->type = atom; if (created) { infoPtr = (DndInfo *) Tcl_Alloc(sizeof(DndInfo)); infoPtr->head.next = NULL; infoPtr->interp = interp; infoPtr->tkwin = tkwin; infoPtr->hashEntry = hPtr; /* infoPtr->IDropTarget = isDropTarget; */ Tk_CreateEventHandler(tkwin, StructureNotifyMask, TkDND_DestroyEventProc, (ClientData) infoPtr); Tcl_SetHashValue(hPtr, infoPtr); infoPtr->head.next = tnew; /* Make window DND aware... */ XDND_Enable(dnd, win); created = False; } else { infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); infoPtr->tkwin = tkwin; head = prev = &infoPtr->head; /* * Laurent Riesterer 09/07/2000: * fix start of list to correctly handle priority... */ for (curr = head->next; curr != NULL; prev = curr, curr = curr->next) { if (curr->priority > priority) break; } XDND_DEBUG5("<> type='%s','%s'" " / event=%ld / mask=%08x\n", typeStr, ActualType[i], eventType, (unsigned int) eventMask); XDND_DEBUG3("<> curr.prio=%d / tnew.prio=%d\n", (curr ? curr->priority:-1), tnew->priority); tnew->next = prev->next; prev->next = tnew; } } /* for (i=0; iDesiredType); } /* TkDND_GetCurrentTypeName */ /* *---------------------------------------------------------------------- * TkDND_GetCurrentTypeCode -- * Returns a string that describes the current dnd type code in hex. * * Results: * A dynamic string. Should be freed. * * Notes: *---------------------------------------------------------------------- */ char *TkDND_GetCurrentTypeCode(void) { char tmp[64], *str; sprintf(tmp, "0x%08x", (unsigned int)dnd->DesiredType); str = Tcl_Alloc(sizeof(char) * strlen(tmp)); strcpy(str, tmp); return str; } /* TkDND_GetCurrentTypeCode */ /* *---------------------------------------------------------------------- * TkDND_GetCurrentActionName -- * Returns a string that describes the current dnd action. * * Results: * A static string. Should never be freed. * * Notes: *---------------------------------------------------------------------- */ char *TkDND_GetCurrentActionName(void) { Atom action = dnd->SupportedAction; if (action == dnd->DNDActionCopyXAtom) return (char*)"copy"; if (action == dnd->DNDActionMoveXAtom) return (char*)"move"; if (action == dnd->DNDActionLinkXAtom) return (char*)"link"; if (action == dnd->DNDActionAskXAtom) return (char*)"ask"; if (action == dnd->DNDActionPrivateXAtom) return (char*)"private"; return (char*)"unknown"; } /* TkDND_GetCurrentActionName */ /* *---------------------------------------------------------------------- * TkDND_GetCurrentButton -- * Returns a integer that describes the current button used * for the drag operation. (Laurent Riesterer, 24/06/2000) * * Results: * An integer. * * Notes: *---------------------------------------------------------------------- */ int TkDND_GetCurrentButton(void) { return dnd->button; } /* TkDND_GetCurrentButton */ /* *---------------------------------------------------------------------- * TkDND_GetCurrentModifiers -- * Returns a string that describes the modifiers that are currently * pressed during a drag and drop operation. * (Laurent Riesterer, 24/06/2000) * Results: * A dynamic string. Should be freed. * * Notes: *---------------------------------------------------------------------- */ char *TkDND_GetCurrentModifiers(Tk_Window tkwin) { Tcl_DString ds; char *str; unsigned int AltMsk, MetaMsk; AltMsk = dnd->Alt_ModifierMask; MetaMsk = dnd->Meta_ModifierMask; Tcl_DStringInit(&ds); if (dnd->state & ShiftMask) Tcl_DStringAppendElement(&ds, "Shift"); if (dnd->state & ControlMask) Tcl_DStringAppendElement(&ds, "Control"); if (dnd->state & AltMsk) Tcl_DStringAppendElement(&ds, "Alt"); if (dnd->state & MetaMsk) Tcl_DStringAppendElement(&ds, "Meta"); if (dnd->state & Mod1Mask && AltMsk != Mod1Mask && MetaMsk != Mod1Mask) Tcl_DStringAppendElement(&ds, "Mod1"); if (dnd->state & Mod2Mask && AltMsk != Mod2Mask && MetaMsk != Mod2Mask) Tcl_DStringAppendElement(&ds, "Mod2"); if (dnd->state & Mod3Mask && AltMsk != Mod3Mask && MetaMsk != Mod3Mask) Tcl_DStringAppendElement(&ds, "Mod3"); if (dnd->state & Mod4Mask && AltMsk != Mod4Mask && MetaMsk != Mod4Mask) Tcl_DStringAppendElement(&ds, "Mod4"); if (dnd->state & Mod5Mask && AltMsk != Mod5Mask && MetaMsk != Mod5Mask) Tcl_DStringAppendElement(&ds, "Mod5"); str = Tcl_Alloc(sizeof(char) * (Tcl_DStringLength(&ds)+1)); memcpy(str, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)+1); Tcl_DStringFree(&ds); return str; } /* TkDND_GetCurrentModifiers */ /* *---------------------------------------------------------------------- * TkDND_GetSourceActions -- * Returns a string that describes the supported by the target actions. * * Results: * A dynamic string. Should be freed. * * Notes: *---------------------------------------------------------------------- */ char *TkDND_GetSourceActions(void) { Atom *action = dnd->DraggerAskActionList; Tcl_DString ds; char *str; Tcl_DStringInit(&ds); if (action != NULL) { while (*action != None) { if (*action == dnd->DNDActionCopyXAtom) str = (char*)"copy"; else if (*action == dnd->DNDActionMoveXAtom) str = (char*)"move"; else if (*action == dnd->DNDActionLinkXAtom) str = (char*)"link"; else if (*action == dnd->DNDActionAskXAtom) str = (char*)"ask"; else if (*action == dnd->DNDActionPrivateXAtom) str = (char*)"private"; else str = (char*)"unknown"; Tcl_DStringAppendElement(&ds, str); action++; } } str = Tcl_Alloc(sizeof(char) * (Tcl_DStringLength(&ds)+1)); memcpy(str, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)+1); Tcl_DStringFree(&ds); return str; } /* TkDND_GetSourceActions */ /* *---------------------------------------------------------------------- * TkDND_GetSourceActionDescriptions -- * Returns a string that describes the supported by the target action * descriptions. * * Results: * A dynamic string. Should be freed. * * Notes: *---------------------------------------------------------------------- */ char *TkDND_GetSourceActionDescriptions(void) { char *descriptions = NULL; Tcl_DString ds; char *str; Tcl_DStringInit(&ds); if (dnd->DraggerAskDescriptions != NULL) { descriptions = dnd->DraggerAskDescriptions; } if (descriptions != NULL) { while (*descriptions != '\0') { Tcl_DStringAppendElement(&ds, descriptions); descriptions += strlen(descriptions)+1 ; } } str = Tcl_Alloc(sizeof(char) * (Tcl_DStringLength(&ds)+1)); memcpy(str, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)+1); Tcl_DStringFree(&ds); return str; } /* TkDND_GetSourceActionDescriptions */ /* *---------------------------------------------------------------------- * TkDND_GetSourceTypeList -- * Returns a string that describes the supported by the drag source * types. * * Results: * A dynamic string. Should be freed. * * Notes: * Feature not supported by OLE DND. Simulated. *---------------------------------------------------------------------- */ char *TkDND_GetSourceTypeList(void) { Tcl_DString ds; Atom *typelist = dnd->DraggerTypeList; char *str; int i; Tcl_DStringInit(&ds); for (i = 0; typelist && typelist[i] != None; i++) { Tcl_DStringAppendElement(&ds, TkDND_TypeToString(typelist[i])); } str = Tcl_Alloc(sizeof(char) * (Tcl_DStringLength(&ds)+1)); memcpy(str, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)+1); Tcl_DStringFree(&ds); return str; } /* TkDND_GetSourceTypeList */ /* *---------------------------------------------------------------------- * TkDND_GetSourceTypeCodeList -- * Returns a string that describes the supported by the target action * descriptions. * * Results: * A dynamic string. Should be freed. * * Notes: * Feature not supported by OLE DND. Simulated. *---------------------------------------------------------------------- */ char *TkDND_GetSourceTypeCodeList(void) { Tcl_DString ds; Atom *atomPtr = dnd->DraggerTypeList; char *str, tmp[64]; Tcl_DStringInit(&ds); for (atomPtr = dnd->DraggerTypeList; *atomPtr != None; atomPtr++) { sprintf(tmp, "0x%08x", (unsigned int)*atomPtr); Tcl_DStringAppendElement(&ds, tmp); } str = Tcl_Alloc(sizeof(char) * (Tcl_DStringLength(&ds)+1)); memcpy(str, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)+1); Tcl_DStringFree(&ds); return str; } /* TkDND_GetSourceTypeCodeList */ /* *---------------------------------------------------------------------- * TkDND_DndDrag -- * Begins a drag and returns when the drop finishes or the * operation is cancelled. * * Results: * Standard TCL result * * Notes: * windowPath is assumed to be a valid Tk window pathname at this * point. *---------------------------------------------------------------------- */ int TkDND_DndDrag(Tcl_Interp *interp, char *windowPath, int button, Tcl_Obj *Actions, char *Descriptions, Tk_Window cursor_window, char *cursor_callback) { Tcl_HashEntry *hPtr; Tcl_Obj **elem; Atom *atom, actions[6] = {0, 0, 0, 0, 0, 0}; DndInfo *infoPtr; DndType *curr; char *action; int type_count = 1, elem_nu, i, result; hPtr = Tcl_FindHashEntry(&TkDND_SourceTable, windowPath); if (hPtr == NULL) { Tcl_AppendResult(interp, "unable to begin drag operation: ", "no source types have been bound to ", windowPath, (char *) NULL); return TCL_ERROR; } infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { type_count++; } atom = (Atom *) Tcl_Alloc(sizeof(Atom)*(type_count+1)); type_count = 0; for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { atom[type_count++] = curr->type; XDND_DEBUG2("TkDND_DndDrag: Adding type: %s\n", curr->typeStr); } atom[type_count] = 0; /* * Handle User-requested Actions... */ if (Actions == NULL) { /* The User has not specified any actions: defaults to copy... */ actions[0] = dnd->DNDActionCopyXAtom; memset(Descriptions, '\0', TKDND_MAX_DESCRIPTIONS_LENGTH); strcpy(Descriptions, "Copy\0\0"); } else { Tcl_ListObjGetElements(interp, Actions, &elem_nu, &elem); for (i = 0; i < elem_nu; i++) { action = Tcl_GetString(elem[i]); if (strcmp(action,"copy")==0) actions[i] = dnd->DNDActionCopyXAtom; else if (strcmp(action,"move")==0) actions[i] = dnd->DNDActionMoveXAtom; else if (strcmp(action,"link")==0) actions[i] = dnd->DNDActionLinkXAtom; else if (strcmp(action,"ask" )==0) actions[i] = dnd->DNDActionAskXAtom; else actions[i] = dnd->DNDActionPrivateXAtom; } actions[5] = 0; } /* * Install an XError Handler, so in case some XDND aware application * crashes to not also crash us with a BadWindow or similar error... */ TkDND_StartProtectedSection(Tk_Display(infoPtr->tkwin), infoPtr->tkwin); dnd->button = button; result = XDND_BeginDrag(dnd, Tk_WindowId(infoPtr->tkwin), actions, atom, Descriptions, cursor_window, cursor_callback); if(result) { /* DND was successful! */ Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); } else { /* DND was not successful. Make sure all widgets get ... */ /* TkDND_WidgetApplyLeave(dnd, dnd->dropper_window); */ Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); } XDND_Reset(dnd); /* * Restore default XError Handler... */ TkDND_EndProtectedSection(Tk_Display(infoPtr->tkwin)); /* * Don't free it, XDND_Reset has already freed it * Tcl_Free((char *) atom); */ return TCL_OK; } int TkDND_GetDataFromImage(DndInfo *info, char *imageName, char *type, char **result, int *length) { /* TODO: implement :-) */ return 0; } /* TkDND_GetDataFromImage */ /* *---------------------------------------------------------------------- * TkDND_LocalErrorHandler -- * Our local XDND XError Handler. * * Results: * * Notes: *---------------------------------------------------------------------- */ static int TkDND_LocalErrorHandler(Display *display, XErrorEvent *error) { char buffer[512]; int return_val = 0; if (error->error_code == BadWindow && error->resourceid == Tk_WindowId(ProtectionOwnerWindow) && error->serial >= FirstProtectRequest) { /* This error is for us :-) */ fprintf(stderr, "tkdnd: XError caugth:\n"); XGetErrorText(display, error->error_code, buffer, 511); fprintf(stderr, " %s\n", buffer); return 0; } /* Not for us. Try to call the default error handler... */ if (PreviousErrorHandler != NULL) { return_val = (*PreviousErrorHandler)(display, error); } return return_val; } /* TkDND_LocalErrorHandler */ /* *---------------------------------------------------------------------- * TkDND_StartProtectedSection -- * Registers an XError Handler. * * Results: * None * * Notes: *---------------------------------------------------------------------- */ static void TkDND_StartProtectedSection(Display *display, Tk_Window window) { PreviousErrorHandler = XSetErrorHandler(TkDND_LocalErrorHandler); FirstProtectRequest = NextRequest(display); ProtectionOwnerWindow = window; } /* TkDND_StartProtectedSection */ /* *---------------------------------------------------------------------- * TkDND_EndProtectedSection -- * Restores the default XError Handler. * * Results: * None * * Notes: *---------------------------------------------------------------------- */ static void TkDND_EndProtectedSection(Display *display) { XSync(display, False); XSetErrorHandler(PreviousErrorHandler); PreviousErrorHandler = NULL; ProtectionOwnerWindow = NULL; } /* TkDND_EndProtectedSection */ /*static Window TkDND_GetXParent(DndClass *dnd, Window w) { Window root, parent, *kids; unsigned int nkids; if (XQueryTree(dnd->display, w, &root, &parent, &kids, &nkids)) { if (kids) { XFree(kids); } if (parent!=root) { return parent; } } return None; }*/ #ifdef TKDND_ENABLE_SHAPE_EXTENSION #include "Shape/shape.c" #endif /* TKDND_ENABLE_SHAPE_EXTENSION */ /* * End of tkXDND.c */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/Cursors.h0000644000175000017500000001434010562165600022737 0ustar domibeldomibel/* * Define DND Cursors... */ /* No Drop Cursor... */ #define noDropCursorWidth 20 #define noDropCursorHeight 20 #define noDropCursorX 10 #define noDropCursorY 10 static unsigned char noDropCurBits[] = { 0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01, 0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06, 0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03, 0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00}; static unsigned char noDropCurMask[] = { 0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03, 0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f, 0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07, 0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00}; /* Copy Cursor... */ #define CopyCursorWidth 29 #define CopyCursorHeight 25 #define CopyCursorX 10 #define CopyCursorY 10 static unsigned char CopyCurBits[] = { 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0xe8, 0x0f, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static unsigned char CopyCurMask[] = { 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00}; /* Move Cursor... */ #define MoveCursorWidth 21 #define MoveCursorHeight 25 #define MoveCursorX 10 #define MoveCursorY 10 static unsigned char MoveCurBits[] = { 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x04, 0x08, 0x02, 0x0c, 0x08, 0x02, 0x1c, 0x08, 0x02, 0x3c, 0x08, 0x02, 0x7c, 0x08, 0x02, 0xfc, 0x08, 0x02, 0xfc, 0x09, 0x02, 0xfc, 0x0b, 0x02, 0x7c, 0x08, 0xfe, 0x6d, 0x0f, 0x00, 0xc4, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00}; static unsigned char MoveCurMask[] = { 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1f, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x06, 0x1c, 0x07, 0x0e, 0x1c, 0x07, 0x1e, 0x1c, 0x07, 0x3e, 0x1c, 0x07, 0x7e, 0x1c, 0x07, 0xfe, 0x1c, 0x07, 0xfe, 0x1d, 0x07, 0xfe, 0x1f, 0x07, 0xfe, 0x1f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1e, 0xff, 0xef, 0x1f, 0x00, 0xe6, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01}; /* Link Cursor... */ #define LinkCursorWidth 29 #define LinkCursorHeight 25 #define LinkCursorX 10 #define LinkCursorY 10 static unsigned char LinkCurBits[] = { 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0xe8, 0x0f, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static unsigned char LinkCurMask[] = { 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00}; /* Ask Cursor... */ #define AskCursorWidth 29 #define AskCursorHeight 25 #define AskCursorX 10 #define AskCursorY 10 static unsigned char AskCurBits[] = { 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x88, 0x03, 0x02, 0x00, 0x48, 0x04, 0x02, 0x00, 0x08, 0x04, 0x02, 0x00, 0x08, 0x02, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static unsigned char AskCurMask[] = { 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00}; kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/Motif/0000755000175000017500000000000011461110203022166 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/Motif/lib/0000755000175000017500000000000011461110203022734 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/Motif/lib/Dnd.h0000644000175000017500000000620510562165466023643 0ustar domibeldomibel/***********************************************************/ /* Copyright 1996 Daniel Dardailler. Permission to use, copy, modify, distribute, and sell this software for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Daniel Dardailler not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Daniel Dardailler makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ************************************************************/ #ifndef _DnD_h #define _DnD_h /* This is a Dnd Dynamic Motif-compliant Protocol messaging API */ /* Only requires Xlib layer */ #include #include #define DndVersion 1 #define DndRevision 0 #define DndIncludeVersion (DndVersion * 10 + DndRevision) /* The following values are used in the DndData structure */ /* protocol style */ #define DND_DRAG_NONE 0 #define DND_DRAG_DROP_ONLY 1 #define DND_DRAG_DYNAMIC 5 /* message type */ #define DND_TOP_LEVEL_ENTER 0 #define DND_TOP_LEVEL_LEAVE 1 #define DND_DRAG_MOTION 2 #define DND_DROP_SITE_ENTER 3 #define DND_DROP_SITE_LEAVE 4 #define DND_DROP_START 5 #define DND_OPERATION_CHANGED 8 /* operation(s) */ #define DND_NOOP 0L #define DND_MOVE (1L << 0) #define DND_COPY (1L << 1) #define DND_LINK (1L << 2) /* status */ #define DND_NO_DROP_SITE 1 #define DND_INVALID_DROP_SITE 2 #define DND_VALID_DROP_SITE 3 /* completion */ #define DND_DROP 0 #define DND_DROP_HELP 1 #define DND_DROP_CANCEL 2 /* Client side structure used in the API */ typedef struct { unsigned char reason; /* message type: DND_TOP_LEVEL_ENTER, etc */ Time time ; unsigned char operation; unsigned char operations; unsigned char status; unsigned char completion; short x ; short y ; Window src_window ; Atom property ; } DndData ; /* extern functions */ /* These provides for basic formatting of ICCCM message going back and forth during the D&D gesture */ extern void DndWriteSourceProperty(Display * dpy, Window window, Atom dnd_selection, Atom * targets, unsigned short num_targets); extern void DndReadSourceProperty(Display * dpy, Window window, Atom dnd_selection, Atom ** targets, unsigned short * num_targets); extern void DndWriteReceiverProperty(Display * dpy, Window window, unsigned char protocol_style); extern void DndReadReceiverProperty(Display * dpy, Window window, unsigned char * protocol_style); extern void DndFillClientMessage(Display * dpy, Window window, XClientMessageEvent *cm, DndData * dnd_data, char receiver); extern Bool DndParseClientMessage(XClientMessageEvent *cm, DndData * dnd_data, char * receiver); #endif /* _Dnd_h */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/Motif/lib/Dnd.c0000644000175000017500000002336510562163641023635 0ustar domibeldomibel/***********************************************************/ /* Copyright 1996 Daniel Dardailler. Permission to use, copy, modify, distribute, and sell this software for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Daniel Dardailler not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Daniel Dardailler makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ************************************************************/ /***********************************************************/ /* Motif Drag&Drop Dynamic Protocol messaging API code */ /* Only requires Xlib layer - not MT safe */ /* Author: Daniel Dardailler, daniel@x.org */ /***********************************************************/ #include #include static Atom atom_message_type, atom_receiver_info, atom_src_property_type; unsigned char _DndByteOrder (void) { static unsigned char byte_order = 0; if (!byte_order) { unsigned int endian = 1; byte_order = (*((char *)&endian))?'l':'B'; } return byte_order ; } static void InitAtoms(Display * dpy) { if (atom_message_type) return ; /* already Initialized */ /* Init atoms used in the com */ atom_message_type = XInternAtom(dpy, "_MOTIF_DRAG_AND_DROP_MESSAGE", False); atom_src_property_type = XInternAtom(dpy, "_MOTIF_DRAG_INITIATOR_INFO", False); atom_receiver_info = XInternAtom(dpy, "_MOTIF_DRAG_RECEIVER_INFO", False); } /* Position the _MOTIF_DRAG_INITIATOR_INFO property on the source window. Called by the source of the drag to indicate the supported target list (thru the index scheme) */ extern void DndWriteSourceProperty(Display * dpy, Window window, Atom dnd_selection, Atom * targets, unsigned short num_targets) { DndSrcProp src_prop ; InitAtoms(dpy); src_prop.byte_order = _DndByteOrder() ; src_prop.protocol_version = DND_PROTOCOL_VERSION; src_prop.target_index = _DndTargetsToIndex(dpy, targets, num_targets); /*if (src_prop.target_index == -1) return ;*/ src_prop.selection = dnd_selection ; /* write the buffer to the property */ XChangeProperty (dpy, window, dnd_selection, atom_src_property_type, 8, PropModeReplace, (unsigned char *)&src_prop, sizeof(DndSrcProp)); } extern void DndReadSourceProperty(Display * dpy, Window window, Atom dnd_selection, Atom ** targets, unsigned short * num_targets) { DndSrcProp * src_prop = NULL; Atom type ; int format ; unsigned long bytesafter, lengthRtn; InitAtoms(dpy); if ((XGetWindowProperty (dpy, window, dnd_selection, 0L, 100000L, False, atom_src_property_type, &type, &format, &lengthRtn, &bytesafter, (unsigned char **) &src_prop) != Success) || (type == None)) { #ifdef ENABLE_MOTIF_WARNINGS printf("No property - DndReadSourceProperty return 0 \n"); #endif *num_targets = 0; return ; } if (src_prop->byte_order != _DndByteOrder()) { SWAP2BYTES(src_prop->target_index); SWAP4BYTES(src_prop->selection); } *num_targets = _DndIndexToTargets(dpy, src_prop->target_index, targets); XFree((char*)src_prop); } /* Position the _MOTIF_DRAG_RECEIVER_INFO property on the dropsite window. Called by the receiver of the drop to indicate the supported protocol style : dynamic, drop_only or none */ extern void DndWriteReceiverProperty(Display * dpy, Window window, unsigned char protocol_style) { DndReceiverProp receiver_prop ; InitAtoms(dpy); receiver_prop.byte_order = _DndByteOrder() ; receiver_prop.protocol_version = DND_PROTOCOL_VERSION; receiver_prop.protocol_style = protocol_style ; receiver_prop.proxy_window = None ; receiver_prop.num_drop_sites = 0 ; receiver_prop.total_size = sizeof(DndReceiverProp); /* write the buffer to the property */ XChangeProperty (dpy, window, atom_receiver_info, atom_receiver_info, 8, PropModeReplace, (unsigned char *)&receiver_prop, sizeof(DndReceiverProp)); } /* protocol style equiv (preregister stuff really) */ #define DND_DRAG_DROP_ONLY_EQUIV 3 #define DND_DRAG_DYNAMIC_EQUIV1 2 #define DND_DRAG_DYNAMIC_EQUIV2 4 extern void DndReadReceiverProperty(Display * dpy, Window window, unsigned char * protocol_style) { DndReceiverProp *receiver_prop = NULL ; Atom type ; int format ; unsigned long bytesafter, lengthRtn; InitAtoms(dpy); if ((XGetWindowProperty (dpy, window, atom_receiver_info, /* _MOTIF_DRAG_RECEIVER_INFO */ 0L, 100000L, False, atom_receiver_info, &type, &format, &lengthRtn, &bytesafter, (unsigned char **) &receiver_prop) != Success) || (type == None)) { /* no property => no d&d */ *protocol_style = DND_DRAG_NONE ; return ; } /* in dynamic we don't really care about byte swapping since the pertinent info is all expressed in one byte quantities */ *protocol_style = receiver_prop->protocol_style; /* do the equiv stuff for Motif pre-register */ if (*protocol_style == DND_DRAG_DROP_ONLY_EQUIV) *protocol_style = DND_DRAG_DROP_ONLY ; else if (*protocol_style == DND_DRAG_DYNAMIC_EQUIV1 || *protocol_style == DND_DRAG_DYNAMIC_EQUIV2) *protocol_style = DND_DRAG_DYNAMIC ; XFree((void *)receiver_prop) ; } /* Produce a client message to be sent by the caller */ extern void DndFillClientMessage(Display * dpy, Window window, XClientMessageEvent *cm, DndData * dnd_data, char receiver) { DndMessage * dnd_message = (DndMessage*)&cm->data.b[0] ; InitAtoms(dpy); cm->display = dpy; cm->type = ClientMessage; cm->serial = LastKnownRequestProcessed(dpy); cm->send_event = True; cm->window = window; cm->format = 8; cm->message_type = atom_message_type ;/* _MOTIF_DRAG_AND_DROP_MESSAGE */ dnd_message->reason = dnd_data->reason | DND_SET_EVENT_TYPE(receiver); dnd_message->byte_order = _DndByteOrder(); /* we're filling in flags with more stuff that necessary, depending on the reason, but it doesn't matter */ dnd_message->flags = 0 ; dnd_message->flags |= DND_SET_STATUS(dnd_data->status) ; dnd_message->flags |= DND_SET_OPERATION(dnd_data->operation) ; dnd_message->flags |= DND_SET_OPERATIONS(dnd_data->operations) ; dnd_message->flags |= DND_SET_COMPLETION(dnd_data->completion) ; dnd_message->time = dnd_data->time ; switch(dnd_data->reason) { case DND_DROP_SITE_LEAVE: break ; case DND_TOP_LEVEL_ENTER: case DND_TOP_LEVEL_LEAVE: dnd_message->data.top.src_window = dnd_data->src_window ; dnd_message->data.top.property = dnd_data->property ; break ; /* cannot fall thru since the byte layout is different in both set of messages, see top and pot union stuff */ case DND_DRAG_MOTION: case DND_OPERATION_CHANGED: case DND_DROP_SITE_ENTER: case DND_DROP_START: dnd_message->data.pot.x = dnd_data->x ; /* mouse position */ dnd_message->data.pot.y = dnd_data->y ; dnd_message->data.pot.src_window = dnd_data->src_window ; dnd_message->data.pot.property = dnd_data->property ; break ; default: #ifdef ENABLE_MOTIF_WARNINGS printf("DndWriteClientMessage default: warning\n"); #endif break ; } } extern Bool DndParseClientMessage(XClientMessageEvent *cm, DndData * dnd_data, char * receiver) { DndMessage * dnd_message = (DndMessage*)&cm->data.b[0] ; InitAtoms(cm->display); if (cm->message_type != atom_message_type) { #ifdef ENABLE_MOTIF_WARNINGS printf("Invalid _MOTIF_DRAG_AND_DROP_MESSAGE - DndReadClientMessage fails\n"); #endif return False ; } if (dnd_message->byte_order != _DndByteOrder()) { SWAP2BYTES(dnd_message->flags); SWAP4BYTES(dnd_message->time); } /* do the rest in the switch */ dnd_data->reason = dnd_message->reason ; if (DND_GET_EVENT_TYPE(dnd_data->reason)) *receiver = 1 ; else *receiver = 0 ; dnd_data->reason &= DND_CLEAR_EVENT_TYPE ; dnd_data->time = dnd_message->time ; /* we're reading in more stuff that necessary. but who cares */ dnd_data->status = DND_GET_STATUS(dnd_message->flags) ; dnd_data->operation = DND_GET_OPERATION(dnd_message->flags) ; dnd_data->operations = DND_GET_OPERATIONS(dnd_message->flags) ; dnd_data->completion = DND_GET_COMPLETION(dnd_message->flags) ; switch(dnd_data->reason) { case DND_TOP_LEVEL_ENTER: case DND_TOP_LEVEL_LEAVE: if (dnd_message->byte_order != _DndByteOrder()) { SWAP4BYTES(dnd_message->data.top.src_window); SWAP4BYTES(dnd_message->data.top.property); } dnd_data->src_window = dnd_message->data.top.src_window ; dnd_data->property = dnd_message->data.top.property ; break ; /* cannot fall thru, see above comment in write msg */ case DND_DRAG_MOTION: case DND_OPERATION_CHANGED: case DND_DROP_SITE_ENTER: case DND_DROP_START: if (dnd_message->byte_order != _DndByteOrder()) { SWAP2BYTES(dnd_message->data.pot.x); SWAP2BYTES(dnd_message->data.pot.y); SWAP4BYTES(dnd_message->data.pot.property); SWAP4BYTES(dnd_message->data.pot.src_window); } dnd_data->x = dnd_message->data.pot.x ; dnd_data->y = dnd_message->data.pot.y ; dnd_data->property = dnd_message->data.pot.property ; dnd_data->src_window = dnd_message->data.pot.src_window ; break ; case DND_DROP_SITE_LEAVE: break; default: #ifdef ENABLE_MOTIF_WARNINGS printf("DndReadClientMessage default: warning\n"); #endif break ; } return True ; } kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/Motif/lib/Target.c0000644000175000017500000002134310674510742024352 0ustar domibeldomibel/***********************************************************/ /* Copyright 1996 Daniel Dardailler. Permission to use, copy, modify, distribute, and sell this software for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Daniel Dardailler not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Daniel Dardailler makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ************************************************************/ /***** Targets/Index stuff */ /* incomplete support: search for unsupported */ #include #include #include #include /* * For C++ compilers, use extern "C" */ #ifdef __cplusplus extern "C" { #endif static int AtomCompare(const void *atom1, const void *atom2 ); #ifdef __cplusplus } #endif static Atom atom_motif_window, atom_target_list ; static void InitAtoms(Display * dpy) { if (atom_motif_window) return ; /* already Initialized */ /* Init atoms used in the com */ atom_motif_window = XInternAtom(dpy, "_MOTIF_DRAG_WINDOW", False); atom_target_list = XInternAtom(dpy, "_MOTIF_DRAG_TARGETS", False); } static Window MotifWindow(Display *display ) { Atom type; int format; unsigned long size; unsigned long bytes_after; Window *property = NULL; Window motif_window ; /* this version does no caching, so it's slow: round trip each time */ if ((XGetWindowProperty (display, DefaultRootWindow(display), atom_motif_window, 0L, 100000L, False, AnyPropertyType, &type, &format, &size, &bytes_after, (unsigned char **) &property) == Success) && (type != None)) { motif_window = *property; } else { XSetWindowAttributes sAttributes; /* really, this should be done on a separate connection, with XSetCloseDownMode (RetainPermanent), so that others don't have to recreate it; hopefully, some real Motif application will be around to do it */ sAttributes.override_redirect = True; sAttributes.event_mask = PropertyChangeMask; motif_window = XCreateWindow (display, DefaultRootWindow (display), -170, -560, 1, 1, 0, 0, InputOnly, CopyFromParent, (CWOverrideRedirect |CWEventMask), &sAttributes); XMapWindow (display, motif_window); } if (property) { XFree ((char *)property); } return (motif_window); } static DndTargetsTable TargetsTable(Display *display) { Atom type; int format; unsigned long size; unsigned long bytes_after; Window motif_window = MotifWindow(display) ; DndTargets * target_prop; DndTargetsTable targets_table ; int i,j ; char * target_data ; /* this version does no caching, so it's slow: round trip each time */ /* ideally, register for property notify on this target_list atom and update when necessary only */ if ((XGetWindowProperty (display, motif_window, atom_target_list, 0L, 100000L, False, atom_target_list, &type, &format, &size, &bytes_after, (unsigned char **) &target_prop) != Success) || type == None) { #ifdef ENABLE_MOTIF_WARNINGS printf("Get Targets cannot get property on motif_window\n"); #endif return NULL ; } if (target_prop->protocol_version != DND_PROTOCOL_VERSION) { #ifdef ENABLE_MOTIF_WARNINGS printf("Get Targets warning: D&D protocol mismatch\n"); #endif } if (target_prop->byte_order != _DndByteOrder()) { /* need to swap num_target_lists and size */ SWAP2BYTES(target_prop->num_target_lists); SWAP4BYTES(target_prop->data_size); } /* now parse DndTarget prop data in a TargetsTable */ targets_table = (DndTargetsTable)malloc(sizeof(DndTargetsTableRec)); targets_table->num_entries = target_prop->num_target_lists ; targets_table->entries = (DndTargetsTableEntry) malloc(sizeof(DndTargetsTableEntryRec) * target_prop->num_target_lists); target_data = (char*)target_prop + sizeof(*target_prop) ; for (i=0 ; i < targets_table->num_entries; i++) { CARD16 num_targets ; CARD32 atom ; memcpy(&num_targets, target_data, 2); target_data += 2; /* potential swap needed here */ if (target_prop->byte_order != _DndByteOrder()) SWAP2BYTES(num_targets); targets_table->entries[i].num_targets = num_targets ; targets_table->entries[i].targets = (Atom *) malloc(sizeof(Atom) * targets_table->entries[i].num_targets); for (j = 0; j < num_targets; j++) { memcpy(&atom, target_data, 4 ); target_data += 4; /* another potential swap needed here */ if (target_prop->byte_order != _DndByteOrder()) SWAP4BYTES(atom); targets_table->entries[i].targets[j] = (Atom) atom ; } } if (target_prop) { XFree((char *)target_prop); } return targets_table ; } static int AtomCompare(const void *atom1, const void *atom2 ) { return (*((Atom *) atom1) - *((Atom *) atom2)); } extern int _DndTargetsToIndex(Display * display, Atom * targets, int num_targets) { int i, j; Atom *sorted_targets; DndTargetsTable targets_table; int index = -1 ; InitAtoms(display) ; if (!(targets_table = TargetsTable (display))|| (index >= targets_table->num_entries)) { #ifdef ENABLE_MOTIF_WARNINGS printf("_DndTargetsToIndex: cannot find the target table data\n"); #endif return -1 ; } /* sort the given target list */ sorted_targets = (Atom *) malloc(sizeof(Atom) * num_targets); memcpy (sorted_targets, targets, sizeof(Atom) * num_targets); qsort ((void *)sorted_targets, (size_t)num_targets, (size_t)sizeof(Atom), AtomCompare); /* look for a match */ for (i = 0; i < targets_table->num_entries; i++) { if (num_targets == targets_table->entries[i].num_targets) { for (j = 0; j < num_targets; j++) { if (sorted_targets[j] != targets_table->entries[i].targets[j]) { break; } } if (j == num_targets) { index = i ; break ; } } } XFree ((char *)sorted_targets); /* free the target table and its guts */ for (i=0 ; i < targets_table->num_entries; i++) XFree((char*)targets_table->entries[i].targets); XFree((char*)targets_table); #ifdef ENABLE_MOTIF_WARNINGS if (index == -1 ) printf("DndTargetsToIndex: non existing target list: unsupported\n"); #endif /* to support: need to grab the server, add our target list to the property, return index = num_entries++, and ungrab */ return index ; } int _DndIndexToTargets(Display * display, int index, Atom ** targets) { DndTargetsTable targets_table; int i, tmp; /* again, slow: no caching here, alloc/free each time */ InitAtoms(display) ; if (!(targets_table = TargetsTable (display)) || (index >= targets_table->num_entries)) { return -1; } /* transfer the correct target list index */ *targets = (Atom*)malloc(sizeof(Atom)*targets_table-> entries[index].num_targets); memcpy((char*)*targets, (char*)targets_table->entries[index].targets, sizeof(Atom)*targets_table->entries[index].num_targets); /* free the target table and its guts */ for (i=0 ; i < targets_table->num_entries; i++) XFree((char*)targets_table->entries[i].targets); tmp = targets_table->entries[index].num_targets; XFree((char*)targets_table); return tmp; /* targets_table->entries[index].num_targets;*/ } #if 0 int _DndIndexToTargets(Display * display, int index, Atom ** targets) { DndTargetsTable targets_table; int i ; /* again, slow: no caching here, alloc/free each time */ InitAtoms(display) ; printf("index %d\n", index); if (!(targets_table = TargetsTable (display)) || (index >= targets_table->num_entries)) { return -1; } /* transfer the correct target list index */ *targets = (Atom*)malloc(sizeof(Atom)*targets_table-> entries[index].num_targets); memcpy((char*)*targets, (char*)targets_table->entries[index].targets, sizeof(Atom)*targets_table->entries[index].num_targets); /* free the target table and its guts */ for (i=0 ; i < targets_table->num_entries; i++) XFree((char*)targets_table->entries[i].targets); XFree((char*)targets_table); return targets_table->entries[index].num_targets; } #endif kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/Motif/lib/DndP.h0000644000175000017500000001145310562166444023761 0ustar domibeldomibel/***********************************************************/ /* Copyright 1996 Daniel Dardailler. Permission to use, copy, modify, distribute, and sell this software for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Daniel Dardailler not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Daniel Dardailler makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ************************************************************/ #ifndef _DnDP_h #define _DnDP_h /*** Dnd Protocol stream structures and other low-level stuff */ #include #include typedef struct _DndSrcProp { BYTE byte_order ; BYTE protocol_version ; CARD16 target_index ; CARD32 selection ; } DndSrcProp ; typedef struct _DndReceiverProp { BYTE byte_order ; BYTE protocol_version ; BYTE protocol_style ; BYTE pad1; CARD32 proxy_window; CARD16 num_drop_sites ; CARD16 pad2; CARD32 total_size; } DndReceiverProp ; /* need to use some union hack since window and property are in different order depending on the message ... */ typedef struct _DndTop { CARD32 src_window; CARD32 property; } DndTop ; typedef struct _DndPot { INT16 x; INT16 y; CARD32 property; CARD32 src_window; } DndPot ; typedef struct _DndMessage { BYTE reason; BYTE byte_order; CARD16 flags; CARD32 time; union { DndTop top ; DndPot pot ; } data ; } DndMessage ; typedef struct { BYTE byte_order; BYTE protocol_version; CARD16 num_target_lists; CARD32 data_size; /* then come series of CARD16,CARD32,CARD32,CARD32... */ } DndTargets; /* protocol version */ #define DND_PROTOCOL_VERSION 0 #define DND_EVENT_TYPE_MASK ((BYTE)0x80) #define DND_EVENT_TYPE_SHIFT 7 #define DND_CLEAR_EVENT_TYPE ((BYTE)0x7F) /* message_type is data[0] of the client_message this return 1 (receiver bit up) or 0 (initiator) */ #define DND_GET_EVENT_TYPE(message_type) \ ((char) (((message_type) & DND_EVENT_TYPE_MASK) >> DND_EVENT_TYPE_SHIFT)) /* event_type can be 0 (initiator) or 1 (receiver) */ #define DND_SET_EVENT_TYPE(event_type) \ (((BYTE)(event_type) << DND_EVENT_TYPE_SHIFT) & DND_EVENT_TYPE_MASK) #define DND_OPERATION_MASK ((CARD16) 0x000F) #define DND_OPERATION_SHIFT 0 #define DND_STATUS_MASK ((CARD16) 0x00F0) #define DND_STATUS_SHIFT 4 #define DND_OPERATIONS_MASK ((CARD16) 0x0F00) #define DND_OPERATIONS_SHIFT 8 #define DND_COMPLETION_MASK ((CARD16) 0xF000) #define DND_COMPLETION_SHIFT 12 #define DND_GET_OPERATION(flags) \ ((unsigned char) \ (((flags) & DND_OPERATION_MASK) >> DND_OPERATION_SHIFT)) #define DND_SET_OPERATION(operation) \ (((CARD16)(operation) << DND_OPERATION_SHIFT)\ & DND_OPERATION_MASK) #define DND_GET_STATUS(flags) \ ((unsigned char) \ (((flags) & DND_STATUS_MASK) >> DND_STATUS_SHIFT)) #define DND_SET_STATUS(status) \ (((CARD16)(status) << DND_STATUS_SHIFT)\ & DND_STATUS_MASK) #define DND_GET_OPERATIONS(flags) \ ((unsigned char) \ (((flags) & DND_OPERATIONS_MASK) >> DND_OPERATIONS_SHIFT)) #define DND_SET_OPERATIONS(operation) \ (((CARD16)(operation) << DND_OPERATIONS_SHIFT)\ & DND_OPERATIONS_MASK) #define DND_GET_COMPLETION(flags) \ ((unsigned char) \ (((flags) & DND_COMPLETION_MASK) >> DND_COMPLETION_SHIFT)) #define DND_SET_COMPLETION(completion) \ (((CARD16)(completion) << DND_COMPLETION_SHIFT)\ & DND_COMPLETION_MASK) #define SWAP4BYTES(l) {\ struct { unsigned t :32;} bit32;\ char n, *tp = (char *) &bit32;\ bit32.t = l;\ n = tp[0]; tp[0] = tp[3]; tp[3] = n;\ n = tp[1]; tp[1] = tp[2]; tp[2] = n;\ l = bit32.t;\ } #define SWAP2BYTES(s) {\ struct { unsigned t :16; } bit16;\ char n, *tp = (char *) &bit16;\ bit16.t = s;\ n = tp[0]; tp[0] = tp[1]; tp[1] = n;\ s = bit16.t;\ } /** Private extern functions */ extern unsigned char _DndByteOrder (void); /***** Targets/Index stuff */ typedef struct { int num_targets; Atom *targets; } DndTargetsTableEntryRec, * DndTargetsTableEntry; typedef struct { int num_entries; DndTargetsTableEntry entries; } DndTargetsTableRec, * DndTargetsTable; extern int _DndTargetsToIndex(Display * display, Atom * targets, int num_targets); extern int _DndIndexToTargets(Display * display, int index, Atom ** targets); #endif /* _DndP_h */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/XDND.c0000644000175000017500000025303110562403651022032 0ustar domibeldomibel/* * XDND.c -- Tk XDND Drag'n'Drop Protocol Implementation * * This file implements the unix portion of the drag&drop mechanism * for the tk toolkit. The protocol in use under unix is the * XDND protocol. * * This software is copyrighted by: * George Petasis, National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * Laurent Riesterer, Rennes, France. * e-mail: laurent.riesterer@free.fr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ #include #include #include #include #include #include #include #include "vtkTcl.h" #include "vtkTk.h" #include #include #include #include #ifdef TKDND_ENABLE_MOTIF_DRAGS #include #endif /* TKDND_ENABLE_MOTIF_DRAGS */ /* * Define the default cursors... */ /* static char dnd_copy_cursor_bits[] = { 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0xe8, 0x0f, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static char dnd_copy_mask_bits[] = { 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00}; static char dnd_move_cursor_bits[] = { 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x04, 0x08, 0x02, 0x0c, 0x08, 0x02, 0x1c, 0x08, 0x02, 0x3c, 0x08, 0x02, 0x7c, 0x08, 0x02, 0xfc, 0x08, 0x02, 0xfc, 0x09, 0x02, 0xfc, 0x0b, 0x02, 0x7c, 0x08, 0xfe, 0x6d, 0x0f, 0x00, 0xc4, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00}; static char dnd_move_mask_bits[] = { 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1f, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x06, 0x1c, 0x07, 0x0e, 0x1c, 0x07, 0x1e, 0x1c, 0x07, 0x3e, 0x1c, 0x07, 0x7e, 0x1c, 0x07, 0xfe, 0x1c, 0x07, 0xfe, 0x1d, 0x07, 0xfe, 0x1f, 0x07, 0xfe, 0x1f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1e, 0xff, 0xef, 0x1f, 0x00, 0xe6, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01}; static char dnd_link_cursor_bits[] = { 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0xe8, 0x0f, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static char dnd_link_mask_bits[] = { 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00}; static char dnd_ask_cursor_bits[] = { 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x88, 0x03, 0x02, 0x00, 0x48, 0x04, 0x02, 0x00, 0x08, 0x04, 0x02, 0x00, 0x08, 0x02, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static char dnd_ask_mask_bits[] = { 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00}; static XDNDCursor dnd_cursors[] = { {29, 25, 10, 10, dnd_copy_cursor_bits, dnd_copy_mask_bits, "XdndNoDrop", 0, 0, 0, 0}, {29, 25, 10, 10, dnd_copy_cursor_bits, dnd_copy_mask_bits, "XdndActionCopy", 0, 0, 0, 0}, {21, 25, 10, 10, dnd_move_cursor_bits, dnd_move_mask_bits, "XdndActionMove", 0, 0, 0, 0}, {29, 25, 10, 10, dnd_link_cursor_bits, dnd_link_mask_bits, "XdndActionLink", 0, 0, 0, 0}, {29, 25, 10, 10, dnd_ask_cursor_bits, dnd_ask_mask_bits, "XdndActionAsk", 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; */ /* * XDND_Reset -- * Resets a dnd structure... */ void XDND_Reset(XDND *dndp) { /* * If we are in the middle of handling a tcl callback, don't reset the * structure, as we may get called from a ClientMessage Handler, due to an * "update" tcl statement... */ /* if (dndp->ExecutingCallback) return; */ dndp->interp = NULL; dndp->x = 0; dndp->y = 0; dndp->button = 0; dndp->state = 0; dndp->CallbackStatus = 0; dndp->InternalDrag = False; dndp->ReceivedStatusFlag = False; if (dndp->data != NULL) Tcl_Free(dndp->data); dndp->data = NULL; dndp->index = 0; dndp->DraggerWindow = None; if (dndp->DraggerTypeList != NULL) Tcl_Free((char *)dndp->DraggerTypeList); dndp->DraggerTypeList = NULL; dndp->DraggerAskActionList = NULL; dndp->CursorWindow = NULL; dndp->CursorCallback = NULL; dndp->WaitForStatusFlag = False; dndp->Toplevel = None; dndp->MouseWindow = None; dndp->MouseWindowIsAware = False; dndp->MsgWindow = None; dndp->DesiredType = None; #ifdef XDND_USE_TK_GET_SELECTION dndp->DesiredName = NULL; #endif /* XDND_USE_TK_GET_SELECTION */ dndp->SupportedAction = None; dndp->WillAcceptDropFlag = False; dndp->LastEventTime = CurrentTime; dndp->IsDraggingFlag = False; dndp->LastEnterDeliveredWindow = None; #ifdef TKDND_ENABLE_MOTIF_DROPS dndp->Motif_DND = False; #endif /* TKDND_ENABLE_MOTIF_DROPS */ #ifdef TKDND_ENABLE_MOTIF_DRAGS dndp->Motif_ToplevelAware = False; dndp->Motif_LastToplevel = None; #endif /* TKDND_ENABLE_MOTIF_DRAGS */ } /* XDND_Reset */ /* * XDND_Init -- * Allocates & initialises a dnd structure... */ XDND *XDND_Init(Display *display) { XDND *dndp; XModifierKeymap *ModMap; KeyCode *codePtr; KeySym keysym; #ifdef TKDND_ENABLE_MOTIF_DRAGS char SelectionName[64]; #endif /* TKDND_ENABLE_MOTIF_DRAGS */ int i, max; /*XDNDCursor *cursor; XColor black, white;*/ dndp = (XDND *) Tcl_Alloc(sizeof(XDND)); if (dndp == NULL) return NULL; /* Initialise dndp structure */ dndp->data = NULL; dndp->DraggerTypeList = NULL; dndp->DraggerAskDescriptions = NULL; XDND_Reset(dndp); dndp->display = display; dndp->RootWindow = DefaultRootWindow(display); dndp->XDNDVersion = XDND_VERSION; /*dndp->cursors = dnd_cursors;*/ /* * Initialise Cursors... */ #if 0 black.pixel = BlackPixel(display, DefaultScreen(display)); white.pixel = WhitePixel(display, DefaultScreen(display)); XQueryColor(display, DefaultColormap(display, DefaultScreen(display)), &black); XQueryColor(display, DefaultColormap(display, DefaultScreen(display)), &white); for (cursor = &dndp->cursors[0]; cursor->width; cursor++) { cursor->image_pixmap = XCreateBitmapFromData(display, dndp->RootWindow, (char *) cursor->image_data, cursor->width, cursor->height); cursor->mask_pixmap = XCreateBitmapFromData(display, dndp->RootWindow, (char *) cursor->mask_data, cursor->width, cursor->height); cursor->cursor = XCreatePixmapCursor (display, cursor->image_pixmap, cursor->mask_pixmap, &black, &white, cursor->x, cursor->y); XFreePixmap (display, cursor->image_pixmap); XFreePixmap (display, cursor->mask_pixmap); cursor->action = XInternAtom (dndp->display, cursor->_action, False); cursor->image_pixmap = cursor->mask_pixmap = 0; } #endif /* * Create required X atoms... */ dndp->DNDSelectionName = XInternAtom(display, "XdndSelection", False); dndp->DNDProxyXAtom = XInternAtom(display, "XdndProxy", False); dndp->DNDAwareXAtom = XInternAtom(display, "XdndAware", False); dndp->DNDTypeListXAtom = XInternAtom(display, "XdndTypeList", False); dndp->DNDEnterXAtom = XInternAtom(display, "XdndEnter", False); dndp->DNDHereXAtom = XInternAtom(display, "XdndPosition", False); dndp->DNDStatusXAtom = XInternAtom(display, "XdndStatus", False); dndp->DNDLeaveXAtom = XInternAtom(display, "XdndLeave", False); dndp->DNDDropXAtom = XInternAtom(display, "XdndDrop", False); dndp->DNDFinishedXAtom = XInternAtom(display, "XdndFinished", False); dndp->DNDActionCopyXAtom = XInternAtom(display, "XdndActionCopy", False); dndp->DNDActionMoveXAtom = XInternAtom(display, "XdndActionMove", False); dndp->DNDActionLinkXAtom = XInternAtom(display, "XdndActionLink", False); dndp->DNDActionAskXAtom = XInternAtom(display, "XdndActionAsk", False); dndp->DNDActionPrivateXAtom = XInternAtom(display, "XdndActionPrivate", False); dndp->DNDActionListXAtom = XInternAtom(display, "XdndActionList", False); dndp->DNDActionDescriptionXAtom = XInternAtom(display,"XdndActionDescription", False); dndp->DNDDirectSave0XAtom = XInternAtom(display, "XdndDirectSave0", False); dndp->DNDMimePlainTextXAtom = XInternAtom(display, "text/plain", False); dndp->DNDStringAtom = XInternAtom(display, "STRING", False); dndp->DNDNonProtocolAtom = XInternAtom(display, "TkDndBinarySelectionAtom", False); /* * Motif Needed XAtoms... */ #ifdef TKDND_ENABLE_MOTIF_DROPS dndp->Motif_DND = False; dndp->Motif_DND_SuccessAtom = XInternAtom(display, "XmTRANSFER_SUCCESS", False); dndp->Motif_DND_FailureAtom = XInternAtom(display, "XmTRANSFER_FAILURE", False); #endif /* TKDND_ENABLE_MOTIF_DROPS */ #ifdef TKDND_ENABLE_MOTIF_DRAGS sprintf(SelectionName, "TK_MOTIF_Selection_%d",(int) getpid()); dndp->Motif_DND_Selection = XInternAtom(display, SelectionName, False); dndp->Motif_DND_WM_STATE = XInternAtom(display, "WM_STATE", False); #endif /* TKDND_ENABLE_MOTIF_DRAGS */ dndp->WidgetExistsCallback = NULL; dndp->WidgetApplyEnterCallback = NULL; dndp->WidgetApplyPositionCallback = NULL; dndp->WidgetApplyLeaveCallback = NULL; dndp->WidgetInsertDropDataCallback = NULL; dndp->Ask = NULL; dndp->GetData = NULL; dndp->HandleEvents = NULL; dndp->GetDragAtoms = NULL; dndp->SetCursor = NULL; /* * Try to get the modifier the Alt key is associated with... * (Laurent Riesterer 24/06/2000, taken from tkUnixKey.c) */ dndp->Alt_ModifierMask = 0; dndp->Meta_ModifierMask = 0; ModMap = XGetModifierMapping(dndp->display); codePtr = ModMap->modifiermap; max = 8 * ModMap->max_keypermod; for (i = 0; i < max; i++, codePtr++) { if (*codePtr == 0) continue; keysym = XKeycodeToKeysym(dndp->display, *codePtr, 0); if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) { dndp->Alt_ModifierMask |= ShiftMask << (i/ModMap->max_keypermod); } if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) { dndp->Meta_ModifierMask |= ShiftMask << (i/ModMap->max_keypermod); } } XFreeModifiermap(ModMap); return dndp; } /* XDND_Init */ /* * EnableDND -- * Creates the XdndAware property on the specified window and all its parents */ void XDND_Enable(XDND *dnd, Window window) { Tk_Window tkwin; Window root_return, parent, *children_return = 0; unsigned int nchildren_return; int status; Atom version = XDND_VERSION; /* * Find the real toplevel that holds the wanted window. The property must * be set on each top-level X window that contains widgets that can accept * drops. (new in version 3) * The property should not be set on subwindows... */ status = XQueryTree(dnd->display, window, &root_return, &parent, &children_return, &nchildren_return); if (children_return) XFree(children_return); if (status && dnd->WidgetExistsCallback) { if (!(*dnd->WidgetExistsCallback) (dnd, parent)) { /* * Force Tk to create the window... */ tkwin = Tk_IdToWindow(dnd->display, window); if (tkwin != NULL) Tk_MakeWindowExist(tkwin); XChangeProperty(dnd->display, window, dnd->DNDAwareXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) &version, 1); XDND_DEBUG2("XDND_Enable: Enabling window %ld\n", window); #ifdef TKDND_ENABLE_MOTIF_DROPS /*DndWriteReceiverProperty(dnd->display, window, DND_DRAG_DYNAMIC);*/ #endif /* TKDND_ENABLE_MOTIF_DROPS */ } else { XDND_Enable(dnd, parent); } } } /* XDND_Enable */ /* * XDND_IsDndAware -- * Returns True if the given X window supports the XDND protocol. * proxy is the window to which the client messages should be sent. * vers is the version to use. */ XDND_BOOL XDND_IsDndAware(XDND *dnd, Window window, Window* proxy, Atom *vers) { XDND_BOOL result = False; Atom actualType, *data; int actualFormat; unsigned long itemCount, remainingBytes; unsigned char* rawData = NULL; *proxy = window; *vers = 0; if (window == None) return False; /* check for XdndProxy... */ XGetWindowProperty(dnd->display, window, dnd->DNDProxyXAtom, 0, LONG_MAX, False, XA_WINDOW, &actualType, &actualFormat, &itemCount, &remainingBytes, &rawData); if (actualType == XA_WINDOW && actualFormat == 32 && itemCount > 0) { *proxy = (Window) rawData; XFree(rawData); rawData = NULL; /* check XdndProxy on proxy window -- must point to itself */ XGetWindowProperty(dnd->display, *proxy, dnd->DNDProxyXAtom, 0, LONG_MAX, False, XA_WINDOW, &actualType, &actualFormat, &itemCount, &remainingBytes, &rawData); if (actualType != XA_WINDOW || actualFormat != 32 || itemCount == 0 || (Window) rawData != *proxy) { *proxy = window; } } XFree(rawData); rawData = NULL; /* check XdndAware... */ XGetWindowProperty(dnd->display, *proxy, dnd->DNDAwareXAtom, 0, LONG_MAX, False, XA_ATOM, &actualType, &actualFormat, &itemCount, &remainingBytes, &rawData); if (actualType == XA_ATOM && actualFormat == 32 && itemCount > 0) { data = (Atom*) rawData; if (data[0] >= XDND_MINVERSION) { result = True; if (XDND_MINVERSION < data[0]) *vers = XDND_MINVERSION; else *vers = data[0]; XDND_DEBUG3("XDND_IsDndAware: " "Window %ld is XDND aware. Version: %ld\n", window, *vers); } else { *proxy = None; } } XFree(rawData); return result; } /* XDND_IsDndAware */ /* * XDND_AtomListLength -- * This function returns the length of a given Atom list */ int XDND_AtomListLength(Atom *list) { int n; if (list == NULL) return 0; for (n = 0; list[n]; n++); return n; } /* XDND_AtomListLength */ /* * XDND_DescriptionListLength -- * This function returns the length of a given Description list... */ int XDND_DescriptionListLength(char *list) { int n = 0; if (list == NULL) return 0; while (1) { if (*list == '\0' && *(list+1) == '\0') return n+1; /* Just to make sure... */ if (n > 1000000) return 0; list++; n++; } } /* XDND_DescriptionListLength */ /* * XDND_GetTypeList -- * Returns a type list of all the currently defined types of the given * window. * Note that the caller must free the pointer returned... */ Atom *XDND_GetTypeList(XDND *dnd, Window window) { Atom actualType, *data, *TypeList=NULL; int actualFormat, i; unsigned long itemCount, remainingBytes; unsigned char *rawData = NULL; if (window == None) return NULL; /* * Check if the "XdndTypeList" property is present... */ XGetWindowProperty(dnd->display, window, dnd->DNDTypeListXAtom, 0, LONG_MAX, False, XA_ATOM, &actualType, &actualFormat, &itemCount, &remainingBytes, &rawData); if (actualType == XA_ATOM && actualFormat == 32 && itemCount > 0) { TypeList = (Atom *) Tcl_Alloc(sizeof(Atom)*(itemCount+1)); if (TypeList == NULL) return NULL; data = (Atom *) rawData; for (i=0; idisplay, toplevel, dnd->DNDAwareXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) &version, 1); XChangeProperty(dnd->display, toplevel, dnd->DNDAwareXAtom, XA_ATOM, 32, PropModeAppend, (unsigned char *) list, (typeCount > 3 ? 3 : typeCount)); #ifdef TKDND_ENABLE_MOTIF_DRAGS DndWriteSourceProperty(dnd->display, toplevel, dnd->Motif_DND_Selection, list, typeCount); #endif /* TKDND_ENABLE_MOTIF_DRAGS */ } if (typeCount > XDND_ENTERTYPECOUNT) { /* The list has more than XDND_ENTERTYPECOUNT types. The property * "XdndTypeList" must be created... */ if (toplevel != None) { XChangeProperty(dnd->display, toplevel, dnd->DNDTypeListXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char*) list, typeCount); } XChangeProperty(dnd->display, window, dnd->DNDTypeListXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char*) list, typeCount); XDND_DEBUG3("XDND_AnnounceTypeList: TypeList (%d) on window %ld:\n", typeCount, window); } else { XDND_DEBUG4("XDND_AnnounceTypeList: > %d types (%d) on window %ld:\n", XDND_ENTERTYPECOUNT, typeCount, window); } #ifdef DND_DEBUG for (i=0; idisplay, list[i]); XDND_DEBUG3("\t==> Atom[%d]: %s\n", i, AtomName); XFree(AtomName); } #endif /* DND_DEBUG */ } /* XDND_AnnounceTypeList */ /* * XDND_AppendType -- * This function will append a type in the current acceptable typelist of the * specified window... */ void XDND_AppendType(XDND *dnd, Window window, Atom type) { Atom types[2]; types[0] = type; types[1] = 0; XChangeProperty(dnd->display, window, dnd->DNDTypeListXAtom, XA_ATOM, 32, PropModeAppend, (unsigned char*) types, 1); } /* XDND_AppendType */ /* * XDND_AnnounceAskActions -- * Creates the XdndActionList and XdndActionDescription properties on * DraggerWindow. */ void XDND_AnnounceAskActions(XDND *dnd, Window window, Atom *Actions, char *Descriptions) { Window toplevel; int actionCount, desCount; #ifdef DND_DEBUG char *AtomName; int i; #endif /* DND_DEBUG */ /* * Announce actions to the toplevel window also... */ actionCount = XDND_AtomListLength(Actions); desCount = XDND_DescriptionListLength(Descriptions); toplevel = XDND_FindToplevel(dnd, window); if (toplevel != None) { XDND_DEBUG3("XDND_AnnounceAskActions: Announcing on toplevel %ld %d " "actions:\n", toplevel, actionCount); XChangeProperty(dnd->display, toplevel, dnd->DNDActionListXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) Actions, actionCount); XChangeProperty(dnd->display, toplevel, dnd->DNDActionDescriptionXAtom, XA_STRING, 8, PropModeReplace, (unsigned char *) Descriptions, desCount); } XChangeProperty(dnd->display, window, dnd->DNDActionListXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *) Actions, actionCount); XChangeProperty(dnd->display, window, dnd->DNDActionDescriptionXAtom, XA_STRING, 8, PropModeReplace, (unsigned char *) Descriptions, desCount); #ifdef DND_DEBUG for (i = 0; i < actionCount; i++) { AtomName = XGetAtomName(dnd->display, Actions[i]); XDND_DEBUG3("\t==> Atom[%d]: %s\n", i, AtomName); XFree(AtomName); } #endif /* DND_DEBUG */ } /* XDND_AnnounceAskActions */ /* * XDND_GetAskActions -- * Returns the action list of all the currently defined actions of the given * window. * Note that the caller must free the pointer returned... */ Atom *XDND_GetAskActions(XDND *dnd, Window window) { Atom actualType, *data, *ActionList=NULL; int actualFormat, i; unsigned long itemCount, remainingBytes; unsigned char *rawData = NULL; if (window == None) return NULL; /* * Check if the "XdndActionList" property is present... */ XGetWindowProperty(dnd->display, window, dnd->DNDActionListXAtom, 0, LONG_MAX, False, XA_ATOM, &actualType, &actualFormat, &itemCount, &remainingBytes, &rawData); if (actualType == XA_ATOM && actualFormat == 32 && itemCount > 0) { ActionList = (Atom *) Tcl_Alloc(sizeof(Atom)*(itemCount+1)); if (ActionList == NULL) return NULL; data = (Atom *) rawData; for (i=0; iSupportedAction != None) { ActionList = (Atom *) Tcl_Alloc(sizeof(Atom)*2); if (ActionList == NULL) return NULL; ActionList[0] = dnd->SupportedAction; ActionList[1] = None; } } return ActionList; } /* XDND_GetAskActions */ /* * XDND_GetAskActionDescriptions -- * Returns the action descriptions of all the currently defined actions of * the given window. * Note that the caller must free the pointer returned... */ char *XDND_GetAskActionDescriptions(XDND *dnd, Window window) { Atom actualType; char *data; int actualFormat; unsigned long itemCount, remainingBytes; unsigned char *rawData = NULL; if (window == None) return NULL; /* * Check if the "XdndDescriptionList" property is present... */ XGetWindowProperty(dnd->display, window, dnd->DNDActionDescriptionXAtom, 0, LONG_MAX, False, XA_STRING, &actualType, &actualFormat, &itemCount, &remainingBytes, &rawData); if (actualType == XA_STRING && actualFormat == 8 && itemCount > 0) { data = (char *) rawData; if (dnd->DraggerAskDescriptions != NULL) { memset(dnd->DraggerAskDescriptions, '\0', TKDND_MAX_DESCRIPTIONS_LENGTH); if (itemCount > TKDND_MAX_DESCRIPTIONS_LENGTH - 1) { itemCount = TKDND_MAX_DESCRIPTIONS_LENGTH -1; data[itemCount] = '\0'; data[itemCount+1] = '\0'; } memcpy(dnd->DraggerAskDescriptions, data, itemCount+1); } XFree(rawData); } else { /* * The "XdndDescriptionList" was non-existent or empty... */ if (rawData != NULL) XFree(rawData); } return dnd->DraggerAskDescriptions; } /* XDND_GetAskActionDescriptions */ /* * XDND_DraggerCanProvideText -- * Returns True if text/plain is in itsDraggerTypeList. */ XDND_BOOL XDND_DraggerCanProvideText(XDND *dnd) { int i; for (i = 1; i <= XDND_AtomListLength(dnd->DraggerTypeList); i++) { if (dnd->DraggerTypeList[i] == dnd->DNDMimePlainTextXAtom) { return True; } } return False; } /* XDND_DraggerCanProvideText */ /* * XDND_SendDNDEnter * Sends XdndEnter message :-) */ void XDND_SendDNDEnter(XDND *dnd, Window window, Window msgWindow, XDND_BOOL isAware, Atom vers) { XEvent xEvent; int typeCount, msgTypeCount, i; dnd->XDNDVersion = vers; dnd->MouseWindow = window; dnd->MouseWindowIsAware = isAware; dnd->MsgWindow = msgWindow; dnd->WillAcceptDropFlag = False; dnd->WaitForStatusFlag = False; dnd->UseMouseRectFlag = False; dnd->MouseRectR.x = dnd->MouseRectR.y = 0; dnd->MouseRectR.width = dnd->MouseRectR.height = 0; if (dnd->MouseWindowIsAware) { XDND_DEBUG2("XDND_SendDNDEnter: Sending XdndEnter to window %ld\n", dnd->MsgWindow); memset(&xEvent, 0, sizeof (xEvent)); typeCount = XDND_AtomListLength(dnd->DraggerTypeList); xEvent.xclient.type = ClientMessage; xEvent.xclient.display = dnd->display; xEvent.xclient.window = dnd->MouseWindow; xEvent.xclient.message_type = dnd->DNDEnterXAtom; xEvent.xclient.format = 32; xEvent.xclient.data.l[0] = dnd->DraggerWindow; /* source window */ xEvent.xclient.data.l[1] = 0; /* version in high byte, bit 0 => more data types */ xEvent.xclient.data.l[1] |= (dnd->XDNDVersion << 24); if (typeCount > XDND_ENTERTYPECOUNT) { xEvent.xclient.data.l[1] |= 1; } xEvent.xclient.data.l[2] = None; xEvent.xclient.data.l[3] = None; xEvent.xclient.data.l[4] = None; msgTypeCount = Min(typeCount, 3); for (i = 0; i < msgTypeCount; i++) { xEvent.xclient.data.l[2 + i] = dnd->DraggerTypeList[i]; } XSendEvent(dnd->display, dnd->MsgWindow, 0, 0, &xEvent); } } /* XDND_SendDNDEnter */ /* * XDND_SendDNDPosition -- * This is sent to let the target to inform target about mouse position... */ XDND_BOOL XDND_SendDNDPosition(XDND *dnd, Atom action) { XEvent xEvent; if (dnd->MsgWindow == None || dnd->MouseWindow == None) { return False; } xEvent.xclient.type = ClientMessage; xEvent.xclient.display = dnd->display; xEvent.xclient.window = dnd->MouseWindow; xEvent.xclient.message_type = dnd->DNDHereXAtom; xEvent.xclient.format = 32; xEvent.xclient.data.l[0] = dnd->DraggerWindow; /* source window (sender) */ xEvent.xclient.data.l[1] = 0; xEvent.xclient.data.l[2] = (dnd->x << 16) | dnd->y; /* mouse coordinates */ xEvent.xclient.data.l[3] = CurrentTime; xEvent.xclient.data.l[4] = action; XDND_DEBUG2("XDND_SendDNDPosition: Sending XdndPosition to window %ld\n", dnd->MsgWindow); XSendEvent(dnd->display, dnd->MsgWindow, 0, 0, &xEvent); return True; } /* XDND_SendDNDPosition */ /* * XDND_SendDNDStatus -- * This is sent to let the source know that we are ready for another * DNDHere message... */ XDND_BOOL XDND_SendDNDStatus(XDND *dnd, Atom action) { XEvent xEvent; int width = 1, height = 1; if (dnd->DraggerWindow == None) { return False; } memset (&xEvent, 0, sizeof(XEvent)); xEvent.xclient.type = ClientMessage; xEvent.xclient.display = dnd->display; xEvent.xclient.window = dnd->DraggerWindow; xEvent.xclient.message_type = dnd->DNDStatusXAtom; xEvent.xclient.format = 32; /* * Placing the widget the mouse is in was a bug, reported by * * xEvent.xclient.data.l[0] = dnd->MouseWindow; */ xEvent.xclient.data.l[0] = dnd->Toplevel; xEvent.xclient.data.l[1] = 0; /* * Set a rectangle of 1x1 pixel at mouse position... */ xEvent.xclient.data.l[2] = ((dnd->x) << 16) | ((dnd->y) & 0xFFFFUL); xEvent.xclient.data.l[3] = ((width) << 16) | ((height) & 0xFFFFUL); XDND_DEBUG2("XDND_SendDNDStatus: WillAcceptDropFlag=%d\n", dnd->WillAcceptDropFlag); if (dnd->WillAcceptDropFlag) { xEvent.xclient.data.l[1] |= 1; xEvent.xclient.data.l[4] = action; } else { xEvent.xclient.data.l[4] = None; } XSendEvent(dnd->display, dnd->DraggerWindow, 0, 0, &xEvent); return True; } /* XDND_SendDNDStatus */ /* * XDND_HandleDNDStatus -- */ int XDND_HandleDNDStatus(XDND *dnd, XClientMessageEvent clientMessage) { Window target; Atom TargetSupportedAction; int TargetWillAccept, TargetWantsPosition; long x, y, width, height; #ifdef DND_DEBUG char *AtomName; #endif /* DND_DEBUG */ /* * Extract XdndStatus information from ClientMessage... */ target = clientMessage.data.l[0]; /* if (target != dnd->MouseWindow) return False; */ TargetWillAccept = clientMessage.data.l[1] & 0x1L; TargetWantsPosition = clientMessage.data.l[1] & 0x2UL; x = clientMessage.data.l[2] >> 16; y = clientMessage.data.l[2] & 0xFFFFL; width = clientMessage.data.l[3] >> 16; height = clientMessage.data.l[3] & 0xFFFFL; TargetSupportedAction = (Atom) clientMessage.data.l[4]; if (TargetSupportedAction == None || !TargetWillAccept) { /* * We got None as a supported action. This means that the drop will * not be accepted... */ /* TargetWillAccept = False; TargetWantsPosition = False; TargetSupportedAction = None;*/ /* * TODO: I have decided to ignore the None value, because there are a * few malbehaved applications, like cooledit that they send None but * they mean drop :-) */ TargetSupportedAction = dnd->DNDActionCopyXAtom; } /* * Fill relevant slots in dnd structure... */ /* dnd->MouseWindow = target; */ dnd->WillAcceptDropFlag = TargetWillAccept; dnd->SupportedAction = TargetSupportedAction; dnd->WaitForStatusFlag = False; /* XdndStatus message received ! */ /* * Change the cursor according to the supported by the target action... */ if (TargetWillAccept) { if (TargetSupportedAction == dnd->DNDActionCopyXAtom) { if (dnd->SetCursor != NULL) { (*dnd->SetCursor) (dnd, XDND_COPY_CURSOR); } } else if (TargetSupportedAction == dnd->DNDActionMoveXAtom) { if (dnd->SetCursor != NULL) { (*dnd->SetCursor) (dnd, XDND_MOVE_CURSOR); } } else if (TargetSupportedAction == dnd->DNDActionLinkXAtom) { if (dnd->SetCursor != NULL) { (*dnd->SetCursor) (dnd, XDND_LINK_CURSOR); } } else if (TargetSupportedAction == dnd->DNDActionAskXAtom) { if (dnd->SetCursor != NULL) { (*dnd->SetCursor) (dnd, XDND_ASK_CURSOR); } } else if (TargetSupportedAction == dnd->DNDActionPrivateXAtom) { if (dnd->SetCursor != NULL) { (*dnd->SetCursor) (dnd, XDND_PRIVATE_CURSOR); } } else { XDND_DEBUG2("XDND_HandleDNDStatus: Error: Unkown action %ld\n", TargetSupportedAction); if (dnd->SetCursor != NULL) { (*dnd->SetCursor) (dnd, XDND_NODROP_CURSOR); } dnd->WillAcceptDropFlag = False; dnd->SupportedAction = None; return False; } } else { if (dnd->SetCursor != NULL) { (*dnd->SetCursor) (dnd, XDND_NODROP_CURSOR); } } #ifdef DND_DEBUG XDND_DEBUG2("XDND_HandleDNDStatus: ClientMessage from window %ld\n", target); if (TargetSupportedAction == None) { XDND_DEBUG4(" Accepts Drop=%d, Wants Position=%d, Action=%s,\n", TargetWillAccept, TargetWantsPosition, "None"); } else { AtomName = XGetAtomName(dnd->display, TargetSupportedAction); XDND_DEBUG4(" Accepts Drop=%d, Wants Position=%d, Action=%s,\n", TargetWillAccept, TargetWantsPosition, AtomName); XFree(AtomName); } XDND_DEBUG5(" x=%ld, y=%ld, width=%ld, height=%ld\n", x, y, width, height); #endif /* DND_DEBUG */ return True; } /* XDND_HandleDNDStatus */ /* * XDND_SendDNDLeave -- * This is sent to let the target know that the mouse has left the window... */ XDND_BOOL XDND_SendDNDLeave(XDND *dnd) { XEvent xEvent; if (dnd->MsgWindow == None) { return False; } xEvent.xclient.type = ClientMessage; xEvent.xclient.display = dnd->display; xEvent.xclient.window = dnd->MouseWindow; xEvent.xclient.message_type = dnd->DNDLeaveXAtom; xEvent.xclient.format = 32; xEvent.xclient.data.l[0] = dnd->DraggerWindow; xEvent.xclient.data.l[1] = 0; xEvent.xclient.data.l[2] = 0; /* empty rectangle */ xEvent.xclient.data.l[3] = 0; XDND_DEBUG3("XDND_SendDNDLeave: Sending XdndLeave to window %ld " "for window %ld\n", dnd->MsgWindow, dnd->MouseWindow); XSendEvent(dnd->display, dnd->MsgWindow, 0, 0, &xEvent); return True; } /* XDND_SendDNDLeave */ /* * XDND_SendDNDDrop -- * Notify the drop target that a drop is requested by the drag source... */ XDND_BOOL XDND_SendDNDDrop(XDND *dnd) { XEvent xEvent; if (dnd->MsgWindow == None) { return False; } xEvent.xclient.type = ClientMessage; xEvent.xclient.display = dnd->display; xEvent.xclient.window = dnd->MouseWindow; xEvent.xclient.message_type = dnd->DNDDropXAtom; xEvent.xclient.format = 32; xEvent.xclient.data.l[0] = dnd->DraggerWindow; xEvent.xclient.data.l[1] = 0; xEvent.xclient.data.l[2] = dnd->LastEventTime; xEvent.xclient.data.l[3] = 0; XDND_DEBUG2("XDND_SendDNDDrop: Sending XdndDrop to window %ld\n", dnd->MsgWindow); XSendEvent(dnd->display, dnd->MsgWindow, 0, 0, &xEvent); return True; } /* XDND_SendDNDDrop */ /* * XDND_SendDNDSelection -- * Notify the drop target that a drop is requested by the drag source... */ XDND_BOOL XDND_SendDNDSelection(XDND *dnd, XSelectionRequestEvent *request) { XEvent xEvent; if (request->requestor == None) { return False; } XDND_DEBUG3("XDND_SendDNDSelection: Sending \"%s\" (%d)\n", dnd->data, dnd->index); XChangeProperty(dnd->display, request->requestor, request->property, request->target, 8, PropModeReplace, (const unsigned char*)dnd->data, dnd->index); xEvent.xselection.type = SelectionNotify; xEvent.xselection.property = request->property; xEvent.xselection.display = request->display; xEvent.xselection.requestor = request->requestor; xEvent.xselection.selection = request->selection; xEvent.xselection.target = request->target; xEvent.xselection.time = request->time; XDND_DEBUG2("XDND_SendDNDSelection: Sending Selection to window %ld\n", request->requestor); XSendEvent(dnd->display, request->requestor, 0, 0, &xEvent); return True; } /* XDND_SendDNDSelection */ /* * XDND_FindTarget -- * Searches for XdndAware window under the cursor. * We have to search the tree all the way from the root window to the leaf * because we have to pass through whatever layers the window manager has * inserted. Also, while traversing the tree, if we found a window that is * XDND aware (and according to the protocol this property must exist only on * toplevel windows), the toplevel window is returned... * If any of the variables toplevel, msgWindow, aware and version is NULL, * then there will be no check for the XdndAware property... */ XDND_BOOL XDND_FindTarget(XDND *dnd, int x, int y, Window *toplevel, Window *msgWindow, Window *target, XDND_BOOL *aware, Atom *version) { int xd, yd; Window child, new_child; #ifdef TKDND_ENABLE_MOTIF_DRAGS Atom type = None; int format; unsigned long nitems, after; unsigned char *data; #endif /* TKDND_ENABLE_MOTIF_DRAGS */ if (toplevel != NULL && msgWindow != NULL && aware != NULL && version != NULL) { *toplevel = *msgWindow = *target = None; *aware = False; *version = None; } else { /* Just to make sure... */ toplevel = msgWindow = NULL; aware = NULL; version = NULL; } if (dnd->RootWindow == None || dnd->DraggerWindow == None) return False; if (dnd->Toplevel != None && !dnd->IsDraggingFlag) { child = dnd->Toplevel; } else { child = dnd->RootWindow; } for (;;) { new_child = None; if (!XTranslateCoordinates(dnd->display, dnd->RootWindow, child, x, y, &xd, &yd, &new_child)) { break; } if (new_child == None) break; child = new_child; /* * Check for XdndAware property... */ if (aware != NULL && !(*aware)) { if (XDND_IsDndAware(dnd, child, msgWindow, version)) { *toplevel = child; *aware = True; } #ifdef TKDND_ENABLE_MOTIF_DRAGS else { /* * If Motif drops are allowed, check for the "WM_STATE" * property. This should be defined only on toplevels, * according to Motif... */ XGetWindowProperty(dnd->display, child, dnd->Motif_DND_WM_STATE, 0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &data); if (type != None) *toplevel = child; if (data != NULL) XFree(data); } #endif /* TKDND_ENABLE_MOTIF_DRAGS */ } } *target = child; return True; } /* XDND_FindTarget */ /* * XDND_FindToplevel -- * Find the real toplevel that holds the given window... * Warning: This works only for tk windows. Do not attempt to use it in order * to find toplevels belonging to other applications. The results will be * wrong! */ Window XDND_FindToplevel(XDND *dnd, Window window) { Window root_return, parent, *children_return = 0; unsigned int nchildren_return; int status; #ifdef DND_DEBUG Tk_Window tkwin; char *name; #endif /* DND_DEBUG */ if (window == None) return None; status = XQueryTree(dnd->display, window, &root_return, &parent, &children_return, &nchildren_return); if (children_return) XFree(children_return); if (status) { if (dnd->WidgetExistsCallback) { if (!(*dnd->WidgetExistsCallback) (dnd, parent)) { #ifdef DND_DEBUG tkwin = Tk_IdToWindow(dnd->display, window); name = Tk_PathName(tkwin); if (name == NULL) name = "(tk internal/hidden window)"; XDND_DEBUG3("++++ XDND_FindToplevel: widget %s: %ld\n", name, window); #endif /* DND_DEBUG */ return window; } else { return XDND_FindToplevel(dnd, parent); } } } return None; } /* XDND_FindToplevel */ /* * D R A G O P E R A T I O N S */ /* * XDND_BeginDrag -- * This function begins a drag action... */ XDND_BOOL XDND_BeginDrag(XDND *dnd, Window source, Atom *actions, Atom *types, char *Descriptions, Tk_Window cursor_window, char *cursor_callback) { XEvent xevent, fake_xevent; XRectangle rectangle; KeySym sym; Window toplevel, msgWindow, mouseWindow; Atom actualAction; Time event_time; int accept, win_x_temp, win_y_temp, ret; int status = True, want_position; unsigned int mask_return; float x_mouse, y_mouse; #ifdef TKDND_ENABLE_MOTIF_DRAGS XClientMessageEvent cm; int Motif_do_messaging = False, check_motif = True; unsigned char receiv_protocol_style = DND_DRAG_NONE; #endif /* TKDND_ENABLE_MOTIF_DRAGS */ /* * First make sure that we want a drag: wait until the cursor moves more * than five pixels... */ do { XNextEvent (dnd->display, &xevent); if (xevent.type == ButtonRelease) { /*XSendEvent (dnd->display, xevent.xany.window, 0, ButtonReleaseMask, &xevent);*/ if (dnd->HandleEvents != NULL) (*dnd->HandleEvents) (dnd, &xevent); return False; } else { if (dnd->HandleEvents != NULL) (*dnd->HandleEvents) (dnd, &xevent); } } while (xevent.type != MotionNotify); x_mouse = (float) xevent.xmotion.x_root; y_mouse = (float) xevent.xmotion.y_root; for (;;) { XNextEvent (dnd->display, &xevent); if (xevent.type == MotionNotify) { if (XDND_Sqrt((x_mouse - xevent.xmotion.x_root) * (x_mouse - xevent.xmotion.x_root) + (y_mouse - xevent.xmotion.y_root) * (y_mouse - xevent.xmotion.y_root)) > 4.0) break; } if (xevent.type == ButtonRelease) { /* XSendEvent(dnd->display, xevent.xany.window, 0, ButtonReleaseMask, &xevent);*/ Tk_HandleEvent(&xevent); return False; } } XDND_DEBUG("\n\n\n\nXDND_BeginDrag: moved 5 pixels - going to drag\n"); XDND_Reset(dnd); dnd->x = xevent.xmotion.x_root; dnd->y = xevent.xmotion.y_root; /* Laurent Riesterer 24/06/2000: */ dnd->button = (xevent.xmotion.state & Button1Mask ? 1 : xevent.xmotion.state & Button2Mask ? 2 : xevent.xmotion.state & Button3Mask ? 3 : xevent.xmotion.state & Button4Mask ? 4 : 5); dnd->state = 0; XDND_DEBUG2("XDND_BeginDrag: dragging with button: %d\n", dnd->button); dnd->IsDraggingFlag = True; dnd->InternalDrag = False; dnd->DraggerWindow = source; dnd->DraggerTypeList = types; dnd->DraggerAskActionList = actions; dnd->DraggerAskDescriptions = Descriptions; dnd->CursorWindow = cursor_window; dnd->CursorCallback = cursor_callback; /* TODO: cache string! */ dnd->Toplevel = XDND_FindToplevel(dnd, source); dnd->MouseWindow = None; dnd->DesiredType = types[0]; dnd->SupportedAction = actions[0]; dnd->MouseWindowIsAware = False; dnd->MsgWindow = None; if (dnd->data != NULL) Tcl_Free(dnd->data); dnd->data = NULL; dnd->index = 0; /* Reset Cursor Cache... */ if (dnd->SetCursor != NULL) (*dnd->SetCursor) (dnd, -2); /* * This function will create the Window property "XdndTypeList" if we have * more than XDND_ENTERTYPECOUNT types... */ XDND_AnnounceTypeList(dnd, source, types); XDND_AnnounceAskActions(dnd, source, actions, Descriptions); /* * Get the ownership of selection, grab the cursor and set the * noDrop cursor... */ XSetSelectionOwner(dnd->display, dnd->DNDSelectionName, dnd->DraggerWindow, CurrentTime); #ifdef TKDND_ENABLE_MOTIF_DRAGS XSetSelectionOwner(dnd->display, dnd->Motif_DND_Selection, dnd->DraggerWindow, CurrentTime); #endif /* TKDND_ENABLE_MOTIF_DRAGS */ if (XGrabPointer(dnd->display, dnd->RootWindow, False, ButtonMotionMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, dnd->cursors[0].cursor, CurrentTime) != GrabSuccess) { XDND_DEBUG("XDND_BeginDrag: Unable to grab pointer\n"); } /* * Enter our private Drag Event Loop. We have to by-pass tk's event loop, * as intergrating this stuff with tk event loop would require a * substantially number of changes and the tkDND would never be a trully * loadable extension... */ while (xevent.xany.type != ButtonRelease) { XAllowEvents(dnd->display, SyncPointer, CurrentTime); XNextEvent(dnd->display, &xevent); switch (xevent.type) { case Expose: {/* Handle Expose Events... */ if (dnd->HandleEvents != NULL) { (*dnd->HandleEvents) (dnd, &xevent); } break; } /* Expose */ /* * This event is not actually reported, so we find out by * ourselves from motion events */ case EnterNotify: break; /* * This event is not actually reported, so we find out by * ourselves from motion events */ case LeaveNotify: break; /* done, but must send a leave event */ case ButtonRelease: { /* * D R O P S E C T I O N: We have a button release. It is * either a drop, or time to exit or private event loop and * give control to Tk... */ dnd->state = xevent.xbutton.state; /* Laurent Riesterer 24/06/2000 */ if (dnd->WillAcceptDropFlag) { if (dnd->InternalDrag) { if (dnd->data != NULL) Tcl_Free(dnd->data); dnd->data = NULL; dnd->index = 0; /* * Do we have to display an Ask dialog? */ if (dnd->SupportedAction == dnd->DNDActionAskXAtom) { if (dnd->Ask != NULL) { status = (*dnd->Ask) (dnd, dnd->DraggerWindow, dnd->MouseWindow, &actualAction); if (!status || actualAction == None) { /* * Either an error has occured or the user has canceled the * drop. So, call the callback... */ XDND_DEBUG2("XDND_BeginDrag: Internal Window, executing Leave" "directly for window %ld\n", dnd->MouseWindow); if (dnd->WidgetApplyLeaveCallback != NULL) { status = (*dnd->WidgetApplyLeaveCallback) (dnd, dnd->MouseWindow); } goto exit; } dnd->SupportedAction = actualAction; } else { /* TODO: What to do here? How to decide on the correct action? */ } } /* * Retieve the data from widget... */ if (dnd->GetData != NULL) { status = (*dnd->GetData) (dnd, dnd->DraggerWindow, (unsigned char **) &dnd->data, &dnd->index, dnd->DesiredType); } /* * Call the insert widget data callback... */ if (dnd->WidgetInsertDropDataCallback != NULL) { (*dnd->WidgetInsertDropDataCallback) (dnd, (unsigned char *) dnd->data, dnd->index, 0, dnd->MouseWindow, dnd->DraggerWindow, dnd->DesiredType); } if (dnd->data != NULL) Tcl_Free(dnd->data); dnd->data = NULL; } else { /* * Keep a copy of the button release event. We need it in order to * give it back to tk when we are done! */ memcpy(&fake_xevent, &xevent, sizeof(xevent)); /* * Send an XdndDrop message to the target! */ dnd->LastEventTime = xevent.xbutton.time; status = XSetSelectionOwner(dnd->display, dnd->DNDSelectionName, dnd->DraggerWindow, CurrentTime); XDND_DEBUG3("XDND_BeginDrag: XSetSelectionOwner %s (status=%d).\n", (status ? "succeded" : "FAILED"), status); XDND_SendDNDDrop(dnd); /* * Now we must start another Event loop, to wait for XdndSelection * requests from the drop target, as it will need to access the * data... */ for (;;) { XAllowEvents(dnd->display, SyncPointer, CurrentTime); XNextEvent(dnd->display, &xevent); switch (xevent.type) { case Expose: {/* Handle Expose Events... */ if (dnd->HandleEvents != NULL) (*dnd->HandleEvents) (dnd, &xevent); break; } /* Expose */ case MotionNotify: { /* If more than a few seconds have passed, the other app has * probably crashed :-) */ if (xevent.xmotion.time > dnd->LastEventTime + 10000) { /* allow a 10 second timeout as default */ XDND_DEBUG("XDND_BeginDrag: Timeout - exiting event loop"); memcpy(&xevent, &fake_xevent, sizeof(xevent)); goto exit; } break; } case ClientMessage: { XDND_DEBUG("XDND_BeginDrag: Loop 2-ClientMessage recieved\n"); if (xevent.xclient.message_type == dnd->DNDFinishedXAtom) { XDND_DEBUG("XDND_BeginDrag: XdndFinished received...\n"); memcpy(&xevent, &fake_xevent, sizeof(xevent)); goto exit; } XDND_HandleClientMessage(dnd, &xevent); break; } /* ClientMessage */ case SelectionRequest: { if (xevent.xselectionrequest.selection != dnd->DNDSelectionName) break; XDND_DEBUG("XDND_BeginDrag: SelectionRequest: getting widget " "data...\n"); /* * Retieve the data from widget... */ if (dnd->data != NULL) Tcl_Free(dnd->data); dnd->data = NULL; dnd->index = 0; dnd->DesiredType = xevent.xselectionrequest.target; if (dnd->GetData != NULL) { status = (*dnd->GetData) (dnd, dnd->DraggerWindow, (unsigned char **) &dnd->data, &dnd->index, dnd->DesiredType); } XDND_DEBUG("XDND_BeginDrag: Sending Selection...\n"); XDND_SendDNDSelection(dnd, &xevent.xselectionrequest); if (dnd->data != NULL) { Tcl_Free(dnd->data); dnd->data = NULL; dnd->index = 0; } memcpy(&xevent, &fake_xevent, sizeof(xevent)); goto exit; } /* SelectionRequest */ } /* switch (xevent.type) */ } /* for (;;) */ } } else { /* No drop, so send XdndLeave... */ if (dnd->MouseWindowIsAware) { if (!dnd->InternalDrag) { XDND_SendDNDLeave(dnd); } else if (dnd->WidgetApplyLeaveCallback != NULL) { (*dnd->WidgetApplyLeaveCallback) (dnd, dnd->MouseWindow); } } XDND_DEBUG("XDND_BeginDrag: ButtonRelease: exiting tkDND " "private event loop without dropping...\n"); } break; } /* ButtonRelease */ /* * A key has been pressed. We have to check whether it is a * modifier or Escape. */ case KeyPress: { sym = XKeycodeToKeysym(dnd->display, xevent.xkey.keycode, 0); XDND_DEBUG4("XDND_BeginDrag: KeyPress: state=0x%08x keycode=%d" " keysym=%ld\n", xevent.xkey.state, xevent.xkey.keycode, sym); dnd->state = xevent.xkey.state; /* * See if the button pressed is a modifier... * Laurent Riesterer 09/07/2000: * optimization in setting the mask */ if ( sym == XK_Shift_L || sym == XK_Shift_R ) { dnd->state |= ShiftMask; } else if (sym == XK_Control_L || sym == XK_Control_R) { dnd->state |= ControlMask; } else if (sym == XK_Meta_L || sym == XK_Meta_R ) { dnd->state |= dnd->Meta_ModifierMask; } else if (sym == XK_Alt_L || sym == XK_Alt_R ) { dnd->state |= dnd->Alt_ModifierMask; } xevent.type = MotionNotify; xevent.xmotion.type = MotionNotify; xevent.xmotion.state = dnd->state; XSendEvent(dnd->display, xevent.xkey.window, False, 0, &xevent); break; } /* KeyPress */ /* * A key has been released. We have to check whether it is a * modifier or Escape... */ case KeyRelease: { sym = XKeycodeToKeysym(dnd->display, xevent.xkey.keycode, 0); XDND_DEBUG4("XDND_BeginDrag: KeyRelease: state=0x%08x " "keycode=%d keysym=%ld\n", xevent.xkey.state, xevent.xkey.keycode, sym); dnd->state = xevent.xkey.state; /* * See if the button pressed is a modifier... * Laurent Riesterer 09/07/2000: * correction in reseting the mask */ if ( sym == XK_Shift_L || sym == XK_Shift_R) { dnd->state &= ~ShiftMask; } else if (sym == XK_Control_L || sym == XK_Control_R) { dnd->state &= ~ControlMask; } else if (sym == XK_Meta_L || sym == XK_Meta_R) { dnd->state &= ~dnd->Meta_ModifierMask; } else if (sym == XK_Alt_L || sym == XK_Alt_R) { dnd->state &= ~dnd->Alt_ModifierMask; } if (sym == XK_Escape) { /* * Time to forget the whole insident... * Simulate a button release, but with drop denial... */ dnd->WillAcceptDropFlag = False; fake_xevent.type = ButtonRelease; fake_xevent.xbutton.type = ButtonRelease; fake_xevent.xbutton.x = xevent.xkey.x; fake_xevent.xbutton.y = xevent.xkey.y; fake_xevent.xbutton.x_root = xevent.xkey.x_root; fake_xevent.xbutton.y_root = xevent.xkey.y_root; fake_xevent.xbutton.button = dnd->button; fake_xevent.xbutton.state = xevent.xkey.state; XSendEvent(dnd->display, xevent.xkey.window, False, 0, &fake_xevent); } else { /* * Simulate a MotionNotify event, so as to call the * callbacks again... */ fake_xevent.type = MotionNotify; fake_xevent.xmotion.type = MotionNotify; fake_xevent.xmotion.state = dnd->state; XSendEvent(dnd->display, xevent.xkey.window, False, 0, &fake_xevent); } break; } /* KeyRelease */ /* * The cursor has moved... */ case MotionNotify: { event_time = xevent.xmotion.time; dnd->state = xevent.xmotion.state; /* Laurent Riesterer 24/06/2000 */ memcpy (&fake_xevent, &xevent, sizeof(xevent)); XDND_DEBUG2("XDND_BeginDrag: MotionNotify recieved: (state=0x%08x)\n", xevent.xmotion.state); if (dnd->DraggerWindow == None) goto exit; /* * Get mouse coordinates relative to the root window. */ if (!XQueryPointer(dnd->display, dnd->DraggerWindow, &(dnd->RootWindow), &mouseWindow, &(dnd->x), &(dnd->y), &win_x_temp, &win_y_temp, &mask_return)) break; /* * Find the topmost window the mouse is in. The * XDND_FindTarget function will search the whole window tree * from the root window until the leaf window the mouse is * in. If in the way a window that has the XdndAware property * is found, the proper slots are filled... */ XDND_FindTarget(dnd, dnd->x, dnd->y, &toplevel, &msgWindow, &mouseWindow, &(dnd->MouseWindowIsAware), &(dnd->XDNDVersion)); if (mouseWindow == None) { XDND_DEBUG("XDND_BeginDrag: Mouse cursor in the root window?\n"); break; } /* * Have we entered a new toplevel window? A toplevel window * has the XdndAware atom in its properties. According to the * XDND protocol, this is a toplevel window, as only toplevel * windows are allowed to carry this property... */ if (dnd->Toplevel != toplevel) { XDND_DEBUG4("XDND_BeginDrag: Entering Toplevel: %ld, Old Toplevel" ": %ld XdndAware=%d...\n", toplevel, dnd->Toplevel, dnd->MouseWindowIsAware); #ifdef TKDND_ENABLE_MOTIF_DRAGS /* * Send a DND_TOP_LEVEL_LEAVE to the previous Motif * toplevel, if any... */ if (dnd->Motif_LastToplevel != None) { if (dnd->Motif_DND && Motif_do_messaging) { dnd->Motif_DND_Data.reason = DND_TOP_LEVEL_LEAVE; dnd->Motif_DND_Data.time = event_time; dnd->Motif_DND_Data.src_window = dnd->Motif_LastToplevel; DndFillClientMessage (dnd->display, dnd->Motif_LastToplevel, &cm, &(dnd->Motif_DND_Data), 0); printf("MotifDrag: Sending DND_TOP_LEVEL_LEAVE to window %ld\n", dnd->Motif_LastToplevel); XSendEvent(dnd->display, dnd->Motif_LastToplevel, False, 0, (XEvent *) &cm); Motif_do_messaging = False; dnd->Motif_LastToplevel = None; } } /* * Is the new toplevel our window? * If it is, forget the whole Motif theme... */ check_motif = True; if (dnd->WidgetExistsCallback != NULL) { if ((*dnd->WidgetExistsCallback) (dnd, toplevel)) { check_motif = False; } } /* * Is it a foreign window and Motif DND aware? */ if (toplevel != None && check_motif) { printf("MotifDrag: Checking if toplevel %ld is Motif aware...\n", toplevel); DndReadReceiverProperty(dnd->display, toplevel, &receiv_protocol_style); } else { receiv_protocol_style = DND_DRAG_NONE; } if (receiv_protocol_style == DND_DRAG_NONE) { dnd->Motif_DND = False; dnd->Motif_ToplevelAware = False; Motif_do_messaging = False; } else if (receiv_protocol_style == DND_DRAG_DROP_ONLY) { dnd->Motif_DND = True; dnd->Motif_ToplevelAware = True; Motif_do_messaging = False; /*ChangeCursorValid(event.xcrossing.display, event.xcrossing.time); */ } else if (receiv_protocol_style == DND_DRAG_DYNAMIC) { /* * The cursor must be changed if we enter a drop site. */ /* ChangeCursorInvalid(event.xcrossing.display, event.xcrossing.time); */ printf("MotifDrag: Sending DND_TOP_LEVEL_ENTER to window %ld\n", toplevel); dnd->Motif_DND_Data.reason = DND_TOP_LEVEL_ENTER; dnd->Motif_DND_Data.time = event_time; dnd->Motif_DND_Data.src_window = toplevel; dnd->Motif_DND_Data.property = dnd->Motif_DND_Selection; DndFillClientMessage (dnd->display, toplevel, &cm, &(dnd->Motif_DND_Data), 0); XSendEvent(dnd->display, toplevel, False, 0, (XEvent *)&cm); dnd->Motif_DND = True; dnd->Motif_ToplevelAware = True; dnd->Motif_LastToplevel = toplevel; Motif_do_messaging = True ; } #endif /* TKDND_ENABLE_MOTIF_DRAGS */ dnd->Toplevel = toplevel; } /* * Have we entered a new widget? */ if (dnd->MouseWindow != mouseWindow) { XDND_DEBUG3("XDND_BeginDrag: Entering Window: %ld, Old Window: %ld\n", mouseWindow, dnd->MouseWindow); if (dnd->MouseWindow == None) { XDND_DEBUG("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); } /* * Send a XdndLeave message, to the old window, if any... */ if (dnd->MouseWindow != None) { /* * Was the last window one of our own windows? If this * is the case, call the callbacks directly. There is * no need to go through the XServer... */ if (dnd->InternalDrag) { XDND_DEBUG2("XDND_BeginDrag: Internal Window, executing Leave " "directly for window %ld\n", dnd->MouseWindow); if (dnd->WidgetApplyLeaveCallback != NULL) { status = (*dnd->WidgetApplyLeaveCallback) (dnd, dnd->MouseWindow); if (status == TCL_ERROR) { XDND_DEBUG2("XDND_BeginDrag: Last error:\n %s\n", Tcl_GetString(Tcl_GetObjResult(dnd->interp))); goto exit; } } } else { /* * The last window belongs to a foreign * application. Send the proper messages through * the XServer... */ XDND_DEBUG2("XDND_BeginDrag: External Window, sending " "XdndLeave to window %ld\n", dnd->MouseWindow); XDND_SendDNDLeave(dnd); } /* if (dnd->InternalDrag) */ dnd->WillAcceptDropFlag = False; dnd->SupportedAction = actions[0]; } /* if (dnd->MouseWindow != None) */ dnd->MouseWindow = mouseWindow; dnd->MsgWindow = msgWindow; /* * We are now officially in the new window. Is the new * window XDND aware? */ if (dnd->MouseWindowIsAware) { dnd->InternalDrag = False; /* We don't know that yet... */ /* We are at a new window, so reset preffered action :-) */ dnd->SupportedAction = actions[0]; /* * We need to send an XdndEnter message. * Is it an internal window? */ if (dnd->WidgetExistsCallback != NULL) { if ((*dnd->WidgetExistsCallback) (dnd, mouseWindow)) { /* * This is an internal window: Do not send a * XdndEnter message through the XServer, but * call the callback directly... */ XDND_DEBUG2("XDND_BeginDrag: Internal Window, sending Enter " "directly for window %ld\n", mouseWindow); dnd->InternalDrag = True; if (dnd->WidgetApplyEnterCallback != NULL) { accept = (*dnd->WidgetApplyEnterCallback) (dnd, mouseWindow, source, actions[0], dnd->x, dnd->y, event_time, dnd->DraggerTypeList); if (dnd->CallbackStatus != TCL_OK) goto exit; #ifdef XDND_DEBUG if (!accept) XDND_DEBUG("XDND_BeginDrag: Enter denied!\n"); #endif /* XDND_DEBUG */ if (dnd->SupportedAction == None) break; } /* if (dnd->WidgetApplyEnterCallback != NULL) */ } /* if ((*dnd->WidgetExistsCallback) (dnd, mouseWindow)) */ } /* if (dnd->WidgetExistsCallback != NULL) */ /* * If the new window does not belong to this * application, send the XdndEnter message... */ if (!dnd->InternalDrag) { XDND_DEBUG2("XDND_BeginDrag: Foreign Window, sending XdndEnter " "ClientMessage to window %ld\n", dnd->MsgWindow); XDND_SendDNDEnter(dnd, mouseWindow, dnd->MsgWindow, True, dnd->XDNDVersion); } } else { /* * The new window is not XDND aware... */ XDND_DEBUG2("XDND_BeginDrag: Window %ld is not XDND aware...\n", dnd->Toplevel); if (dnd->SetCursor != NULL) { ret = (*dnd->SetCursor) (dnd, XDND_NODROP_CURSOR); if (!ret) goto exit; } dnd->MouseWindowIsAware = False; dnd->MsgWindow = None; } /* if (dnd->MouseWindowIsAware) */ } /* if (dnd->MouseWindow != mouseWindow) */ /* * Whether we are in a new window or not, report the mouse * position to the window, if it is XDND aware... */ if (dnd->MouseWindowIsAware && dnd->SupportedAction != None) { if (dnd->InternalDrag) { /* * Simulate the XdndPosition/XdndStatus dialog without * going through the X-Server, as it is an internal * drop... */ dnd->WaitForStatusFlag = False; if (dnd->WidgetApplyPositionCallback != NULL) { status = (*dnd->WidgetApplyPositionCallback) (dnd, dnd->MouseWindow, dnd->DraggerWindow, actions[0], actions, dnd->x, dnd->y, event_time, dnd->DraggerTypeList, &want_position, &(dnd->SupportedAction), &(dnd->DesiredType), &rectangle); if (dnd->CallbackStatus == TCL_ERROR) goto exit; if (status) { /* * The target will accept the drop... */ dnd->WillAcceptDropFlag = True; /* * Change the cursor according to the * supported by the target action... */ if (dnd->SetCursor != NULL) { if (dnd->SupportedAction == dnd->DNDActionCopyXAtom) { ret = (*dnd->SetCursor) (dnd, XDND_COPY_CURSOR); } else if (dnd->SupportedAction == dnd->DNDActionMoveXAtom) { ret = (*dnd->SetCursor) (dnd, XDND_MOVE_CURSOR); } else if (dnd->SupportedAction == dnd->DNDActionLinkXAtom) { ret = (*dnd->SetCursor) (dnd, XDND_LINK_CURSOR); } else if (dnd->SupportedAction == dnd->DNDActionAskXAtom) { ret = (*dnd->SetCursor) (dnd, XDND_ASK_CURSOR); } else if (dnd->SupportedAction == dnd->DNDActionPrivateXAtom) { ret = (*dnd->SetCursor) (dnd, XDND_PRIVATE_CURSOR); } else { ret = (*dnd->SetCursor) (dnd, XDND_NODROP_CURSOR); } if (!ret) goto exit; } /* if (dnd->SetCursor != NULL) */ } else { /* * The widget refused drop... */ if (dnd->SetCursor != NULL) { ret = (*dnd->SetCursor) (dnd, XDND_NODROP_CURSOR); if (!ret) goto exit; } } /* if (status) */ } /* if (dnd->WidgetApplyPositionCallback != NULL) */ } else { /* * This is a foreign window. Send XdndPosition * message... */ if (!dnd->WaitForStatusFlag) { /* * If we are not waiting for XdndStatus message * (in a slow network...) send an XdndPosition * message: */ XDND_SendDNDPosition(dnd, dnd->SupportedAction); dnd->WaitForStatusFlag = True; } } /* if (dnd->InternalDrag) */ #ifdef TKDND_ENABLE_MOTIF_DRAGS } else { if (check_motif && dnd->Motif_DND && Motif_do_messaging) { printf("MotifDrag: Sending DND_DRAG_MOTION to window %ld\n", dnd->Motif_LastToplevel); dnd->Motif_DND_Data.reason = DND_DRAG_MOTION; dnd->Motif_DND_Data.time = event_time; /* TODO: Proper support for motif actions... */ dnd->Motif_DND_Data.operation = DND_COPY; /* TODO */ dnd->Motif_DND_Data.operations = DND_MOVE|DND_COPY; /* TODO */ dnd->Motif_DND_Data.x = dnd->x; dnd->Motif_DND_Data.y = dnd->y; DndFillClientMessage (dnd->display, dnd->Motif_LastToplevel, &cm, &(dnd->Motif_DND_Data), 0); XSendEvent(dnd->display, dnd->Motif_LastToplevel, False, 0, (XEvent *)&cm); /* TODO: Continue with motif drag :-) */ } #endif /* TKDND_ENABLE_MOTIF_DRAGS */ } /* if (dnd->MouseWindowIsAware) */ /* * The following call will not change the mouse cursor. * It will only move the cursor window, only if its position is not * the current one (stored internally). */ if (dnd->SetCursor != NULL) { ret = (*dnd->SetCursor) (dnd, -1); if (!ret) goto exit; } break; } /* MotionNotify */ case ClientMessage: { XDND_DEBUG("XDND_BeginDrag: ClientMessage recieved\n"); XDND_HandleClientMessage(dnd, &xevent); break; } /* ClientMessage */ case SelectionRequest: { XDND_DEBUG("XDND_BeginDrag: " "SelectionRequest: getting widget data\n"); if (xevent.xselectionrequest.selection != dnd->DNDSelectionName) break; /* * Retieve the data from widget... */ if (dnd->data != NULL) Tcl_Free(dnd->data); dnd->data = NULL; dnd->index = 0; dnd->DesiredType = xevent.xselectionrequest.target; if (dnd->GetData != NULL) { status = (*dnd->GetData) (dnd, dnd->DraggerWindow, (unsigned char **) &dnd->data, &dnd->index, dnd->DesiredType); } XDND_DEBUG("XDND_BeginDrag: Sending Selection...\n"); XDND_SendDNDSelection(dnd, &xevent.xselectionrequest); if (dnd->data != NULL) { Tcl_Free(dnd->data); dnd->data = NULL; dnd->index = 0; } break; } /* SelectionRequest */ } /* switch (xevent.type) */ } /* while (xevent.xany.type != ButtonRelease) */ exit: XUngrabPointer(dnd->display, CurrentTime); /* * Tk had processed a ButtonPress event when we get called and stealed * the events from tk. So, pass this button release back to tk, so as * not to activate menus, etc... */ if (dnd->HandleEvents != NULL) (*dnd->HandleEvents) (dnd, &xevent); XDND_Reset(dnd); XDND_DEBUG("XDND_BeginDrag: Returning to Tk's event loop...\n"); return status; } /* XDND_BeginDrag */ /* * D R O P O P E R A T I O N S */ /* * XDND_HandleClientMessage -- * Handle Client Messages... * Usually these events come for a target window, while a drop cursor is over * a target window... */ int XDND_HandleClientMessage(XDND *dnd, XEvent *xevent) { XClientMessageEvent clientMessage; clientMessage = xevent->xclient; /* * target: receive and process window-level enter and leave */ if (clientMessage.message_type == dnd->DNDEnterXAtom) { return XDND_HandleDNDEnter(dnd, clientMessage); } else if (clientMessage.message_type == dnd->DNDHereXAtom) { return XDND_HandleDNDHere(dnd, clientMessage); } else if (clientMessage.message_type == dnd->DNDLeaveXAtom) { return XDND_HandleDNDLeave(dnd, clientMessage); } else if (clientMessage.message_type == dnd->DNDDropXAtom) { return XDND_HandleDNDDrop(dnd, clientMessage); } else if (clientMessage.message_type == dnd->DNDStatusXAtom) { /* * source: clear our flag when we receive status message */ return XDND_HandleDNDStatus(dnd, clientMessage); } else if (clientMessage.message_type == dnd->DNDFinishedXAtom) { XDND_DEBUG("XDND_HandleClientMessage: Received XdndFinished\n"); return True; } else { #ifdef TKDND_ENABLE_MOTIF_DROPS /* * Is it a Motif Message? */ if (MotifDND_HandleClientMessage(dnd, *xevent)) { return True; } #endif /* TKDND_ENABLE_MOTIF_DROPS */ /* * Not for us :-) */ return False; } return False; } /* XDND_HandleClientMessage */ /* * XDND_HandleDNDEnter -- * This function is called when the mouse enters a toplevel that is XDND * aware (note: not a widget!). Its purpose is to anounce the source window * and its supported types... */ int XDND_HandleDNDEnter(XDND *dnd, XClientMessageEvent clientMessage) { Atom *typelist; int vers; #ifdef DND_DEBUG Atom *atom; char *AtomName; #endif /* DND_DEBUG */ /* * We should not receive such an event during a drag operation... */ if (dnd->IsDraggingFlag) { XDND_DEBUG("XDND_HandleDNDEnter: Received during drag?\n"); return False; } vers = (clientMessage.data.l[1] >> 24); XDND_DEBUG2("XDND_HandleDNDEnter: Requesting protocol version %d\n", vers); if (vers < XDND_MINVERSION) return False; dnd->XDNDVersion = vers; XDND_DEBUG2("XDND_HandleDNDEnter: Using protocol version %ld\n", dnd->XDNDVersion); dnd->IsDraggingFlag = False; dnd->DraggerWindow = clientMessage.data.l[0]; dnd->Toplevel = clientMessage.window; dnd->MouseWindow = None; dnd->WillAcceptDropFlag = False; dnd->DesiredType = None; if (dnd->DraggerTypeList != NULL) { Tcl_Free((char *)dnd->DraggerTypeList); dnd->DraggerTypeList = NULL; } /*XSelectInput(dnd->display, dnd->DraggerWindow, StructureNotifyMask);*/ /* * Does the drag source supports less than 3 types? */ if ((clientMessage.data.l[1] & 0x1UL) == 0) { typelist = (Atom *) Tcl_Alloc(sizeof(Atom)*4); if (typelist == NULL) return False; typelist[0] = clientMessage.data.l[2]; typelist[1] = clientMessage.data.l[3]; typelist[2] = clientMessage.data.l[4]; typelist[3] = None; #ifdef DND_DEBUG XDND_DEBUG("XDND_HandleDNDEnter: " "Drag source supports at most 3 types:\n"); for (atom = typelist; *atom != 0; atom++) { AtomName = XGetAtomName(dnd->display, *atom); XDND_DEBUG2(" %s\n", AtomName); XFree(AtomName); } #endif /* DND_DEBUG */ } else { typelist = XDND_GetTypeList(dnd, dnd->DraggerWindow); if (typelist == NULL) { XDND_DEBUG("XDND_HandleDNDEnter: " "There are no supported types by the drag source!\n"); return False; } #ifdef DND_DEBUG XDND_DEBUG("XDND_HandleDNDEnter: " "Drag source supports more than 3 types\n"); for (atom = typelist; *atom != 0; atom++) { AtomName = XGetAtomName(dnd->display, *atom); XDND_DEBUG2(" %s\n", AtomName); XFree(AtomName); } #endif /* DND_DEBUG */ } dnd->DraggerTypeList = typelist; /* * Get the supported by the drag source actions... */ if (dnd->DraggerAskActionList != NULL) { Tcl_Free((char *) dnd->DraggerAskActionList); } dnd->DraggerAskActionList = XDND_GetAskActions(dnd, dnd->DraggerWindow); /* The following command will place the actions in the variable * dnd->DraggerAskDescriptions... */ XDND_GetAskActionDescriptions(dnd, dnd->DraggerWindow); dnd->ResetValues = False; return True; } /* XDND_HandleDNDEnter */ /* * XDND_HandleDNDHere -- * This function will be constantly called while the mouse is moving inside * the toplevel. It is responsible to get the widgets below the mouse and * send the appropriate messages to the widgets (like Enter/Leave...) */ int XDND_HandleDNDHere(XDND *dnd, XClientMessageEvent clientMessage) { XRectangle rectangle; Window target; Atom action, supportedAction = None, desired_type; Time time; int wantPosition, will_accept = True; #ifdef DND_DEBUG char *AtomName; #endif /* DND_DEBUG */ XDND_DEBUG("XDND_HandleDNDHere:\n"); /* * We should not receive such an event during a drag operation... */ if (dnd->IsDraggingFlag) { XDND_DEBUG("XDND_HandleDNDHere: Received during drag?\n"); return False; } if (dnd->DraggerWindow != (Window) clientMessage.data.l[0]) { XDND_DEBUG("XDND_HandleDNDHere: bad DraggerWindow\n"); return False; } time = clientMessage.data.l[3]; action = clientMessage.data.l[4]; dnd->x = (clientMessage.data.l[2] >> 16); dnd->y = (clientMessage.data.l[2] & 0xFFFFUL); dnd->IsDraggingFlag = False; dnd->Toplevel = clientMessage.window; if (!XDND_FindTarget(dnd, dnd->x, dnd->y, NULL, NULL, &target, NULL, NULL)) { XDND_DEBUG("XDND_HandleDNDHere: target NOT found\n"); return False; } XDND_DEBUG("XDND_HandleDNDHere: target found\n"); /* Is the target widget the same as the previous call? If not, send a Leave * event to the old window and an enter event to the new one... */ if (target != dnd->MouseWindow) { if (dnd->MouseWindow != None && dnd->WidgetApplyLeaveCallback != NULL) { (*dnd->WidgetApplyLeaveCallback) (dnd, dnd->MouseWindow); } dnd->MouseWindow = target; if (dnd->WidgetApplyEnterCallback != NULL) { will_accept = (*dnd->WidgetApplyEnterCallback) (dnd, target, dnd->DraggerWindow, action, dnd->x, dnd->y, time, dnd->DraggerTypeList); /* TODO: The callback may raise an error. What can we do? The drag * source has a global cursor drag... */ } } dnd->MouseWindowIsAware = True; if (will_accept) { if (dnd->DraggerAskActionList == NULL) { dnd->DraggerAskActionList = XDND_GetAskActions(dnd, dnd->DraggerWindow); XDND_GetAskActionDescriptions(dnd, dnd->DraggerWindow); /* * If we fail, make a "list" out of the Dragger supported action... */ dnd->DraggerAskActionList = (Atom *) Tcl_Alloc(sizeof(Atom)*2); if (dnd->DraggerAskActionList != NULL) { dnd->DraggerAskActionList[0] = action; dnd->DraggerAskActionList[1] = None; } } dnd->WillAcceptDropFlag = (*dnd->WidgetApplyPositionCallback) (dnd, target, dnd->DraggerWindow, action, dnd->DraggerAskActionList, dnd->x, dnd->y, time, dnd->DraggerTypeList, &wantPosition, &supportedAction, &desired_type, &rectangle); /* TODO: The callback may raise an error. What can we do? The drag * source has a global cursor drag... */ dnd->DesiredType = desired_type; #ifdef DND_DEBUG if (dnd->WillAcceptDropFlag) { AtomName = XGetAtomName(dnd->display, supportedAction); XDND_DEBUG2("XDND_HandleDNDHere: Supported Action: %s\n", AtomName); XFree(AtomName); } #endif /* DND_DEBUG */ } else { dnd->MouseWindow = None; dnd->MouseWindowIsAware = True; dnd->WillAcceptDropFlag = False; dnd->DesiredType = None; XDND_DEBUG("XDND_HandleDNDHere: Window refuses drop!\n"); } /* TODO: */ dnd->SupportedAction = supportedAction; XDND_SendDNDStatus(dnd, supportedAction); dnd->ResetValues = False; return True; } /* XDND_HandleDNDHere */ /* * XDND_HandleDNDLeave -- */ int XDND_HandleDNDLeave(XDND *dnd, XClientMessageEvent clientMessage) { XDND_DEBUG("XDND_HandleDNDLeave\n"); /* * We should not receive such an event during a drag operation... */ if (dnd->IsDraggingFlag) { XDND_DEBUG("XDND_HandleDNDLeave: Received during drag?\n"); return False; } /*XSelectInput(dnd->display, dnd->DraggerWindow, NoEventMask);*/ if (dnd->DraggerWindow != clientMessage.data.l[0]) { XDND_DEBUG("XDND_HandleDNDLeave: bad DraggerWindow\n"); return False; } /* * Declare that we want to reset values. If we execute a tcl callback that * contains an "update" command, it is very possible that a ClientMessage is * handled, handling an XdndEnter/XdndPosition event. We don't want to loose * them :-)... */ dnd->ResetValues = True; if (dnd->WidgetApplyLeaveCallback != NULL) { (*dnd->WidgetApplyLeaveCallback) (dnd, dnd->MouseWindow); } if (dnd->ResetValues) { dnd->IsDraggingFlag = False; dnd->DraggerWindow = None; if (dnd->DraggerTypeList != NULL) { Tcl_Free((char *)dnd->DraggerTypeList); dnd->DraggerTypeList = NULL; } if (dnd->DraggerAskActionList != NULL) { Tcl_Free((char *) dnd->DraggerAskActionList); } dnd->DraggerAskActionList = NULL; dnd->Toplevel = None; dnd->MouseWindow = None; dnd->WillAcceptDropFlag = False; dnd->DesiredType = None; XDND_Reset(dnd); } return True; } /* XDND_HandleDNDLeave */ /* * XDND_HandleDNDDrop -- */ int XDND_HandleDNDDrop(XDND *dnd, XClientMessageEvent clientMessage) { Atom actualType, actualAction; Window selectionOwner; Tk_Window tkwin; XEvent xevent; XDND_BOOL receivedEvent = False, userBored = False; Time time; int status, format; long read = 0; clock_t startTime, endTime; unsigned char *s, *data = NULL; unsigned long count, remaining; XDND_DEBUG("XDND_HandleDNDDrop\n"); /* * We should not receive such an event during a drag operation... */ if (dnd->IsDraggingFlag) { XDND_DEBUG("XDND_HandleDNDDrop: Received during drag?\n"); return False; } if (dnd->DraggerWindow != (Window) clientMessage.data.l[0]) { XDND_DEBUG("XDND_HandleDNDDrop: bad DraggerWindow\n"); dnd->DraggerWindow = (Window) clientMessage.data.l[0]; } if ((tkwin = Tk_IdToWindow(dnd->display, dnd->MouseWindow)) == NULL) { XDND_DEBUG("XDND_HandleDNDDrop: bad Mouse Window\n"); goto finish; } time = clientMessage.data.l[2]; #ifdef XDND_USE_TK_GET_SELECTION dnd->DesiredName = Tk_GetAtomName(tkwin, dnd->DesiredType); if (strncmp(dnd->DesiredName, "text", 4) == 0) { /* Textual data. Let tk handle them... */ if (dnd->data != NULL) Tcl_Free(dnd->data); dnd->data = NULL; dnd->index = 0; status = Tk_GetSelection(dnd->interp, tkwin, dnd->DNDSelectionName, dnd->DNDStringAtom, &XDND_GetSelProc, (ClientData) dnd); if (status == TCL_ERROR) { XDND_DEBUG2("XDND_HandleDNDDrop:%s\n", Tcl_GetStringResult(dnd->interp)); goto binary; } } else { binary: #endif /* XDND_USE_TK_GET_SELECTION */ status = False; /* Binary data?? */ if (dnd->data != NULL) Tcl_Free(dnd->data); dnd->data = NULL; dnd->index = 0; selectionOwner = XGetSelectionOwner(dnd->display, dnd->DNDSelectionName); if (selectionOwner == None) goto finish; #ifdef DND_DEBUG XDND_DEBUG3(": Getting selection with type \"%s\" (0x%08x)\n", Tk_GetAtomName(tkwin, dnd->DesiredType), dnd->DesiredType); #endif XConvertSelection(dnd->display, dnd->DNDSelectionName, dnd->DesiredType, dnd->DNDNonProtocolAtom, dnd->MouseWindow, CurrentTime); startTime = clock(); endTime = startTime + 5 * CLOCKS_PER_SEC; while (!receivedEvent && clock() < endTime) { receivedEvent = XCheckTypedWindowEvent(dnd->display, dnd->MouseWindow, SelectionNotify, &xevent); if (!userBored && clock() > startTime + 1 * CLOCKS_PER_SEC) { userBored = True; /* * TODO: Make the cursor the busy cursor... */ } if (receivedEvent) break; } do { if (XGetWindowProperty(dnd->display, dnd->MouseWindow, dnd->DNDNonProtocolAtom, read / 4, 65536, True, AnyPropertyType, &actualType, &format, &count, &remaining, &s) != Success) { XFree (s); goto finish; } read += count; if (data == NULL) { data = (unsigned char *) Tcl_Alloc(sizeof(unsigned char) *(read+2)); dnd->index = 0; if (data == NULL) return TCL_ERROR; } else { data = (unsigned char *) Tcl_Realloc((char*)data, sizeof(unsigned char)*(read+2)); } memcpy(&(data)[dnd->index], s, read); dnd->index = read; data[read] = '\0'; /* printf("atom=%ld, read=%ld, binary-data:%s\n", actualType, read, s); */ XFree (s); } while (remaining); dnd->data = (char*)data; dnd->index = read; #ifdef XDND_USE_TK_GET_SELECTION } #endif /* XDND_USE_TK_GET_SELECTION */ XDND_DEBUG3("XDND_HandleDNDDrop: Dropped data: (%d) \"%s\"\n", dnd->index, dnd->data); /* * If the desired action is ask, ask the user :-) */ if (dnd->SupportedAction == dnd->DNDActionAskXAtom) { if (dnd->Ask != NULL) { status = (*dnd->Ask) (dnd, dnd->DraggerWindow, dnd->MouseWindow, &actualAction); if (!status || actualAction == None) return False; dnd->SupportedAction = actualAction; } else { /* TODO: What to do here? How to decide on the correct action? */ } } /* * Call the insert widget data callback... */ if (dnd->WidgetInsertDropDataCallback != NULL) { (*dnd->WidgetInsertDropDataCallback) (dnd, (unsigned char *) dnd->data, dnd->index, 0, dnd->MouseWindow, dnd->DraggerWindow, dnd->DesiredType); } if (dnd->data != NULL) Tcl_Free(dnd->data); dnd->data = NULL; dnd->index = 0; finish: #ifdef TKDND_ENABLE_MOTIF_DROPS if (!dnd->Motif_DND) { #endif /* TKDND_ENABLE_MOTIF_DROPS */ /* * Send "XdndFinish"... */ xevent.xclient.type = ClientMessage; xevent.xclient.display = dnd->display; xevent.xclient.window = dnd->DraggerWindow; xevent.xclient.message_type = dnd->DNDFinishedXAtom; xevent.xclient.format = 32; xevent.xclient.data.l[0] = dnd->Toplevel; xevent.xclient.data.l[1] = 0; XSendEvent(dnd->display, dnd->DraggerWindow, 0, 0, &xevent); #ifdef TKDND_ENABLE_MOTIF_DROPS } #endif /* TKDND_ENABLE_MOTIF_DROPS */ /*XSelectInput(dnd->display, dnd->DraggerWindow, NoEventMask);*/ dnd->IsDraggingFlag = False; dnd->DraggerWindow = None; if (dnd->DraggerTypeList != NULL) { Tcl_Free((char *)dnd->DraggerTypeList); dnd->DraggerTypeList = NULL; } if (dnd->DraggerAskActionList != NULL) { Tcl_Free((char *) dnd->DraggerAskActionList); } dnd->DraggerAskActionList = NULL; dnd->Toplevel = None; dnd->MouseWindow = None; dnd->WillAcceptDropFlag = False; dnd->DesiredType = None; /* * Make sure we free any allocated memory... */ if (dnd->data != NULL) Tcl_Free(dnd->data); dnd->data = NULL; XDND_Reset(dnd); return True; } /* XDND_HandleDNDDrop */ /* * XDND_GetSelProc -- * This is the callback for Tk_GetSelection */ int XDND_GetSelProc(ClientData clientData, Tcl_Interp *interp, char *portion) { XDND *dnd = (XDND *) clientData; int length; if (portion == NULL) return TCL_ERROR; length = strlen(portion); if (dnd->data == NULL) { dnd->data = (char *) Tcl_Alloc(sizeof(char)*(length+2)); dnd->index = 0; if (dnd->data == NULL) return TCL_ERROR; } else { dnd->data = Tcl_Realloc(dnd->data, sizeof(char)*(length+2)); } strcpy(&(dnd->data)[dnd->index], portion); dnd->index += length; return TCL_OK; } /* XDND_GetSelProc */ /* * EOF - End of File */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/XDND.h0000644000175000017500000003434210562403651022041 0ustar domibeldomibel/* * XDND.h -- Definitions of the Tk XDND Drag'n'Drop Protocol Implementation * * This file implements the unix portion of the drag&drop mechanish * for the tk toolkit. The protocol in use under unix is the * XDND protocol. * * This software is copyrighted by: * George Petasis, National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * Laurent Riesterer, Rennes, France. * e-mail: laurent.riesterer@free.fr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ #ifndef _X_DND_H #define _X_DND_H #include "vtkTcl.h" #include "vtkTk.h" #include #include #include "tkDND.h" #ifdef TKDND_ENABLE_MOTIF_DRAGS #ifndef TKDND_ENABLE_MOTIF_DROPS #define TKDND_ENABLE_MOTIF_DROPS #endif /* TKDND_ENABLE_MOTIF_DROPS */ #endif /* TKDND_ENABLE_MOTIF_DRAGS */ /* * We also support Motif drops :-) */ #ifdef TKDND_ENABLE_MOTIF_DROPS #include "Dnd.h" #endif /* TKDND_ENABLE_MOTIF_DROPS */ #define XDND_VERSION 3 #define XDND_MINVERSION 3 #define XDND_ENTERTYPECOUNT 3 #define XDND_BOOL short #define XDND_NODROP_CURSOR 0 #define XDND_COPY_CURSOR 1 #define XDND_MOVE_CURSOR 2 #define XDND_LINK_CURSOR 3 #define XDND_ASK_CURSOR 4 #define XDND_PRIVATE_CURSOR 5 /* * Debug Facilities... */ #ifndef XDND_DEBUG #ifdef DND_DEBUG #include #define XDND_DEBUG(a) \ printf("%s, %d: " a,__FILE__,__LINE__); fflush(stdout) #define XDND_DEBUG2(a,b) \ printf("%s, %d: " a,__FILE__,__LINE__,b); fflush(stdout) #define XDND_DEBUG3(a,b,c) \ printf("%s, %d: " a,__FILE__,__LINE__,b,c); fflush(stdout) #define XDND_DEBUG4(a,b,c,d) \ printf("%s, %d: " a,__FILE__,__LINE__,b,c,d); fflush(stdout) #define XDND_DEBUG5(a,b,c,d,e) \ printf("%s, %d: " a,__FILE__,__LINE__,b,c,d,e); fflush(stdout) #else /* DND_DEBUG */ #define XDND_DEBUG(a) #define XDND_DEBUG2(a,b) #define XDND_DEBUG3(a,b,c) #define XDND_DEBUG4(a,b,c,d) #define XDND_DEBUG5(a,b,c,d,e) #endif /* DND_DEBUG */ #endif /* XDND_DEBUG */ #ifdef __cplusplus extern "C" { #endif #ifndef LONG_MAX #define LONG_MAX 0x8000000L #endif #define Min(x,y) (xToplevel supports Motif */ Atom Motif_DND_Selection; /* The selection that will be used */ Atom Motif_DND_WM_STATE; /* WM_STATE property */ #endif /* TKDND_ENABLE_MOTIF_DRAGS */ /* * Keep info about the last window that we send a event. * If the LastEnterDeliveredWindow is not None, then we have to simulate * a DragLeave to that window. We have to do that, as qt for example * sometimes forgets (!) to send Leave events to windows that overlap... */ Window LastEnterDeliveredWindow; unsigned int Alt_ModifierMask; /* The modifier the Alt keys are bind to */ unsigned int Meta_ModifierMask; /* The modifier the Meta keys are bind to */ /* Here we keep some frequently used Atoms... */ Atom DNDSelectionName; Atom DNDProxyXAtom; Atom DNDAwareXAtom; Atom DNDTypeListXAtom; Atom DNDEnterXAtom; Atom DNDHereXAtom; Atom DNDStatusXAtom; Atom DNDLeaveXAtom; Atom DNDDropXAtom; Atom DNDFinishedXAtom; Atom DNDActionCopyXAtom; Atom DNDActionMoveXAtom; Atom DNDActionLinkXAtom; Atom DNDActionAskXAtom; Atom DNDActionPrivateXAtom; Atom DNDActionListXAtom; Atom DNDActionDescriptionXAtom; Atom DNDDirectSave0XAtom; Atom DNDMimePlainTextXAtom; Atom DNDStringAtom; Atom DNDNonProtocolAtom; /* * Allow user to register event callbacks... */ /* This function will be called for various windows (application or * foreign). It must return True if given window is a valid one and belongs * to this application. Else, False must be returned. * If this method is not set then the code assumes that no widgets have * support for recieving drops. In this case none of the widget methods * need be set. */ int (*WidgetExistsCallback) (struct _XDND_Struct *dnd, Window window); /* This function will be called when the mouse has entered a widget to * announce "XdndEnter". This function must return True if the widget will * accept the drop and False otherwise. If True is returned, the apply * position callback (the next pointer :-)) will be immediately called... */ int (*WidgetApplyEnterCallback) (struct _XDND_Struct *dnd, Window target, Window source, Atom action, int x, int y, Time t, Atom *typelist); /* This function will be called when the mouse is moving inside a drag * target. It is responsible for changing the drop target widget appearence. * It must also sets the correct data to pointers. As per the protocol, if * the widget cannot perform the action specified by `action' then it should * return either XdndActionPrivate or XdndActionCopy into supported_action * (leaving supported_action unchanged is equivalent to XdndActionCopy). * Returns True if widget is ready to accept the drop... */ int (*WidgetApplyPositionCallback) (struct _XDND_Struct *dnd, Window target, Window source, Atom action, Atom *actionList, int x, int y, Time t, Atom *typelist, int *wantPosition, Atom *supported_action, Atom *desired_type, XRectangle *rectangle); /* This function will be called when the mouse leaves a drop target widget, * or when the drop is canceled. It must update the widget border to its * default appearance... */ int (*WidgetApplyLeaveCallback) (struct _XDND_Struct *dnd, Window target); /* This function must insert the data into the drop target */ int (*WidgetInsertDropDataCallback) (struct _XDND_Struct *dnd, unsigned char *data, int length, int remaining, Window into, Window from, Atom type); /* This function will be used in order to get the user-prefered action, if * the action is XdndAsk... */ int (*Ask) (struct _XDND_Struct *dnd, Window source, Window target, Atom *action); /* This is our callback to get the data that is to be dropped from the drag * source... */ int (*GetData) (struct _XDND_Struct *dnd, Window source, unsigned char **data, int *length, Atom type); /* This function will be called, in order to handle events that are not * related to the XDND protocol... */ void (*HandleEvents) (struct _XDND_Struct *dnd, XEvent *xevent); /* * This function must return the current types that a window supports as a * drag source... */ Atom *(*GetDragAtoms) (struct _XDND_Struct *dnd, Window window); /* * Set the cursor callback... * The requested cursors will be one of the extern Cursor variables: * noDropCursor, moveCursor, copyCursor, linkCursor, askCursor */ int (*SetCursor) (struct _XDND_Struct *dnd, int cursor); } XDND; #define DndClass XDND extern Cursor noDropCursor, moveCursor, copyCursor, linkCursor, askCursor; /* * Function Prototypes... */ void XDND_Reset(XDND *dndp); XDND *XDND_Init(Display *display); void XDND_Enable(XDND *dnd, Window window); XDND_BOOL XDND_IsDndAware(XDND *dnd, Window window, Window* proxy, Atom *vers); int XDND_AtomListLength(Atom *list); int XDND_DescriptionListLength(char *list); Atom *XDND_GetTypeList(XDND *dnd, Window window); void XDND_AnnounceTypeList(XDND *dnd, Window window, Atom *list); void XDND_AppendType(XDND *dnd, Window window, Atom type); void XDND_AnnounceAskActions(XDND *dnd, Window window, Atom *Actions, char *Descriptions); Atom *XDND_GetAskActions(XDND *dnd, Window window); char *XDND_GetAskActionDescriptions(XDND *dnd, Window window); XDND_BOOL XDND_DraggerCanProvideText(XDND *dnd); XDND_BOOL XDND_FindTarget(XDND *dnd, int x, int y, Window *toplevel, Window *msgWindow, Window *target, XDND_BOOL *aware, Atom *version); Window XDND_FindToplevel(XDND *dnd, Window window); XDND_BOOL XDND_BeginDrag(XDND *dnd, Window source, Atom *actions, Atom *types, char *Descriptions, Tk_Window cursor_window, char *cursor_callback); void XDND_SendDNDEnter(XDND *dnd, Window window, Window msgWindow, XDND_BOOL isAware, Atom vers); XDND_BOOL XDND_SendDNDPosition(XDND *dnd, Atom action); XDND_BOOL XDND_SendDNDStatus(XDND *dnd, Atom action); XDND_BOOL XDND_SendDNDLeave(XDND *dnd); XDND_BOOL XDND_SendDNDDrop(XDND *dnd); XDND_BOOL XDND_SendDNDSelection(XDND *dnd, XSelectionRequestEvent *request); int XDND_HandleClientMessage(XDND *dnd, XEvent *xevent); int XDND_HandleDNDEnter(XDND *dnd, XClientMessageEvent clientMessage); int XDND_HandleDNDHere(XDND *dnd, XClientMessageEvent clientMessage); int XDND_HandleDNDLeave(XDND *dnd, XClientMessageEvent clientMessage); int XDND_HandleDNDDrop(XDND *dnd, XClientMessageEvent clientMessage); int XDND_GetSelProc(ClientData clientData, Tcl_Interp *interp, char *portion); int XDND_HandleDNDStatus(XDND *dnd, XClientMessageEvent clientMessage); #ifdef TKDND_ENABLE_MOTIF_DROPS int MotifDND_HandleClientMessage(XDND *dnd, XEvent xevent); #endif /* TKDND_ENABLE_MOTIF_DROPS */ #ifdef __cplusplus } #endif #endif /* _X_DND_H */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/unix/Motif.c0000644000175000017500000003306010562403651022351 0ustar domibeldomibel/* * Motif.c -- Tk Motif Drag'n'Drop Protocol Implementation * * This file implements the unix portion of the drag&drop mechanism * for the tk toolkit. The protocol in use under unix is the * XDND protocol. This file adds the possibility for Motif drops... * * This software is copyrighted by: * George Petasis, National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ #include #include #include #include #include #include #include "vtkTcl.h" #include "vtkTk.h" #include #include #include #include /* * Static variable that holds the drag source valid actions... */ Atom MotifDND_DraggerActionList[4]; int MotifDND_HandleClientMessage(XDND *dnd, XEvent xevent) { XClientMessageEvent cm; XRectangle rectangle; XDND_BOOL aware; DndData *dnd_data = &dnd->Motif_DND_Data; Window cur_window = None, src_window = None, temp_win; Atom *src_targets, Selection, DesiredType, temp_atom; /*XDND_BOOL receivedEvent = False, userBored = False; clock_t startTime, endTime; */ char receiver; int status; unsigned short num_src_targets, i; #ifdef DND_DEBUG char *AtomName; #endif /* DND_DEBUG */ if (!(DndParseClientMessage((XClientMessageEvent*) &xevent, dnd_data, &receiver))) { return False; } MotifDND_DraggerActionList[0] = dnd->DNDActionCopyXAtom; MotifDND_DraggerActionList[1] = None; XDND_DEBUG2(" -->> dnd_data->reason = %d\n", dnd_data->reason); if (dnd_data->reason == DND_DRAG_MOTION) { /* * We receive these events as the mouse moves inside the toplevel. * We have to find the actual window we are over, emulate * Enter/Leave events and query widget whether it will accept the * drop or not :-). Simple stuff... */ /* * Set the desired by the drag source action... * TODO: */ /* * Reset drag source supported actions... * TODO: */ /*for (i=0; i<4; i++) { MotifDND_DraggerActionList[i] = None; }*/ dnd->x = dnd_data->x; dnd->y = dnd_data->y; dnd->Toplevel = xevent.xclient.window; src_window = dnd->DraggerWindow; XDND_FindTarget(dnd, dnd->x, dnd->y, &temp_win, &temp_win, &cur_window, &aware, &temp_atom); XDND_DEBUG2("We are at window %ld\n", cur_window); if (cur_window == None) return True; if (dnd->MouseWindow != cur_window) { /* * Send a Leave event to old window... */ XDND_DEBUG2("MotifDND_HandleClientMessage: Sending Leave to window " "%ld...\n", dnd->MouseWindow); if (dnd->WidgetApplyLeaveCallback != NULL) { (*dnd->WidgetApplyLeaveCallback) (dnd, dnd->MouseWindow); } dnd->MouseWindow = cur_window; dnd->WillAcceptDropFlag = False; /* * Send an Enter event to the new window... */ XDND_DEBUG2("MotifDND_HandleClientMessage: Sending Enter to window " "%ld...\n", dnd->MouseWindow); if (dnd->WidgetApplyEnterCallback != NULL) { status = (*dnd->WidgetApplyEnterCallback) (dnd, dnd->MouseWindow, dnd->DraggerWindow, dnd->DNDActionCopyXAtom, dnd->x, dnd->y, CurrentTime, dnd->DraggerTypeList); } } /* * Now, simulate XdndPosition and ask widget whether it will accept * the data at that particular point... */ if (!status) return True; if (dnd->WidgetApplyPositionCallback != NULL) { status = (*dnd->WidgetApplyPositionCallback) (dnd, dnd->MouseWindow, dnd->DraggerWindow, dnd->DNDActionCopyXAtom, MotifDND_DraggerActionList, dnd->x, dnd->y, CurrentTime, dnd->DraggerTypeList, &status, &(dnd->SupportedAction), &(dnd->DesiredType), &rectangle); if (dnd->CallbackStatus == TCL_ERROR || !status) { if (dnd->WillAcceptDropFlag) { /* We have send a drop site enter. Send a drop site leave... */ XDND_DEBUG("MotifDND_HandleClientMessage: sending drop site " "leave\n"); dnd_data->reason = DND_DROP_SITE_LEAVE; dnd_data->time = CurrentTime; DndFillClientMessage(xevent.xclient.display, src_window, &cm, dnd_data, 0); XSendEvent(dnd->display, src_window, False, 0, (XEvent *)&cm); XDND_DEBUG2("MotifDND_HandleClientMessage: XSendEvent " "DND_DROP_SITE_LEAVE %ld\n", src_window); dnd->WillAcceptDropFlag = False; } return True; } /* * if dnd->WillAcceptDropFlag == True, then we have already send a * drop site enter. So, repeat the drag motion event... */ if (dnd->WillAcceptDropFlag) { XDND_DEBUG("MotifDND_HandleClientMessage: repeating drag motion " "...\n"); dnd_data->reason = DND_DRAG_MOTION; dnd_data->time = CurrentTime; if (dnd->SupportedAction == dnd->DNDActionCopyXAtom) { dnd_data->operation = DND_COPY; } else if (dnd->SupportedAction == dnd->DNDActionMoveXAtom) { dnd_data->operation = DND_MOVE; } else if (dnd->SupportedAction == dnd->DNDActionLinkXAtom) { dnd_data->operation = DND_LINK; } else { dnd_data->operation = DND_MOVE|DND_COPY|DND_LINK; } dnd_data->operations = DND_MOVE|DND_COPY|DND_LINK; DndFillClientMessage(xevent.xclient.display, src_window, &cm, dnd_data, 0); XSendEvent(dnd->display, src_window, False, 0, (XEvent *)&cm); XDND_DEBUG2("MotifDND_HandleClientMessage: XSendEvent " "DND_DRAG_MOTION %ld\n", src_window); return True; } dnd->WillAcceptDropFlag = status; XDND_DEBUG("MotifDND_HandleClientMessage: sending drop site " "enter\n"); dnd_data->reason = DND_DROP_SITE_ENTER; dnd_data->time = CurrentTime; dnd_data->operation = DND_MOVE|DND_COPY|DND_LINK; dnd_data->operations = DND_MOVE|DND_COPY|DND_LINK; DndFillClientMessage(xevent.xclient.display, src_window, &cm, dnd_data, 0); XSendEvent(dnd->display, src_window, False, 0, (XEvent *)&cm); XDND_DEBUG2("MotifDND_HandleClientMessage: XSendEvent " "DND_DROP_SITE_ENTER %ld\n", src_window); } } else if (dnd_data->reason == DND_TOP_LEVEL_ENTER) { /* * The mouse has entered in a new toplevel... */ dnd->DraggerWindow = src_window = dnd_data->src_window; dnd->MouseWindow = None; XDND_DEBUG2("source sending a top level enter %ld\n", src_window); /* no answer needed, just read source property */ DndReadSourceProperty(xevent.xclient.display, src_window, dnd_data->property, &src_targets, &num_src_targets); if (dnd->DraggerTypeList!=NULL) Tcl_Free((char *) dnd->DraggerTypeList); /* * Sometimes, we get numbers of supported types, like 41072, and Atom * numbers like 7000000... */ for (i = 0; i < num_src_targets; i++) { if (src_targets[i] > 6000) { num_src_targets = i; break; } } dnd->DraggerTypeList = (Atom *) Tcl_Alloc(sizeof(Atom) * (num_src_targets+2)); XDND_DEBUG2("MotifDND_HandleClientMessage: Drag source supports " "%d types:\n", num_src_targets); for (i = 0; i < num_src_targets; i++) { dnd->DraggerTypeList[i] = src_targets[i]; #ifdef DND_DEBUG XDND_DEBUG2(" (%ld)", src_targets[i]); if (src_targets[i] == None) continue; AtomName = XGetAtomName(dnd->display, src_targets[i]); XDND_DEBUG2(" %s\n", AtomName); XFree(AtomName); #endif /* DND_DEBUG */ } dnd->DraggerTypeList[num_src_targets] = None; if (src_targets != NULL && num_src_targets) free(src_targets); } else if (dnd_data->reason == DND_TOP_LEVEL_LEAVE) { if (dnd->DraggerTypeList!=NULL) Tcl_Free((char *) dnd->DraggerTypeList); dnd->DraggerTypeList = NULL; XDND_DEBUG("source sending a top level leave\n"); /* no need to reply to this message... */ } else if (dnd_data->reason == DND_DROP_SITE_ENTER) { XDND_DEBUG("receiver sending drop site enter\n"); } else if (dnd_data->reason == DND_DROP_SITE_LEAVE) { XDND_DEBUG("receiver sending drop site leave\n"); } else if (dnd_data->reason == DND_OPERATION_CHANGED) { XDND_DEBUG("receiver sending operation changed\n"); } else if (dnd_data->reason == DND_DROP_START) { cur_window = dnd->MouseWindow; src_window = dnd->DraggerWindow; /* * Does the widget wants the drop? */ if (!dnd->WillAcceptDropFlag) { XDND_DEBUG("MotifDND_HandleClientMessage: sending drop failure!\n"); XConvertSelection(dnd->display, dnd_data->property, dnd->Motif_DND_FailureAtom, dnd_data->property, src_window, dnd_data->time); } else { XDND_DEBUG("MotifDND_HandleClientMessage: sending drop start!\n"); dnd_data->reason = DND_DROP_START; dnd_data->status = DND_VALID_DROP_SITE; dnd_data->operation = DND_COPY; dnd_data->completion = DND_DROP; DndFillClientMessage(xevent.xclient.display, cur_window, &cm, dnd_data, 0); XSendEvent(dnd->display, src_window, False, 0, (XEvent *)&cm); XDND_DEBUG2("MotifDND_HandleClientMessage: XSendEvent " "DND_DROP_START %ld\n", src_window); Selection = dnd->DNDSelectionName; DesiredType = dnd->DesiredType; #ifdef DND_DEBUG AtomName = XGetAtomName(dnd->display, dnd_data->property); XDND_DEBUG2("Getting Selection %s\n", AtomName); XFree(AtomName); #endif /* DND_DEBUG */ dnd->DNDSelectionName = dnd_data->property; xevent.xclient.data.l[0] = dnd->DraggerWindow; xevent.xclient.data.l[2] = CurrentTime; dnd->Motif_DND = True; XDND_HandleDNDDrop(dnd, xevent.xclient); dnd->Motif_DND = False; /* Report success, so as to notify the source application that we have * finished... */ XConvertSelection(dnd->display, dnd_data->property, dnd->Motif_DND_SuccessAtom, dnd_data->property, src_window, dnd_data->time); /* * Wait for notification from drag source... * Desided not to include it. Does not offer anything more than * delay :-). According to the protocol, it should be there... */ /* startTime = clock(); endTime = startTime + 5 * CLOCKS_PER_SEC; while (!receivedEvent && clock() < endTime) { receivedEvent=XCheckTypedWindowEvent(dnd->display, dnd->MouseWindow, SelectionNotify, &xevent); if (!userBored && clock() > startTime + 1 * CLOCKS_PER_SEC) { userBored = True; } if (receivedEvent) break; } */ dnd->DNDSelectionName = Selection; } /* * Reset all changed values... */ if (dnd->DraggerTypeList!=NULL) Tcl_Free((char *) dnd->DraggerTypeList); dnd->DraggerTypeList = NULL; dnd->WillAcceptDropFlag = False; dnd->DraggerWindow = None; dnd->MouseWindow = None; dnd->SupportedAction = None; dnd->DesiredType = None; dnd->CallbackStatus = TCL_OK; } return True; } /* MotifDND_HandleClientMessage */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/generic/0000755000175000017500000000000011461110203021541 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/generic/tkDND.h0000644000175000017500000001557110562163641022706 0ustar domibeldomibel/* * tkDND.h -- * * Header files for the drag&drop tk extension. * * This software is copyrighted by: * George Petasis, * Software and Knowledge Engineering Laboratory, * Institute of Informatics and Telecommunications, * National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * and * Laurent Riesterer, Rennes, France. * e-mail: laurent.riesterer@free.fr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ #ifndef _TKDND #define _TKDND #include "vtkTcl.h" #include "vtkTk.h" #include #include /* * If we aren't in 8.4, don't use 8.4 constness */ #ifndef CONST84 #define CONST84 #endif #if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) # define HAVE_TCL84 #endif #if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)) # define HAVE_TCL85 #endif /* * If "VERSION" is not defined, place a default value... */ #ifndef VERSION #ifdef PACKAGE_VERSION #define VERSION PACKAGE_VERSION #else #define VERSION "1.0" #endif #endif #ifdef __WIN32__ # include # include # include # ifndef Tk_GetHWND EXTERN HWND Tk_GetHWND(Window win); # endif /* Tk_GetHWND */ #endif /* __WIN32__ */ /* * These are passed to Tcl_PkgProvide... */ #define TKDND_PACKAGE "tkdnd" #define TKDND_VERSION VERSION /* * Maximum length of the action descriptions list... */ #define TKDND_MAX_DESCRIPTIONS_LENGTH 1034 #define TKDND_MAX_DESCRIPTIONS_LENGTH_STR "1024" /* * These are used for selecting the most specific events. * (Laurent please add description :-) */ #define TKDND_SOURCE 0 #define TKDND_GETDATA 1 #define TKDND_GETCURSOR 2 #define TKDND_TARGET 10 #define TKDND_DRAGENTER 11 #define TKDND_DRAGLEAVE 12 #define TKDND_DRAG 13 #define TKDND_DROP 14 #define TKDND_ASK 15 /* TODO: remove #define TKDND_MODS 0x000000FF #define TKDND_BUTTONS 0x00001F00 */ /* * Debug Facilities... */ #ifdef DND_DEBUG #include #ifdef __WIN32__ /* * Under Windows, we keep a log in a file. (Laurent, 09/07/2000) */ extern FILE *TkDND_Log; #define XDND_DEBUG(a) \ fprintf(TkDND_Log, "%s, %d: " a,__FILE__,__LINE__); fflush(TkDND_Log) #define XDND_DEBUG2(a,b) \ fprintf(TkDND_Log, "%s, %d: " a,__FILE__,__LINE__,b); fflush(TkDND_Log) #define XDND_DEBUG3(a,b,c) \ fprintf(TkDND_Log, "%s, %d: " a,__FILE__,__LINE__,b,c); fflush(TkDND_Log) #define XDND_DEBUG4(a,b,c,d) \ fprintf(TkDND_Log, "%s, %d: " a,__FILE__,__LINE__,b,c,d); fflush(TkDND_Log) #define XDND_DEBUG5(a,b,c,d,e) \ fprintf(TkDND_Log, "%s, %d: " a,__FILE__,__LINE__,b,c,d,e); fflush(TkDND_Log) #define XDND_DEBUG6(a,b,c,d,e,f) \ fprintf(TkDND_Log, "%s, %d: " a,__FILE__,__LINE__,b,c,d,e,f);fflush(TkDND_Log) #else /* __WIN32__ */ /* * Under Unix, we just write messages to stdout... */ #define XDND_DEBUG(a) \ printf("%s, %d: " a,__FILE__,__LINE__); fflush(stdout) #define XDND_DEBUG2(a,b) \ printf("%s, %d: " a,__FILE__,__LINE__,b); fflush(stdout) #define XDND_DEBUG3(a,b,c) \ printf("%s, %d: " a,__FILE__,__LINE__,b,c); fflush(stdout) #define XDND_DEBUG4(a,b,c,d) \ printf("%s, %d: " a,__FILE__,__LINE__,b,c,d); fflush(stdout) #define XDND_DEBUG5(a,b,c,d,e) \ printf("%s, %d: " a,__FILE__,__LINE__,b,c,d,e); fflush(stdout) #define XDND_DEBUG6(a,b,c,d,e,f) \ printf("%s, %d: " a,__FILE__,__LINE__,b,c,d,e,f); fflush(stdout) #endif /* __WIN32__ */ #else /* DND_DEBUG */ /* * Debug is not enabled. Just do nothing :-) */ #define XDND_DEBUG(a) #define XDND_DEBUG2(a,b) #define XDND_DEBUG3(a,b,c) #define XDND_DEBUG4(a,b,c,d) #define XDND_DEBUG5(a,b,c,d,e) #endif /* DND_DEBUG */ typedef struct _DndType { int priority; /* For target types, check priorities */ #ifdef __WIN32__ CLIPFORMAT type; /* Clipboard format (Windows)*/ CLIPFORMAT matchedType; /* Clipboard format (Windows)*/ #else /* __WIN32__ */ Atom type; /* Clipboard format (Unix)*/ Atom matchedType; /* Clipboard format (Unix)*/ #endif /* __WIN32__ */ char *typeStr; /* Name of type */ unsigned long eventType; /* Type of event */ unsigned long eventMask; /* Modifiers of event */ char *script; /* Script to run */ struct _DndType *next; /* Next one in list */ short EnterEventSent; /* Have we send an event? */ } DndType; typedef struct _DndInfo { Tcl_Interp *interp; /* The associated interp */ Tk_Window topwin; /* The main Tk window */ Tk_Window tkwin; /* The associated Tk window */ DndType head; /* Head of the list of supported types */ #ifdef __WIN32__ LPDROPTARGET DropTarget; /* The OLE IDropTarget object */ #endif /* __WIN32__ */ DndType *cbData; Tcl_HashEntry *hashEntry; /* Hash table entry */ } DndInfo; typedef struct _DndClass { Tk_Window MainWindow; /* The main window of our application */ Tcl_Interp *interp; /* A Tcl Interpreter */ Display *display; /* Display Pointer */ } DndClass; #ifndef LONG #define LONG long #endif /* LONG */ #ifdef MAC_TCL /* * Anybody ? */ #endif /* MAC_TCL */ #endif /* _TKDND */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/generic/tkDNDBind.cpp0000644000175000017500000005276610674504474024054 0ustar domibeldomibel/* * tkDNDBind.c -- * * This file implements a drag&drop mechanish for the tk toolkit. * It contains the top-level command routines as well as some needed * functions for defining and removing bind scripts. * * This software is copyrighted by: * George Petasis, National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * Laurent Riesterer, Rennes, France. * e-mail: laurent.riesterer@free.fr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ #include "vtkTcl.h" #include "vtkTk.h" #include #include #include #include #include "tkDND.h" #ifndef __WIN32__ #include "XDND.h" #else #include "OleDND.h" #endif extern DndClass *dnd; #ifdef __WIN32__ #define TKDND_MODS (MK_SHIFT | MK_ALT | MK_CONTROL) #define TKDND_BUTTONS (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) #else /* not __WIN32__ */ #define TKDND_MODS 0x000000FF #define TKDND_BUTTONS 0x00001F00 #endif /* __WIN32__ */ static char *TkDND_GetField _ANSI_ARGS_((char *p, char *copy, int size)); #ifdef __WIN32__ static int TkDND_FindScript _ANSI_ARGS_((DndInfo *infoPtrPtr, char *typeStr, CLIPFORMAT typelist[], unsigned long eventType, unsigned long eventMask, DndType **typePtrPtr)); extern int TkDND_FindMatchingScript(Tcl_HashTable *table, char *windowPath, char *typeStr, CLIPFORMAT typelist[], unsigned long eventType, unsigned long eventMask, int matchExactly, DndType **typePtrPtr, DndInfo **infoPtrPtr); #else /* not __WIN32__ */ static int TkDND_FindScript _ANSI_ARGS_((DndInfo *infoPtrPtr, char *typeStr, Atom typelist[], unsigned long eventType, unsigned long eventMask, DndType **typePtrPtr)); extern int TkDND_FindMatchingScript(Tcl_HashTable *table, char *windowPath, char *typeStr, Atom typelist[], unsigned long eventType, unsigned long eventMask, int matchExactly, DndType **typePtrPtr, DndInfo **infoPtrPtr); #endif /* __WIN32__ */ extern char *TkDND_TypeToString(int type); /* *--------------------------------------------------------------------------- * * TkDND_ParseEventDescription -- (Laurent Riesterer 06/07/2000) * * Fill Pattern buffer with information about event from * event string. * * Results: * Leaves error message in interp and returns 0 if there was an * error due to a badly formed event string. * * Side effects: * On exit, eventStringPtr points to rest of event string (after the * closing '>', so that this procedure can be called repeatedly to * parse all the events in the entire sequence. * *--------------------------------------------------------------------------- */ int TkDND_ParseEventDescription( Tcl_Interp *interp, /* For error messages. */ char *eventStringPtr, /* Hold the event string. */ unsigned long *eventTypePtr, /* Type of operation */ unsigned long *eventMaskPtr) /* Filled with event mask of matched event. */ { char *p; #define FIELD_SIZE 48 char field[FIELD_SIZE]; p = eventStringPtr; if (*p++ != '<') { goto error; } *eventMaskPtr = 0; while (1) { p = TkDND_GetField(p, field, FIELD_SIZE); #ifdef __WIN32__ if (strcmp(field, "Shift") == 0) { *eventMaskPtr |= MK_SHIFT; } else if (strcmp(field, "Control") == 0) { *eventMaskPtr |= MK_CONTROL; } else if (strcmp(field, "Alt") == 0) { *eventMaskPtr |= MK_ALT; } else if (strcmp(field, "Button1") == 0) { *eventMaskPtr |= MK_LBUTTON; } else if (strcmp(field, "Button2") == 0) { *eventMaskPtr |= MK_MBUTTON; } else if (strcmp(field, "Button3") == 0) { *eventMaskPtr |= MK_RBUTTON; } #else /* not __WIN32__ */ if (strcmp(field, "Shift") == 0) { *eventMaskPtr |= ShiftMask; } else if (strcmp(field, "Control") == 0) { *eventMaskPtr |= ControlMask; } else if (strcmp(field, "Alt") == 0) { *eventMaskPtr |= dnd->Alt_ModifierMask; } else if (strcmp(field, "Meta") == 0) { *eventMaskPtr |= dnd->Meta_ModifierMask; } else if (strcmp(field, "Button1") == 0) { *eventMaskPtr |= Button1Mask; } else if (strcmp(field, "Button2") == 0) { *eventMaskPtr |= Button2Mask; } else if (strcmp(field, "Button3") == 0) { *eventMaskPtr |= Button3Mask; } else if (strcmp(field, "Button4") == 0) { *eventMaskPtr |= Button4Mask; } else if (strcmp(field, "Button5") == 0) { *eventMaskPtr |= Button5Mask; } else if (strcmp(field, "Mod1") == 0) { *eventMaskPtr |= Mod1Mask; } else if (strcmp(field, "Mod2") == 0) { *eventMaskPtr |= Mod2Mask; } else if (strcmp(field, "Mod3") == 0) { *eventMaskPtr |= Mod3Mask; } else if (strcmp(field, "Mod4") == 0) { *eventMaskPtr |= Mod4Mask; } else if (strcmp(field, "Mod5") == 0) { *eventMaskPtr |= Mod5Mask; } #endif else break; } if (strcmp(field, "DragEnter") == 0) { *eventTypePtr = TKDND_DRAGENTER; } else if (strcmp(field, "DragLeave") == 0) { *eventTypePtr = TKDND_DRAGLEAVE; } else if (strcmp(field, "Drag") == 0) { *eventTypePtr = TKDND_DRAG; } else if (strcmp(field, "Drop") == 0) { *eventTypePtr = TKDND_DROP; } else if (strcmp(field, "Ask") == 0) { *eventTypePtr = TKDND_ASK; } else { *eventTypePtr = 0; goto error; } if (p[0] != '>' || p[1] != '\0') { goto error; } return TCL_OK; error: Tcl_SetResult(interp, (char*)"invalid event type \"", TCL_STATIC); Tcl_AppendResult(interp, eventStringPtr, "\"", (char *) NULL); return TCL_ERROR; } /* TkDND_ParseEventDescription */ /* *---------------------------------------------------------------------- * * TkDND_GetField -- (Laurent Riesterer 06/07/2000) * * Used to parse pattern descriptions. Copies up to * size characters from p to copy, stopping at end of * string, space, "-", ">", or whenever size is * exceeded. * * Results: * The return value is a pointer to the character just * after the last one copied (usually "-" or space or * ">", but could be anything if size was exceeded). * Also places NULL-terminated string (up to size * character, including NULL), at copy. * * Side effects: * None. * *---------------------------------------------------------------------- */ static char * TkDND_GetField( char *p, /* Pointer to part of pattern. */ char *copy, /* Place to copy field. */ int size) /* Maximum number of characters to copy. */ { #define UCHAR(c) ((unsigned char) (c)) while ((*p != '\0') && !isspace(UCHAR(*p)) && (*p != '>') && (*p != '-') && (size > 1)) { *copy = *p; p++; copy++; size--; } *copy = '\0'; while ((*p == '-') || isspace(UCHAR(*p))) { p++; } return p; } /* TkDND_GetField */ /* *---------------------------------------------------------------------- * TkDND_FindMatchingScript -- (Laurent Riesterer 06/07/2000) * * Find the closest matching script for the type handler * of the given window. * * Results: * A standard TCL result. * *---------------------------------------------------------------------- */ int TkDND_FindMatchingScript( Tcl_HashTable *table, /* Hash table containing the bindings if NULL, then *infoPtrPtr MUST contain the infoPtr */ char *windowPath, /* Name of window (hash key) */ char *typeStr, /* textual representation of type (NULL if not used) */ #ifdef __WIN32__ CLIPFORMAT typelist[], /* Search for this type */ #else Atom typelist[], /* Array for possibles matching types */ #endif unsigned long eventType, /* Type of event */ unsigned long eventMask, /* Mask of event */ int matchExactly, /* Not zero if need an exact match */ DndType **typePtrPtr, /* if not NULL, store DndType */ DndInfo **infoPtrPtr) /* if not NULL, store DndInfo */ { Tcl_HashEntry *hPtr; DndInfo *infoPtr; int found; if (typePtrPtr != NULL) *typePtrPtr = NULL; /* remove state we don't use */ eventMask = eventMask & (TKDND_MODS | TKDND_BUTTONS); if (table != NULL) { if (infoPtrPtr != NULL) *infoPtrPtr = NULL; hPtr = Tcl_FindHashEntry(table, windowPath); if (hPtr == NULL) { XDND_DEBUG2(" Cannot locate wanted widget '%s'\n", windowPath); if (infoPtrPtr != NULL) *infoPtrPtr = NULL; return TCL_OK; } infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); if (infoPtrPtr != NULL) { XDND_DEBUG2(" setting infoPtr = %p\n", infoPtr); *infoPtrPtr = infoPtr; } } else { if (infoPtrPtr != NULL) { infoPtr = *infoPtrPtr; } else { return TCL_OK; } } /* * First try to find and exact match */ found = TkDND_FindScript(infoPtr, typeStr, typelist, eventType, eventMask, typePtrPtr); if (found) { XDND_DEBUG(" -------------\n"); return TCL_OK; } else if (matchExactly) { if (infoPtr != NULL) { Tcl_SetResult(infoPtr->interp, (char*)"script not found", TCL_STATIC); } return TCL_ERROR; } /* * Remove modifiers */ if ((eventMask & ~TKDND_MODS) != eventMask) { XDND_DEBUG(" ---- no mods -------------\n"); found = TkDND_FindScript(infoPtr, typeStr, typelist, eventType, eventMask & ~TKDND_MODS, typePtrPtr); if (found) { return TCL_OK; } #ifdef DND_DEBUG } else { XDND_DEBUG(" ---- skipping no mods -------------\n"); #endif /* DND_DEBUG */ } /* * Remove buttons */ if (((eventMask & ~TKDND_BUTTONS) != eventMask) && ((eventMask & ~TKDND_BUTTONS) != (eventMask & ~TKDND_MODS))) { XDND_DEBUG(" ---- no buttons -------------\n"); found = TkDND_FindScript(infoPtr, typeStr, typelist, eventType, eventMask & ~TKDND_BUTTONS, typePtrPtr); if (found) { return TCL_OK; } #ifdef DND_DEBUG } else { XDND_DEBUG(" ---- skippinp no buttons -------------\n"); #endif /* DND_DEBUG */ } /* * Remove modifiers & buttons */ if ((eventMask != 0 && ((eventMask & ~TKDND_BUTTONS) != 0) && (eventMask & ~TKDND_MODS) != 0)) { XDND_DEBUG(" ---- no mods, no buttons -------------\n"); found = TkDND_FindScript(infoPtr, typeStr, typelist, eventType, 0, typePtrPtr); if (found) { return TCL_OK; } } else { #ifdef DND_DEBUG XDND_DEBUG(" ---- skipping no mods, no buttons ------------\n"); #endif /* DND_DEBUG */ } /* * Last chance: try to find if a Drop event is associated with the type * We indicate its only to set the desired type by resetting the infoPtr */ if ((eventType == TKDND_DRAGENTER || eventType == TKDND_DRAG) && !matchExactly) { XDND_DEBUG(" ---- recurse for DRAG_ENTER -------------\n"); TkDND_FindMatchingScript(table, windowPath, typeStr, typelist, TKDND_DROP, eventMask, False, typePtrPtr, infoPtrPtr); *infoPtrPtr = NULL; } XDND_DEBUG(" -------------\n"); /* if (!found && infoPtrPtr != NULL) { *infoPtrPtr = NULL; }*/ return TCL_OK; } /* TkDND_FindMatchingScript */ /* *---------------------------------------------------------------------- * TkDND_FindScript -- (Laurent Riesterer 06/07/2000) * * TODO: Laurent please add description... * * Results: * A standard TCL result. * *---------------------------------------------------------------------- */ static int TkDND_FindScript( DndInfo *infoPtr, char *typeStr, /* textual representation of type (NULL if not used) */ #ifdef __WIN32__ CLIPFORMAT typelist[], /* Search for this type */ #else Atom typelist[], /* Array for possibles matching types */ #endif unsigned long eventType, /* Type of event */ unsigned long eventMask, /* Mask of event */ DndType **typePtrPtr) /* if not NULL, store DndType */ { DndType *curr; int found = 0, i; char *AtomName, *formatName; AtomName = NULL; /* Avoid warnings under windows... */ i = 0; /* Avoid warnings under windows... */ #ifdef __WIN32__ XDND_DEBUG4(" start search: type=%s / event=%d / mask=%08X\n", typeStr, eventType, eventMask); #else /* __WIN32__ */ XDND_DEBUG4(" start search: type='%s' / type=%ld, mask=%08X\n" " list=", typeStr, eventType, (unsigned int) eventMask); #ifdef DND_DEBUG for (i = 0; typelist && typelist[i]; i++) { AtomName = TkDND_TypeToString(typelist[i]); XDND_DEBUG3(" Type[%d] = \"%s\"\n", i, AtomName); } #endif /* DND_DEBUG */ #endif /* __WIN32__ */ for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { curr->matchedType = 0; /* Test types */ if (typeStr != NULL) { XDND_DEBUG4(" for '%s', %ld / %08x\n", curr->typeStr, curr->eventType, (unsigned int) curr->eventMask); if (curr->eventType == eventType && curr->eventMask == eventMask && Tcl_StringCaseMatch(typeStr, curr->typeStr, 1)) { found = 1; break; } } else { #ifndef __WIN32__ #ifdef DND_DEBUG AtomName = ""; if (curr->type) AtomName = XGetAtomName(dnd->display, curr->type); XDND_DEBUG5(" prio=%3d / type='%-20s' / event=%2ld / " "mask=%08x\n", curr->priority, AtomName, curr->eventType, (unsigned int) curr->eventMask); if (curr->type) XFree(AtomName); #endif /* DND_DEBUG */ for (i = 0; typelist && typelist[i] != None; i++) { if (curr->eventType == eventType && curr->eventMask == eventMask) { if (curr->type == typelist[i]) { found = 1; break; } else if (curr->type == None) { /* * If the type is None is a signal that string matching is involved */ AtomName = (char *) Tk_GetAtomName(infoPtr->tkwin, typelist[i]); if (Tcl_StringCaseMatch(AtomName, curr->typeStr, 1)) { found = 1; curr->matchedType = typelist[i]; /* * Since now we have a match, perhaps we can select a type that * we know how to get the data? */ for (i = 0; typelist && typelist[i]; i++) { AtomName = (char *) Tk_GetAtomName(infoPtr->tkwin, typelist[i]); if (!strcmp(AtomName,"text/plain;charset=UTF-8") || !strcmp(AtomName,"text/plain") || !strcmp(AtomName,"STRING") || !strcmp(AtomName,"TEXT") || !strcmp(AtomName,"COMPOUND_TEXT") || !strcmp(AtomName,"CF_UNICODETEXT") || !strcmp(AtomName,"CF_TEXT") || !strcmp(AtomName,"CF_OEMTEXT") || !strcmp(AtomName,"text/uri-list") || !strcmp(AtomName,"text/file") || !strcmp(AtomName,"text/url") || !strcmp(AtomName,"url/url") || !strcmp(AtomName,"FILE_NAME") || !strcmp(AtomName,"SGI_FILE") || !strcmp(AtomName,"_NETSCAPE_URL") || !strcmp(AtomName,"_MOZILLA_URL") || !strcmp(AtomName,"_SGI_URL") || !strcmp(AtomName,"CF_HDROP") || !strcmp(AtomName,"CF_DIB")) { curr->matchedType = typelist[i]; break; } } /* for (i = 0; typelist && typelist[i]; i++) */ break; } } } } if (found) break; #else /* __WIN32__ */ for (i = 0; typelist && typelist[i]; i++) { if (curr->eventType == eventType && curr->eventMask == eventMask) { if (curr->type == typelist[i]) { found = 1; break; } else if (curr->type == 0) { /* * If the type is 0 is a signal that string matching is involved... */ formatName = TkDND_TypeToString(typelist[i]); if (Tcl_StringCaseMatch(formatName, curr->typeStr, 1)) { found = 1; curr->matchedType = typelist[i]; dnd->DesiredTypeStr = formatName; /* * Since now we have a match, perhaps we can select a type that * we know how to get the data? */ for (i = 0; typelist && typelist[i]; i++) { switch (typelist[i]) { /* Sorted according to preference */ case CF_UNICODETEXT: { curr->matchedType =typelist[i]; dnd->DesiredTypeStr =TkDND_TypeToString(typelist[i]);break;} case CF_TEXT: case CF_OEMTEXT: { /* Are we sure CF_UNICODETEXT is not supported? */ int j; for (j=0; typelist[j]; j++) { if (typelist[j] == CF_UNICODETEXT) {i = j; break;} } if (typelist[i] == CF_OEMTEXT) { /* CF_UNICODETEXT is not supported. Perhaps CF_TEXT is? */ for (j=0; typelist[j]; j++) { if (typelist[j] == CF_TEXT) {i = j; break;} } } curr->matchedType =typelist[i]; dnd->DesiredTypeStr =TkDND_TypeToString(typelist[i]);break;} case CF_HDROP: { curr->matchedType =typelist[i]; dnd->DesiredTypeStr =TkDND_TypeToString(typelist[i]);break;} case CF_DIB: { curr->matchedType =typelist[i]; dnd->DesiredTypeStr =TkDND_TypeToString(typelist[i]);break;} default: { if (typelist[i] == dnd->UniformResourceLocator || typelist[i] == dnd->FileName || typelist[i] == dnd->HTML_Format|| typelist[i] == dnd->RichTextFormat) { curr->matchedType =typelist[i]; dnd->DesiredTypeStr =TkDND_TypeToString(typelist[i]); break; } continue; } } break; } break; } } } } if (found) break; #endif /* __WIN32__ */ } } XDND_DEBUG2(" findmatching = %d\n", found); *typePtrPtr = curr; (void)AtomName; return found; } /* TkDND_FindScript */ /* *---------------------------------------------------------------------- * GetCurrentScript -- (Laurent Riesterer 06/07/2000) * * Set interp result with the current script for the type handler * of the given window. * * Results: * A standard TCL result. * *---------------------------------------------------------------------- */ int TkDND_GetCurrentScript(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask) { Tk_Window tkwin; DndType *typePtr; tkwin = Tk_NameToWindow(interp, windowPath, topwin); if (tkwin == NULL) { return TCL_ERROR; } if (TkDND_FindMatchingScript(table, windowPath, typeStr, NULL, eventType, eventMask, True, &typePtr, NULL) != TCL_OK) { return TCL_ERROR; } Tcl_SetResult(interp, typePtr->script, TCL_VOLATILE); return TCL_OK; } /* TkDND_GetCurrentScript */ /* * End of File. */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/generic/tkDND.cpp0000644000175000017500000014644111044115432023231 0ustar domibeldomibel/* * tkDND.c -- * * This file implements a drag&drop mechanish for the tk toolkit. * It contains the top-level command routines as well as some needed * functions for defining and removing bind scripts. * * This software is copyrighted by: * George Petasis, * Software and Knowledge Engineering Laboratory, * Institute of Informatics and Telecommunications, * National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * and * Laurent Riesterer, Rennes, France. * e-mail: laurent.riesterer@free.fr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. * * RCS: @(#) $Id: tkDND.cpp,v 1.10 2008-07-30 16:47:22 barre Exp $ */ #include "tkDND.h" /* * Global Variable Definitions... */ Tcl_HashTable TkDND_TargetTable; /* This table hold dnd target bindings... */ Tcl_HashTable TkDND_SourceTable; /* This table hold dnd source bindings... */ DndClass *TkDND_dnd = NULL; /* This structure holds platform specific information */ static int initialized = 0; /* > 0 if package is already initialised. */ static char TkDND_DescriptionStr[TKDND_MAX_DESCRIPTIONS_LENGTH]; /* * Forward declarations for procedures defined later in this file: */ /* * For C++ compilers, use extern "C" */ #ifdef __cplusplus extern "C" { #endif DLLEXPORT int Tkdnd_Init(Tcl_Interp *interp); DLLEXPORT int Tkdnd_SafeInit(Tcl_Interp *interp); void TkDND_DestroyEventProc(ClientData clientData, XEvent *eventPtr); #ifdef __cplusplus } #endif int TkDND_DndObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *CONST objv[]); void *TkDND_Init(Tcl_Interp *interp, Tk_Window topwin); int TkDND_AddHandler(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask, char *script, int isDropTarget, int priority); int TkDND_ParseEventDescription(Tcl_Interp *interp, char *eventStringPtr, unsigned long *eventTypePtr, unsigned long *eventMaskPtr); int TkDND_DelHandler(DndInfo *infoPtr, char *typeStr, unsigned long eventType, unsigned long eventMask); int TkDND_DelHandlerByName(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask); int TkDND_GetCurrentTypes(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath); char *TkDND_GetCurrentTypeName(void); char *TkDND_GetCurrentTypeCode(void); char *TkDND_GetCurrentActionName(void); int TkDND_GetCurrentButton(void); char *TkDND_GetCurrentModifiers(Tk_Window tkwin); char *TkDND_GetSourceActions(void); char *TkDND_GetSourceActionDescriptions(void); char *TkDND_GetSourceTypeList(void); char *TkDND_GetSourceTypeCodeList(void); char *TkDND_TypeToString(int type); int TkDND_DndDrag(Tcl_Interp *interp, char *windowPath, int button, Tcl_Obj *Actions, char *Descriptions, Tk_Window cursor_window, char *cursor_callback); int TkDND_ExecuteBinding(Tcl_Interp *interp, char *script, int numBytes, Tcl_Obj *data); char *TkDND_GetDataAccordingToType(DndInfo *info, Tcl_Obj *ResultObj, DndType *typePtr, int *length); int TkDND_GetDataFromImage(DndInfo *info, char *imageName, char *type, char **result, int *length); int TkDND_Update(Display *display, int idle); extern int TkDND_GetCurrentScript(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask); /* *---------------------------------------------------------------------- * * Tkdnd_Init -- * * Initialize the drag and drop package. * * Results: * A standard Tcl result * * Side effects: * "dnd" command is added into interpreter. * *---------------------------------------------------------------------- */ int DLLEXPORT Tkdnd_Init(Tcl_Interp *interp) { int major, minor, patchlevel; Tk_Window topwin; if (!initialized) { if ( #ifdef USE_TCL_STUBS Tcl_InitStubs(interp, "8.3", 0) #else Tcl_PkgRequire(interp, "Tcl", "8.3", 0) #endif /* USE_TCL_STUBS */ == NULL) { return TCL_ERROR; } if ( #ifdef USE_TK_STUBS Tk_InitStubs(interp, "8.3", 0) #else Tcl_PkgRequire(interp, "Tk", "8.3", 0) #endif /* USE_TK_STUBS */ == NULL) { return TCL_ERROR; } /* * Get the version, because we really need 8.3.3+. */ Tcl_GetVersion(&major, &minor, &patchlevel, NULL); if ((major == 8) && (minor == 3) && (patchlevel < 3)) { Tcl_SetResult(interp, (char*)"tkdnd requires Tk 8.3.3 or greater", TCL_STATIC); return TCL_ERROR; } Tcl_PkgProvide(interp, TKDND_PACKAGE, TKDND_VERSION); Tcl_InitHashTable(&TkDND_TargetTable, TCL_STRING_KEYS); Tcl_InitHashTable(&TkDND_SourceTable, TCL_STRING_KEYS); } topwin = Tk_MainWindow(interp); if (topwin == NULL) return TCL_ERROR; /* Create and Initilise the DnD structure... */ if (!initialized) { TkDND_dnd = (DndClass *) TkDND_Init(interp, topwin); if (TkDND_dnd == NULL) { return TCL_ERROR; } } /* Register the "dnd" Command */ if (Tcl_CreateObjCommand(interp, "dnd", (Tcl_ObjCmdProc*) TkDND_DndObjCmd, (ClientData) topwin, (Tcl_CmdDeleteProc *) NULL) == NULL) { return TCL_ERROR; } initialized = 1; return TCL_OK; } /* Tkdnd_Init */ int DLLEXPORT Tkdnd_SafeInit(Tcl_Interp *interp) { return Tkdnd_Init(interp); } /* Tkdnd_SafeInit */ /* *---------------------------------------------------------------------- * TkDND_DndObjCmd -- * * Drag and drop command. This has several forms. * * Results: * A standard TCL result. *---------------------------------------------------------------------- */ int TkDND_DndObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tk_Window topwin = (Tk_Window) clientData; Tk_Window tkwin, cursor_window = NULL; Tcl_Obj *Actions = NULL, **elem, *CursorCallbackObject = NULL; char *window, *action, *description, *Descriptions = TkDND_DescriptionStr, *ptr, *event, *cursor_callback = NULL; int button = 0, i, j, elem_nu, des_nu, des_len, index, status, priority; unsigned long eventType, eventMask; /* Laurent Riesterer 06/07/2000 */ static const char *Methods[] = { "aware", "bindsource", "bindtarget", "clearsource", "cleartarget", "drag", (char *) NULL }; enum methods { AWARE, BINDSOURCE, BINDTARGET, CLEARSOURCE, CLEARTARGET, DRAG }; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?"); return TCL_ERROR; } tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), topwin); if (tkwin == NULL) { return TCL_ERROR; } /* Handle Arguments... */ if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **) Methods, "method", 0, &index) != TCL_OK) return TCL_ERROR; switch ((enum methods) index) { case AWARE: { if (objc != 4 && objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window ?mime-type?"); return TCL_ERROR; } return TCL_OK; } case BINDSOURCE: { if (objc > 6) { Tcl_WrongNumArgs(interp, 2, objv, "window ?type ?script ?priority? ? ?"); return TCL_ERROR; } if (objc >= 4) { if (strchr(Tcl_GetString(objv[3]), '*') != NULL) { Tcl_SetResult(interp, (char*)"the character \"*\" should not be " "contained in the type of a drag source!", TCL_STATIC); return TCL_ERROR; } } if (objc == 3) { /* Return the registered types... */ return TkDND_GetCurrentTypes(interp, topwin, &TkDND_SourceTable, Tcl_GetString(objv[2])); } else if (objc == 4) { /* Return the script for the given type... */ return TkDND_GetCurrentScript(interp, topwin, &TkDND_SourceTable, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), TKDND_GETDATA, 0); } else if (objc == 5) { /* Bind a new handler... */ if (strlen(Tcl_GetString(objv[4])) > 0) { /* Add the new handler... */ return TkDND_AddHandler(interp, topwin, &TkDND_SourceTable, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), TKDND_GETDATA, 0, Tcl_GetString(objv[4]), 0, 50); } else { /* We got an empty string. Remove the handler... */ return TkDND_DelHandlerByName(interp, topwin, &TkDND_SourceTable, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), TKDND_GETDATA, 0); } } else if (objc == 6) { /* The priority... */ if (Tcl_GetIntFromObj(interp, objv[5], &priority) != TCL_OK) { return TCL_ERROR; } if (priority < 1) { priority = 1; } else if (priority > 100) { priority = 100; } if (strlen(Tcl_GetString(objv[4])) == 0) { Tcl_SetResult(interp, (char*)"when priority is specified an empty script " "is not permitted", TCL_STATIC); return TCL_ERROR; } /* Add the new handler... */ return TkDND_AddHandler(interp, topwin, &TkDND_SourceTable, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), TKDND_GETDATA, 0, Tcl_GetString(objv[4]), 0, priority); } } /* BINDSOURCE */ case BINDTARGET :{ if (objc > 7) { Tcl_WrongNumArgs(interp, 2, objv, "window ?type ?event ?script? ?priority? ? ?"); return TCL_ERROR; } if (objc == 3) { /* Return the registered types... */ return TkDND_GetCurrentTypes(interp, topwin, &TkDND_TargetTable, Tcl_GetString(objv[2])); } else if (objc == 4) { /* Return the script for the "" event... */ return TkDND_GetCurrentScript(interp, topwin, &TkDND_TargetTable, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), TKDND_DROP, 0); } else { event = Tcl_GetString(objv[4]); /* Laurent Riesterer 06/07/2000 */ if (TkDND_ParseEventDescription(interp, event, &eventType, &eventMask) != TCL_OK) { return TCL_ERROR; } /* XDND_DEBUG4(" parse result (%s) type = %2d, mask = %08x\n", event, eventType, eventMask); */ if (objc == 5) { /* Return the script for the specified event... */ return TkDND_GetCurrentScript(interp, topwin, &TkDND_TargetTable, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), eventType, eventMask); } else if (objc == 6) { /* Bind a new handler... */ if (strlen(Tcl_GetString(objv[5])) > 0) { /* Add the new handler... */ return TkDND_AddHandler(interp, topwin, &TkDND_TargetTable, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), eventType, eventMask, Tcl_GetString(objv[5]), 1, 50); } else { /* We got an empty string. Remove the handler... */ return TkDND_DelHandlerByName(interp, topwin, &TkDND_TargetTable, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), eventType, eventMask); } } else { /* The priority... */ if (Tcl_GetIntFromObj(interp, objv[6], &priority) != TCL_OK) { return TCL_ERROR; } if (priority < 1) { priority = 1; } else if (priority > 100) { priority = 100; } return TkDND_AddHandler(interp, topwin, &TkDND_TargetTable, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), eventType, eventMask, Tcl_GetString(objv[5]), 1, priority); } } } /* BINDTARGET */ case CLEARSOURCE: { if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); return TCL_ERROR; } return TkDND_DelHandlerByName(interp, topwin, &TkDND_SourceTable, Tcl_GetString(objv[2]), NULL, TKDND_SOURCE, 0); } /* CLEARSOURCE */ case CLEARTARGET: { if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); return TCL_ERROR; } return TkDND_DelHandlerByName(interp, topwin, &TkDND_TargetTable, Tcl_GetString(objv[2]), NULL, TKDND_TARGET, 0); } /* CLEARTARGET */ case DRAG: { if (objc != 3 && objc != 5 && objc != 7 && objc != 9 && objc != 11 && objc != 13) { Tcl_WrongNumArgs(interp, 2, objv, "window ?-button button? " "?-actions action-list? " "?-descriptions description-list? " "?-cursorwindow window? ?-callback script?"); return TCL_ERROR; } /* * Get window. This is a valid one, as we have already check it... */ window = Tcl_GetString(objv[2]); /* * Parse optional parameters... */ for (i = 3; i < objc; i += 2) { if (strncmp(Tcl_GetString(objv[i]), "-b", 2) == 0) { /* -button */ if (Tcl_GetIntFromObj(interp, objv[i+1], &button) != TCL_OK) { return TCL_ERROR; } } else if (strncmp(Tcl_GetString(objv[i]), "-cu", 3) == 0) { /* -cursor */ cursor_window = Tk_NameToWindow(interp, Tcl_GetString(objv[i+1]), topwin); if (cursor_window == NULL) { return TCL_ERROR; } } else if (strncmp(Tcl_GetString(objv[i]), "-ca", 3) == 0) { /* -callback */ CursorCallbackObject = objv[i+1]; Tcl_IncrRefCount(CursorCallbackObject); cursor_callback = Tcl_GetString(objv[i+1]); } else if (strncmp(Tcl_GetString(objv[i]), "-a", 2) == 0) { Actions = objv[i+1]; /* * Check the validity of actions. Valid actions are: * "copy", "move", "link", "ask", "private" */ status = Tcl_ListObjGetElements(interp, Actions, &elem_nu, &elem); if (status != TCL_OK) return status; if (elem_nu > 5) { Tcl_SetResult(interp, (char*)"too many actions specified: at most 5 are " "allowed, which must be from the following" " ones:\ncopy, move, link, ask, private", TCL_STATIC); if (CursorCallbackObject != NULL) Tcl_DecrRefCount(CursorCallbackObject); return TCL_ERROR; } for (j = 0; j < elem_nu; j++) { action = Tcl_GetString(elem[j]); if (strcmp(action, "copy") != 0 && strcmp(action, "move") != 0 && strcmp(action, "link") != 0 && strcmp(action, "ask" ) != 0 && strcmp(action, "private") != 0) { Tcl_SetResult(interp, (char*)"unknown action \"", TCL_STATIC); Tcl_AppendResult(interp, action, "\"!", (char *) NULL); if (CursorCallbackObject != NULL) Tcl_DecrRefCount(CursorCallbackObject); return TCL_ERROR; } } Tcl_IncrRefCount(Actions); } else if (strncmp(Tcl_GetString(objv[i]), "-d", 2) == 0) { if (Actions == NULL) { Tcl_SetResult(interp, (char*)"-actions option must be specified before " "the -descriptions options", TCL_STATIC); if (CursorCallbackObject != NULL) { Tcl_DecrRefCount(CursorCallbackObject); } return TCL_ERROR; } /* * Check the length of the descriptions... */ if (strlen(Tcl_GetString(objv[i+1])) >= TKDND_MAX_DESCRIPTIONS_LENGTH - 10) { Tcl_SetResult(interp, (char*)"the total length of descriptions cannot " "exceed " TKDND_MAX_DESCRIPTIONS_LENGTH_STR " characters", TCL_STATIC); if (CursorCallbackObject != NULL) { Tcl_DecrRefCount(CursorCallbackObject); } return TCL_ERROR; } /* * Get the descriptions... */ ptr = Descriptions; memset(ptr, '\0', TKDND_MAX_DESCRIPTIONS_LENGTH); status = Tcl_ListObjGetElements(interp, objv[i+1], &des_nu, &elem); if (status != TCL_OK) return status; if (elem_nu != des_nu) { Tcl_SetResult(interp, (char*)"description number must be equal to the " "action number, as they describe the actions.", TCL_STATIC); if (CursorCallbackObject != NULL) { Tcl_DecrRefCount(CursorCallbackObject); } return TCL_ERROR; } for (j = 0; j < elem_nu; j++) { description = Tcl_GetString(elem[j]); des_len = (int)strlen(description); memcpy(ptr, description, des_len+1); ptr += des_len+1; } *ptr = '\0'; } else { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "unknown option \"", Tcl_GetString(objv[i]), "\"", (char *) NULL); if (CursorCallbackObject != NULL) { Tcl_DecrRefCount(CursorCallbackObject); } return TCL_ERROR; } } status = TkDND_DndDrag(interp, Tcl_GetString(objv[2]), button, Actions, Descriptions, cursor_window, cursor_callback); if (Actions != NULL) Tcl_DecrRefCount(Actions); if (CursorCallbackObject != NULL) { Tcl_DecrRefCount(CursorCallbackObject); } return status; } /* DRAG */ } (void)window; return TCL_OK; } /* TkDND_DndObjCmd */ /* *---------------------------------------------------------------------- * * TkDND_DelHandler -- * * Delete a handler. Assumes everything has already been looked * up elsewhere * * Results: * A standard TCL results * *---------------------------------------------------------------------- */ int TkDND_DelHandler(DndInfo *infoPtr, char *typeStr, unsigned long eventType, unsigned long eventMask) { DndType *head, *prev, *curr, *next; int match; head = prev = &infoPtr->head; for (curr = head->next; curr != NULL; curr = next) { next = curr->next; match = 0; if ((typeStr == NULL) || (strcmp(curr->typeStr, typeStr) == 0)) { /* Modified by Laurent Riesterer 06/07/2000 */ if (eventType == TKDND_SOURCE || eventType == TKDND_TARGET || (curr->eventType == eventType && curr->eventMask == eventMask)) { match = 1; } if (match) { Tcl_Free(curr->typeStr); Tcl_Free(curr->script); prev->next = next; } } else { prev = curr; } } if (head->next == NULL) { #ifdef __WIN32__ if (infoPtr->DropTarget) { RevokeDragDrop(Tk_GetHWND(Tk_WindowId(infoPtr->tkwin))); } #endif /* __WIN32__ */ Tk_DeleteEventHandler(infoPtr->tkwin, StructureNotifyMask, TkDND_DestroyEventProc, (ClientData) infoPtr); Tcl_DeleteHashEntry(infoPtr->hashEntry); Tcl_Free((char *) infoPtr); } return TCL_OK; } /* TkDND_DelHandler */ /* *---------------------------------------------------------------------- * * TkDND_DelHandlerByName -- * * Remove a drag&drop handler window, freeing up any memory and objects * that need to be cleaned up. * * Arguments: * interp: Tcl interpreter * topwin: The main window * table: Hash table we are removing the window/type from * windowPath: String pathname of window * typeStr: The data type to remove. * eventType: Type of event to remove (Riesterer 06/07/2000) * eventMask: Mask of event to remove (Riesterer 06/07/2000) * * Results: * A standard Tcl result * * Notes: * The table that is passed in must have been initialized. * If type == NULL, then everything is cleaned up. * *---------------------------------------------------------------------- */ int TkDND_DelHandlerByName(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask) { Tcl_HashEntry *hPtr; Tk_Window tkwin; tkwin = Tk_NameToWindow(interp, windowPath, topwin); if (tkwin == NULL) return TCL_ERROR; hPtr = Tcl_FindHashEntry(table, windowPath); if (hPtr == NULL) return TCL_OK; return TkDND_DelHandler((DndInfo *)Tcl_GetHashValue(hPtr), typeStr, eventType, eventMask); } /* TkDND_DelHandlerByName */ /* *---------------------------------------------------------------------- * * TkDND_DestroyEventProc -- * * This routine gets called on events that match the StructureNotify * mask. We only care about DestroyNotify events. * * Results: * None * * Side Effects: * Removes the window from being either a source or a target. * *---------------------------------------------------------------------- */ void TkDND_DestroyEventProc(ClientData clientData, XEvent *eventPtr) { DndInfo *infoPtr = (DndInfo *) clientData; if (eventPtr->type == DestroyNotify) { /* XDND_DEBUG2("Deleting %s\n", Tk_PathName(infoPtr->tkwin)); */ /* Laurent Riesterer 06/07/2000 */ TkDND_DelHandler(infoPtr, NULL, TKDND_SOURCE, 0); /* XDND_DEBUG("done\n"); */ } } /* TkDND_DestroyEventProc */ /* *---------------------------------------------------------------------- * TkDND_GetCurrentTypes -- * * Append a list of the current types that are handled by the given * to the result. * * Results: * A standard TCL result. * *---------------------------------------------------------------------- */ int TkDND_GetCurrentTypes(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath) { Tcl_HashEntry *hPtr; DndInfo *infoPtr; Tk_Window tkwin; DndType *curr; if (interp == NULL) { return TCL_ERROR; } Tcl_ResetResult(interp); tkwin = Tk_NameToWindow(interp, windowPath, topwin); if (tkwin == NULL) { return TCL_ERROR; } hPtr = Tcl_FindHashEntry(table, windowPath); if (hPtr == NULL) { return TCL_OK; } infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { Tcl_AppendElement(interp, curr->typeStr); } return TCL_OK; } /* TkDND_GetCurrentTypes */ /* *---------------------------------------------------------------------- * * TkDND_ExpandPercents -- * * Given a command and an event, produce a new command * by replacing % constructs in the original command * with information from the drop event * * Results: * The new expanded command is appended to the dynamic string * given by dsPtr. * * Side effects: * None. * *-------------------------------------------------------------- */ void TkDND_ExpandPercents(DndInfo *infoPtr, DndType *typePtr, char *before, Tcl_DString *dsPtr, LONG x, LONG y) { /* Used to substitute string as proper Tcl list element. */ int spaceNeeded, cvtFlags; int number, length; register char *string; char numStorage[41]; int wx, wy, free_string = False; Tk_GetRootCoords(infoPtr->tkwin, &wx, &wy); while (1) { /* * Find everything up to the next % character and append it * to the result string. */ for (string = before; (*string != 0) && (*string != '%'); string++) { /* Empty loop body. */ } if (string != before) { Tcl_DStringAppend(dsPtr, before, (int)(string-before)); before = string; } if (*before == 0) break; /* * There's a percent sequence here. Process it. */ number = 0; string = (char*)"??"; switch (before[1]) { case 'A': if (typePtr->script == NULL && *typePtr->typeStr == '\0') { /* * This will only happen when we are processing the Cursor * callback fo a drag source window and the cursor is over * a window that does not supports dnd. So, return an empty * action... */ string = (char*)""; } else { string = TkDND_GetCurrentActionName(); } free_string = False; goto doString; case 'a': string = TkDND_GetSourceActions(); free_string = True; goto doString; case 'b': /* Laurent Riesterer 24/06/2000 */ number = TkDND_GetCurrentButton(); free_string = False; goto doNumber; case 'c': /* The list of supported by the source type codes */ string = TkDND_GetSourceTypeCodeList(); free_string = True; goto doString; case 'C': /* Type code */ string = TkDND_GetCurrentTypeCode(); free_string = True; goto doString; case 'D': /* * This is a special case. %D must be substituted by the * dropped data. We must leave it as %D. It will be * substituted during execution... */ string = (char*)"%D"; free_string = False; goto doString; case 'd': string = TkDND_GetSourceActionDescriptions(); free_string = True; goto doString; case 'm': /* Laurent Riesterer 24/06/2000 */ string = TkDND_GetCurrentModifiers(infoPtr->tkwin); free_string = True; goto doString; case 'T': /* string = typePtr->typeStr; */ string = TkDND_GetCurrentTypeName(); free_string = False; goto doString; case 't': /* The list of supported by the source types */ string = TkDND_GetSourceTypeList(); free_string = True; goto doString; case 'W': string = Tk_PathName(infoPtr->tkwin); free_string = False; goto doString; case 'X': number = x; free_string = False; goto doNumber; case 'x': /*if (! converted) { sPt.x = x; sPt.y = y; ScreenToClient(Tk_GetHWND(Tk_WindowId(infoPtr->tkwin)), &sPt); } number = sPt.x;*/ number = x - wx; free_string = False; goto doNumber; case 'Y': number = y; free_string = False; goto doNumber; case 'y': /*if (! converted) { sPt.x = x; sPt.y = y; ScreenToClient(Tk_GetHWND(Tk_WindowId(infoPtr->tkwin)), &sPt); } number = sPt.y;*/ number = y - wy; free_string = False; goto doNumber; default: numStorage[0] = before[1]; numStorage[1] = '\0'; string = numStorage; free_string = False; goto doString; } doNumber: sprintf(numStorage, "%d", number); string = numStorage; doString: spaceNeeded = Tcl_ScanElement(string, &cvtFlags); length = Tcl_DStringLength(dsPtr); Tcl_DStringSetLength(dsPtr, length + spaceNeeded); spaceNeeded = Tcl_ConvertElement(string, Tcl_DStringValue(dsPtr) + length, cvtFlags | TCL_DONT_USE_BRACES); Tcl_DStringSetLength(dsPtr, length + spaceNeeded); before += 2; if (free_string) Tcl_Free(string); } } /* TkDND_ExpandPercents */ /* *---------------------------------------------------------------------- * * TkDND_ExecuteBinding -- * * This function will execute a drop binding script and will insert * dropped data into the proper place in the script. It will arrange * so as the binary data to be passed as a byte-array object to tcl. * * Results: * The status of the execution... * * Side effects: * What ever the script does. * *-------------------------------------------------------------- */ int TkDND_ExecuteBinding(Tcl_Interp *interp, char *script, int numBytes, Tcl_Obj *objPtr) { Tcl_DString ds; char *start, *data_insert; int status; /* * Getting a NULL interp is for sure a bug in tkdnd, but at least * avoid the crash for now :-) * TODO: Find out why we get sometimes a NULL interp... */ if (interp == NULL) return TCL_ERROR; /* * Just a simple check. If %D is not in the script, just execute the * binding...don't try to execute */ status = TCL_OK; data_insert = strstr(script, "%D"); if (data_insert == NULL) { status = Tcl_EvalEx(interp, script, numBytes, TCL_EVAL_GLOBAL); } else { /* * Actually, here we have a small problem, if the objPtr holds * something in binary. Actually, this may be a bug of the Img * extension. We have somehow to convert the objPtr we have into an * object holding binary data. */ start = script; Tcl_DStringInit(&ds); if (objPtr) { (void) Tcl_GetByteArrayFromObj(objPtr, NULL); } while (data_insert != NULL) { Tcl_DStringAppend(&ds, start, (int)(data_insert-start)); if (objPtr == NULL) { Tcl_DStringAppend(&ds, "{}", 2); } else { #if 1 Tcl_DStringAppendElement(&ds, Tcl_GetString(objPtr)); #else /* * This solutions was proposed by Paul Duffin. We just add a * layer with "binary scan" to convert string to byte-array. */ Tcl_DStringAppend(&ds, "[::dnd::ConvertToBinary ", 24); Tcl_DStringAppendElement(&ds, Tcl_GetString(objPtr)); Tcl_DStringAppend(&ds, "]", 1); #endif } start = data_insert + 2; data_insert = strstr(start, "%D"); } if (*start != '\0') Tcl_DStringAppend(&ds, start, -1); status = Tcl_EvalEx(interp, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), TCL_EVAL_GLOBAL); Tcl_DStringFree(&ds); } return status; } /* TkDND_ExecuteBinding */ /* *---------------------------------------------------------------------- * * TkDND_GetDataAccordingToType -- * * This function will retrieve the data that the binding script * has placed into the given object. This will be done in a "clever" * way if the type is one that we know. On unkown types, the data will * be handled as binary data... * * Results: * The data in a newly allocated buffer. It must be freed with Tcl_Free * when we are done with it... * * Side effects: * - * *-------------------------------------------------------------- */ char *TkDND_GetDataAccordingToType(DndInfo *info, Tcl_Obj *ResultObj, DndType *typePtr, int *length) { Tcl_DString ds; char *data, *result, *type = typePtr->typeStr; /* * If the current DndType structure holds a "generic" type (i.e. a type * with wildcards or one of the cross-platform ones, Files, Text, Image), * we want to normalise this type into something meaningfull... */ if (strchr(type, '*') != NULL || strcmp(type, "Text") == 0 || strcmp(type, "Files") == 0 || strcmp(type, "Image") == 0) { type = TkDND_TypeToString(typePtr->matchedType); } #if 0 printf("TkDND_GetDataAccordingToType: Type=\"%s\"\n", type); #endif /* * Search the type for a known one... */ Tcl_DStringInit(&ds); if (strcmp(type, "text/plain;charset=UTF-8") == 0 || /* XDND */ strcmp(type, "CF_UNICODETEXT") == 0 ) { /* Windows */ /* ################################################################### * # text/plain;charset=UTF-8 * ################################################################### */ /* * We will transfer a string in "UTF-8"... */ data = Tcl_GetString(ResultObj); *length = (int)strlen(data); #ifdef __WIN32__ { LPWSTR buffer; int nWCharNeeded; /* * We will transfer a string in Unicode... */ /* * Tcl fails to convert our code to Unicode. Who knows why... */ #if 0 data = (char *) Tcl_WinUtfToTChar(data, -1, &ds); data = (char *) Tcl_UtfToUniCharDString(data, -1, &ds); *length = Tcl_DStringLength(&ds); #endif /* * Use directly windows functions to convert to Unicode from * UTF-8... */ /* Query the number of WChar required to store the Dest string */ nWCharNeeded = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) data, -1, NULL, 0); /* Allocate the required amount of space */ /* We need more 2 bytes for '\0' */ buffer = (LPWSTR) Tcl_Alloc(sizeof(char)*(nWCharNeeded+1)*2); /* Do the conversion */ nWCharNeeded = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) data, -1, (LPWSTR) buffer, nWCharNeeded); *(LPWSTR)((LPWSTR)buffer + nWCharNeeded) = L'\0'; /* MultiByteToWideChar returns # WCHAR, so multiply by 2 */ *length = 2*nWCharNeeded; Tcl_DStringFree(&ds); return (char *) buffer; } #endif /* __WIN32__ */ } else if (strcmp(type, "CF_OEMTEXT") == 0 ) { /* Windows */ /********************************************************************* * # CF_OEMTEXT (Windows specific format)... ********************************************************************* */ data = Tcl_GetString(ResultObj); data = Tcl_UtfToExternalDString(NULL, data, -1, &ds); /* Convert data to the system encoding... */ #ifdef __WIN32__ /* * We have to convert data to OEM code page... */ CharToOem((LPCTSTR) data, (LPSTR ) Tcl_DStringValue(&ds)); data = Tcl_DStringValue(&ds); #endif /* __WIN32__ */ *length = (int)strlen(data); } else if (strcmp(type, "text/plain") == 0 || /* XDND */ strcmp(type, "text/uri-list") == 0 || /* XDND */ strcmp(type, "text/file") == 0 || /* XDND */ strcmp(type, "url/url") == 0 || /* XDND */ strcmp(type, "STRING") == 0 || /* Motif */ strcmp(type, "TEXT") == 0 || /* Motif */ strcmp(type, "XA_STRING") == 0 || /* Motif */ strcmp(type, "FILE_NAME") == 0 || /* Motif */ strcmp(type, "CF_TEXT") == 0 || /* Windows */ strcmp(type, "CF_HDROP") == 0 || /* Windows */ strncmp(type, "text/", 5) == 0 ) { /* Who knows :-) */ /********************************************************************** * # text/plain and other ASCII textual formats... ********************************************************************** */ data = Tcl_GetString(ResultObj); /* Convert data to the system encoding... */ data = Tcl_UtfToExternalDString(NULL, data, -1, &ds); *length = Tcl_DStringLength(&ds); } else if (strcmp(type, "Images") == 0 || /* Cross Platform */ strcmp(type, "CF_DIB") == 0 ) { /* Windows */ /********************************************************************** * # Images... ********************************************************************** */ Tk_PhotoHandle tkImage; /* * Here, we mainly expect the name of a Tk image... */ tkImage = Tk_FindPhoto(info->interp, Tcl_GetString(ResultObj)); if (tkImage == NULL) { /* TODO: expect raw image data? What format? Img package loaded? * How to convert? :-) */ data = NULL; *length = 0; } TkDND_GetDataFromImage(info, Tcl_GetString(ResultObj), type, &result, length); Tcl_DStringFree(&ds); return result; } else { /********************************************************************** * # Anything else (Unhandled)... ********************************************************************** */ data = (char *) Tcl_GetByteArrayFromObj(ResultObj, length); } result = (char *) Tcl_Alloc(sizeof(char) * (*length)+2); if (result == NULL) { Tcl_DStringFree(&ds); *length = 0; return NULL; } memcpy(result, data, (*length)+2); XDND_DEBUG3("Final: \"%s\" (%d)\n", result, *length); /* Laurent, 9/7/2000 */ result[*length] = '\0'; Tcl_DStringFree(&ds); return result; } /* TkDND_GetDataAccordingToType */ /* *---------------------------------------------------------------------- * * TkDND_CreateDataObjAccordingToType -- * * This function will create a proper Tcl object from the data. * This will be done in a "clever" way if the type is one that we know. * On unkown types, the data will be placed on a byte array, just to be * sure... * Note that in parameter info we may have placed needed information in * order to properly translate the data. For example, for textual data * the encoding will be stored... (petasis, 03/01/2001) * * Results: * The data in a newly allocated Object. The reference count of the * object will be 0. The caller should be free the object when done * with it... * * Side effects: * - * *-------------------------------------------------------------- */ Tcl_Obj *TkDND_CreateDataObjAccordingToType(DndType *typePtr, void *info, unsigned char *data, int length) { Tcl_Encoding encoding; Tcl_DString ds; Tcl_Obj *result; char *conv_data, *element_start, *type = typePtr->typeStr; int i, end, element_number = 0; /* * If the current DndType structure holds a "generic" type (i.e. a type * with wildcards or one of the cross-platform ones, Files, Text, Image), * we want to normalise this type into something meaningfull... */ if (strchr(type, '*') != NULL || strcmp(type, "Text") == 0 || strcmp(type, "Files") == 0 || strcmp(type, "Image") == 0) { type = TkDND_TypeToString(typePtr->matchedType); } #if 0 /* * Print the received data. As it is very hard to find information about * how a specific application organises a list of data, printing it may help * us to gather such information... */ printf("TkDND_CreateDataObjAccordingToType: Type=\"%s\" length=%d:", type, length); for (i=0; i static int tkDND_ShapeObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_ResetResult(interp); if (objc<2) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?window arg ...?"); return TCL_ERROR; } (void)clientData; return TCL_OK; } /* tkShapeObjCmd */ int Shape_Init(Tcl_Interp *interp) { Tcl_CreateObjCommand(interp, "shape", tkDND_ShapeObjCmd, NULL, NULL); Tcl_SetVar(interp, "shape_version", "0.3", TCL_GLOBAL_ONLY); Tcl_SetVar(interp, "shape_patchLevel", "0.3a1", TCL_GLOBAL_ONLY); return Tcl_PkgProvide(interp, "shape", "0.3"); } /* Shape_Init */ /* * EOF */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/win/OleDND.cpp0000644000175000017500000022267211044115432022514 0ustar domibeldomibel/* * OleDND.cpp -- * * This file implements the windows portion of the drag&drop mechanish * for the tk toolkit. The protocol in use under windows is the * OLE protocol. Based on code wrote by Gordon Chafee. * * This software is copyrighted by: * George Petasis, National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * Laurent Riesterer, Rennes, France. * e-mail: laurent.riesterer@free.fr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ #include "vtkTcl.h" #include "vtkTk.h" #include #include #include "tkDND.h" #include "OleDND.h" #include extern Tcl_HashTable TkDND_TargetTable; extern Tcl_HashTable TkDND_SourceTable; extern DndClass *dnd; /* * For C++ compilers, use extern "C" */ #ifdef __cplusplus extern "C" { #endif void TkDND_DestroyEventProc(ClientData clientData, XEvent *eventPtr); #ifdef __cplusplus } #endif extern int TkDND_DelHandler(DndInfo *infoPtr, char *typeStr, char *eventStr, unsigned long eventType, unsigned long eventMask); extern int TkDND_DelHandlerByName(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask); extern int TkDND_FindMatchingScript(Tcl_HashTable *table, char *windowPath, char *typeStr, CLIPFORMAT typelist[], unsigned long eventType, unsigned long eventMask, int matchExactly, DndType **typePtrPtr, DndInfo **infoPtrPtr); extern int TkDND_GetCurrentTypes(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath); extern char *TkDND_GetSourceActions(void); extern void TkDND_ExpandPercents(DndInfo *infoPtr, DndType *typePtr, char *before, Tcl_DString *dsPtr, LONG x, LONG y); extern int TkDND_ExecuteBinding(Tcl_Interp *interp, char *script, int numBytes, Tcl_Obj *data); extern char *TkDND_GetDataAccordingToType(Tcl_Obj *ResultObj, DndType *typePtr, int *length); extern Tcl_Obj *TkDND_CreateDataObjAccordingToType(DndType *typePtr, void *info, unsigned char *data, int length); extern int TkDND_Update(Display *display, int idle); extern int TkDND_WidgetGetData(DndInfo *infoPtr, char **data, int *length, CLIPFORMAT type); extern char *TkDND_TypeToString(int type); static CLIPFORMAT TypeList[100]; static char MatchedTypeStr[256]; /***************************************************************************** *############################################################################ *# Drop Source Related Class. *############################################################################ ****************************************************************************/ /* *---------------------------------------------------------------------- * TkDND_DropSource::TkDND_DropSource * * Constructor *---------------------------------------------------------------------- */ TkDND_DropSource::TkDND_DropSource(DndInfo *info) { m_refCnt = 0; /* Reference count */ infoPtr = info; return; } /* TkDND_DropSource */ /* *---------------------------------------------------------------------- * TkDND_DropSource::~TkDND_DropSource * * Destructor *---------------------------------------------------------------------- */ TkDND_DropSource::~TkDND_DropSource(void) { return; } /* ~TkDND_DropSource */ /* *---------------------------------------------------------------------- * TkDND_DropSource::QueryInterface * * Does interface negotiation. IUnknown and IDropSource are * the supported interfaces. * * Arguments: * * REFIID riid A reference to the interface being queried. * LPVOID *ppvObj Out parameter to return a pointer to interface. * * Results: * NOERROR if interface is supported, E_NOINTERFACE if it is not * *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DropSource::QueryInterface(REFIID riid, LPVOID *ppv) { *ppv=NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDropSource)) { *ppv=(LPVOID)this; } if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } /* TkDND_DropSource::QueryInterface */ /* *---------------------------------------------------------------------- * TkDND_DropSource::AddRef * * Increment the reference count on the object as well as on * the unknown object this enumerator is linked to. * * Results: * The current reference count on the object. *---------------------------------------------------------------------- */ STDMETHODIMP_(ULONG) TkDND_DropSource::AddRef(void) { return ++m_refCnt; } /* TkDND_DropSource::AddRef */ /* *---------------------------------------------------------------------- * TkDND_DropSource::Release * * Decrement the reference count on the object as well as on * the unknown object this enumerator is linked to. If the * reference count becomes 0, the object is deleted. * * Results: * The current reference count on the object. *---------------------------------------------------------------------- */ STDMETHODIMP_(ULONG) TkDND_DropSource::Release(void) { m_refCnt--; if (m_refCnt == 0L) { delete this; return 0L; } return m_refCnt; } /* TkDND_DropSource::Release */ /* *---------------------------------------------------------------------- * TkDND_DropSource::QueryContinueDrag * * Determines whether a drag operation should continue * * Arguments: * fEscapePressed Was the escape key pressed? (in) * grfKeyState Identifies the present state of the modifier * keys on the keyboard (in) * * Result: * DRAGDROP_S_CANCEL to stop the drag, DRAGDROP_S_DROP to drop the * data where it is, or NOERROR to continue. * * Notes: * *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD keyState) { /* * If was pressed or an error has occured in any of our tcl * callbacks, cancel drag... */ if (fEscapePressed || dnd->CallbackStatus == TCL_ERROR) { return ResultFromScode(DRAGDROP_S_CANCEL); } /* * If mouse button initiated drag was released, request a drop... */ if ((dnd->button == 1 && !(keyState & MK_LBUTTON)) || (dnd->button == 2 && !(keyState & MK_MBUTTON)) || (dnd->button == 3 && !(keyState & MK_RBUTTON)) ) { return ResultFromScode(DRAGDROP_S_DROP); } return NOERROR; } /* TkDND_DropSource::QueryContinueDrag */ /* *---------------------------------------------------------------------- * TkDND_DropSource::GiveFeedback * * Enables a source application to provide cursor feedback during a * drag and drop operation. * * Arguments * dwEffect The DROPEFFECT returned from the most recent call * to IDropTarget::DragEnter or IDropTarget::DragOver * * Result: * DRAGDROP_S_USEDEFAULTCURSORS: OLE should use the default cursors * to provide feedback... *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DropSource::GiveFeedback(DWORD dwEffect) { POINT CursorPoint; int ret; Tcl_DString dString; DndInfo info; DndType type; /* * Get Mouse coordinates... */ GetCursorPos(&CursorPoint); /* * Get the desired action... */ if (dwEffect == DROPEFFECT_COPY) strcpy(dnd->DesiredAction, "copy"); else if (dwEffect == DROPEFFECT_MOVE) strcpy(dnd->DesiredAction, "move"); else if (dwEffect == DROPEFFECT_LINK) strcpy(dnd->DesiredAction, "link"); else if (dwEffect == DROPEFFECT_NONE) strcpy(dnd->DesiredAction, ""); else strcpy(dnd->DesiredAction, "private"); /* * If a cursor window is specified by the user, move it to follow cursor... */ if (dnd->CursorWindow != NULL) { if (dnd->x != CursorPoint.x || dnd->y != CursorPoint.y) { Tk_MoveToplevelWindow(dnd->CursorWindow, CursorPoint.x+10, CursorPoint.y); Tk_RestackWindow(dnd->CursorWindow, Above, NULL); } /* * Has also the user registered a Cursor Callback? */ if (dnd->CursorCallback != NULL) { info.tkwin = dnd->DraggerWindow; if (dnd->DesiredTypeStr == NULL) { type.typeStr = (char *) Tk_GetAtomName(info.tkwin, dnd->DesiredType); } else { type.typeStr = dnd->DesiredTypeStr; } type.script = ""; Tcl_DStringInit(&dString); TkDND_ExpandPercents(&info, &type, dnd->CursorCallback, &dString, CursorPoint.x, CursorPoint.y); ret = TkDND_ExecuteBinding(dnd->interp, Tcl_DStringValue(&dString), dnd->length, dnd->data); Tcl_DStringFree(&dString); if (ret == TCL_ERROR) { Tk_BackgroundError(dnd->interp); dnd->CallbackStatus = TCL_ERROR; } TkDND_Update(dnd->display, 0); } } dnd->x = CursorPoint.x; dnd->y = CursorPoint.y; return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS); } /* TkDND_DropSource::GiveFeedback */ /***************************************************************************** *############################################################################ *# Data object Related Class (needed by Drag Source for OLE DND)... *############################################################################ ****************************************************************************/ /* *---------------------------------------------------------------------- * TkDND_DataObject::TkDND_DataObject * * Constructor *---------------------------------------------------------------------- */ TkDND_DataObject::TkDND_DataObject(DndInfo *info) { DndType *curr; m_refCnt = 0; m_numTypes = 0; m_maxTypes = 0; m_typeList = NULL; infoPtr = info; /* * Get the supported platform specific types register for the window, and * register them in the data object, to make them available... */ for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { AddDataType(curr->type); } } /* TkDND_DataObject::TkDND_DataObject */ /* *---------------------------------------------------------------------- * TkDND_DataObject::~TkDND_DataObject * * Destructor *---------------------------------------------------------------------- */ TkDND_DataObject::~TkDND_DataObject(void) { if (m_numTypes > 0) { delete [] m_typeList; } } /* TkDND_DataObject::~TkDND_DataObject */ /* *---------------------------------------------------------------------- * TkDND_DataObject::QueryInterface * * Does interface negotiation. * * Arguments: * * REFIID riid A reference to the interface being queried. * LPVOID *ppvObj Out parameter to return a pointer to interface. * * Results: * NOERROR if interface is supported, E_NOINTERFACE if it is not * *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::QueryInterface(REFIID riid, LPVOID *ppv) { *ppv=NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDataObject)) { *ppv=(LPVOID)this; } if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } /* TkDND_DataObject::QueryInterface */ /* *---------------------------------------------------------------------- * TkDND_DataObject::AddRef * * Increment the reference count. *---------------------------------------------------------------------- */ STDMETHODIMP_(ULONG) TkDND_DataObject::AddRef() { return ++m_refCnt; } /* TkDND_DataObject::AddRef */ /* *---------------------------------------------------------------------- * TkDND_DataObject::Release * * Decrement the reference count, destroy if count reaches 0. *---------------------------------------------------------------------- */ STDMETHODIMP_(ULONG) TkDND_DataObject::Release() { m_refCnt--; if (m_refCnt == 0L) { delete this; return 0L; } return m_refCnt; } /* TkDND_DataObject::Release */ /* *---------------------------------------------------------------------- * TkDND_DataObject::GetData * * Gets the data into the storage medium if possible. *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::GetData(LPFORMATETC pFormatEtcIn, STGMEDIUM *pMedium) { HGLOBAL hMem; UINT i; Tcl_DString ds; char *data, *newStr; int length; /* * Is the requested format supported by our object? */ for (i = 0; i < m_numTypes; i++) { if (m_typeList[i].cfFormat == pFormatEtcIn->cfFormat) { if (pFormatEtcIn->tymed & TYMED_HGLOBAL) { break; } } } if (i == m_numTypes) { /* The requested format was not found... */ return ResultFromScode(DV_E_FORMATETC); } /* * Execute the Tcl binding to get the data that are to be dropped... */ if (!TkDND_WidgetGetData(infoPtr, &data, &length, pFormatEtcIn->cfFormat)) { return S_FALSE; } if (pFormatEtcIn->cfFormat == CF_HDROP) { /************************************************************************ * ###################################################################### * # CF_HDROP (text/uri-list) * ###################################################################### ***********************************************************************/ /* * Being a file drag source is something special... The data must be a * special structure that holds the file list of the files to be dropped... */ LPDROPFILES pDropFiles; Tcl_Obj *ObjResult, **File; Tcl_Interp *interp; int file_nu; /* * Forget what TkDND_WidgetGetData has returned, and access the interpreter * directly, in order to get the tcl list object... */ interp = dnd->interp; ObjResult = Tcl_GetObjResult(interp); Tcl_IncrRefCount(ObjResult); if (Tcl_ListObjGetElements(interp, ObjResult, &file_nu, &File) !=TCL_OK) { Tcl_DecrRefCount(ObjResult); return S_FALSE; } /* * We now have the file names in a tcl list object... * Allocate space for the DROPFILE structure plus the number of files * and one extra byte for final NULL terminator... */ hMem = GlobalAlloc(GHND|GMEM_SHARE, (DWORD) (sizeof(DROPFILES)+(_MAX_PATH)*file_nu+1)); if (hMem == NULL) { Tcl_DecrRefCount(ObjResult); return ResultFromScode(STG_E_MEDIUMFULL); } pDropFiles = (LPDROPFILES) GlobalLock(hMem); /* * Set the offset where the starting point of the file start.. */ pDropFiles->pFiles = sizeof(DROPFILES); /* * File contains wide characters? */ pDropFiles->fWide = FALSE; int CurPosition = sizeof(DROPFILES); for (int i=0; icfFormat == dnd->FileGroupDescriptor || pFormatEtcIn->cfFormat == dnd->FileGroupDescriptorW) { /************************************************************************ * ###################################################################### * # FileGroupDescriptor (text/uri-list, Files) * ###################################################################### ***********************************************************************/ /* We cannot easily support this format. We must have the *contents* of the file(s) to be transferred... */ return S_FALSE; } else if (pFormatEtcIn->cfFormat == CF_UNICODETEXT) { /************************************************************************ * ###################################################################### * # CF_UNICODETEXT (text/plain;charset=UTF-8) * ###################################################################### ***********************************************************************/ /* * TODO: Actually, this code is buggy :-) * I don't know how to pass utf-8 strings. Anybody?? */ //MessageBox(NULL, data, "Error", MB_OK); XDND_DEBUG2("UTF-8: allocating %d\n", length); hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, length+2); if (hMem == NULL) return ResultFromScode(STG_E_MEDIUMFULL); newStr = (char *) GlobalLock(hMem); lstrcpyW((LPWSTR) newStr, (LPWSTR) data); //MessageBox(NULL, Tcl_DStringValue(&ds), "Error", MB_OK); GlobalUnlock(hMem); } else if (pFormatEtcIn->cfFormat == CF_DIB) { /********************************************************************* * ################################################################### * # CF_DIB * ################################################################### ********************************************************************/ /* * In order to create a DIB, we must allocate a BITMAPINFO structure, * followed by the bitmap bits. The caller data should be a tk image... */ Tk_PhotoHandle photo; Tk_PhotoImageBlock block; HANDLE hDIB; BITMAPINFOHEADER *bmi; unsigned char *pData, *pixel; int x, y, lineSize; photo = Tk_FindPhoto(dnd->interp, data); if (photo == NULL) { /* * The data is not a Tk image. Pass them as is to the caller... */ length = lstrlen(data) + 1; hMem = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, length); if (hMem == NULL) return ResultFromScode(STG_E_MEDIUMFULL); newStr = (char *) GlobalLock(hMem); memcpy(newStr, data, length); GlobalUnlock(hMem); } else { Tk_PhotoGetImage(photo, &block); lineSize = ((block.width*3-1)/4+1)*4; hDIB = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(BITMAPINFOHEADER)+lineSize*block.height); if (hDIB == NULL) return ResultFromScode(STG_E_MEDIUMFULL); /* * Fill Header info... */ bmi = (BITMAPINFOHEADER *) GlobalLock (hDIB); if (bmi == NULL) { GlobalUnlock(hDIB); return ResultFromScode(STG_E_MEDIUMFULL); } bmi->biSize = sizeof(BITMAPINFOHEADER); bmi->biWidth = block.width; bmi->biHeight = block.height; bmi->biPlanes = 1; bmi->biBitCount = 24; /* We pass only 24-bit images */ bmi->biCompression = BI_RGB; /* none */ bmi->biSizeImage = 0; /* not calculated/needed */ bmi->biXPelsPerMeter = 0; bmi->biYPelsPerMeter = 0; bmi->biClrUsed = 0; /* * Fill the bitmap bits... */ pData = (unsigned char *) bmi + sizeof(BITMAPINFOHEADER); for (y=0; yhGlobal = hMem; pMedium->tymed = TYMED_HGLOBAL; pMedium->pUnkForRelease = NULL; return S_OK; } /* TkDND_DataObject::GetData */ /* *---------------------------------------------------------------------- * TkDND_DataObject::GetDataHere * * Not implemented and not necessary. *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::GetDataHere(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) { (void)pformatetc; (void)pmedium; return ResultFromScode(E_NOTIMPL); } /* TkDND_DataObject::GetDataHere */ /* *---------------------------------------------------------------------- * TkDND_DataObject::QueryGetData * * TODO: Needs to be implemented. *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::QueryGetData(LPFORMATETC pFormatEtcIn) { UINT i; for (i = 0; i < m_numTypes; i++) { if (m_typeList[i].cfFormat == pFormatEtcIn->cfFormat) { if (pFormatEtcIn->tymed & TYMED_HGLOBAL) { return S_OK; } } } return ResultFromScode(DV_E_FORMATETC); } /* TkDND_DataObject::QueryGetData */ /* *---------------------------------------------------------------------- * TkDND_DataObject::GetCanonicalFormatEtc * * Not implemented and not necessary. *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtcIn, LPFORMATETC pFormatEtcOut) { (void)pFormatEtcIn; (void)pFormatEtcOut; return ResultFromScode(E_NOTIMPL); } /* TkDND_DataObject::GetCanonicalFormatEtc */ /* *---------------------------------------------------------------------- * TkDND_DataObject::SetData * * Not implemented and not necessary. *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::SetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease) { (void)pFormatEtc; (void)pMedium; (void)fRelease; return ResultFromScode(E_NOTIMPL); } /* TkDND_DataObject::SetData */ /* *---------------------------------------------------------------------- * TkDND_DataObject::EnumFormatEtc * * Creates an enumerator. TODO *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC *ppEnumFormatEtc) { if (ppEnumFormatEtc == NULL) { return ResultFromScode(E_INVALIDARG); } if (dwDirection != DATADIR_GET) { *ppEnumFormatEtc = NULL; return ResultFromScode(E_NOTIMPL); } *ppEnumFormatEtc = CreateFormatEtcEnumerator(this, m_numTypes, m_typeList); if (*ppEnumFormatEtc == NULL) { return E_OUTOFMEMORY; } return S_OK; } /* TkDND_DataObject::EnumFormatEtc */ /* *---------------------------------------------------------------------- * TkDND_DataObject::DAdvise * * Not implemented and not necessary. *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::DAdvise(LPFORMATETC pFormatEtc, DWORD advf, LPADVISESINK pAdvSink, DWORD *pdwConnection) { (void)pFormatEtc; (void)advf; (void)pAdvSink; (void)pdwConnection; return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); } /* TkDND_DataObject::DAdvise */ /* *---------------------------------------------------------------------- * TkDND_DataObject::DUnadvise * * Not implemented and not necessary. *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::DUnadvise(DWORD dwConnection) { (void)dwConnection; return ResultFromScode(OLE_E_NOCONNECTION); } /* TkDND_DataObject::DUnadvise */ /* *---------------------------------------------------------------------- * TkDND_DataObject::EnumDAdvise * * Not implemented and not necessary. *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DataObject::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise) { (void)ppEnumAdvise; return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); } /* TkDND_DataObject::EnumDAdvise */ /* *---------------------------------------------------------------------- * TkDND_DataObject::AddDataType * * Add a data type to the list of types that are supported by * this instance of the TkDND_DataObject. * * Results: * TCL_OK if everything is OK. TCL_ERROR if not. * *---------------------------------------------------------------------- */ int TkDND_DataObject::AddDataType(UINT clipFormat) { FORMATETC *oldTypeList; UINT i; if (clipFormat == 0) { return TCL_ERROR; } /* * Is the requested format already in our table? */ for (i = 0; i < m_numTypes; i++) { if ((UINT)m_typeList[i].cfFormat == clipFormat) { return TCL_OK; } } /* * Is our array full? Move it to a larger array... */ if (m_maxTypes == m_numTypes) { m_maxTypes += 10; oldTypeList = m_typeList; m_typeList = new FORMATETC[m_maxTypes]; if (m_typeList == NULL) { return TCL_ERROR; } if (m_numTypes > 0) { for (i = 0; i < m_numTypes; i++) { m_typeList[i] = oldTypeList[i]; } delete [] oldTypeList; } } m_typeList[m_numTypes].cfFormat = clipFormat; m_typeList[m_numTypes].ptd = NULL; m_typeList[m_numTypes].dwAspect = DVASPECT_CONTENT; m_typeList[m_numTypes].lindex = -1; m_typeList[m_numTypes].tymed = TYMED_HGLOBAL; m_numTypes++; return TCL_OK; } /* TkDND_DataObject::AddDataType */ /* *---------------------------------------------------------------------- * TkDND_DataObject::DelDataType * * Remove a data type from the list of types that are supported by * this instance of the TkDND_DataObject. * * Results: * TCL_OK if the type was found in the list and was successfully removed. * TCL_ERROR if the type was not found. * *---------------------------------------------------------------------- */ int TkDND_DataObject::DelDataType(UINT clipFormat) { UINT i, j; if (clipFormat == 0) { return TCL_ERROR; } for (i = 0; i < m_numTypes; i++) { if ((UINT)m_typeList[i].cfFormat == clipFormat) { for (j = i; j < m_numTypes; j++) { m_typeList[j-1] = m_typeList[j]; } m_numTypes--; return TCL_OK; } } return TCL_OK; } /* TkDND_DataObject::DelDataType */ /***************************************************************************** *############################################################################ *# Drop Target Related Class. *############################################################################ ****************************************************************************/ /* *---------------------------------------------------------------------- * TkDND_DropTarget::TkDND_DropTarget * * Constructor *---------------------------------------------------------------------- */ TkDND_DropTarget::TkDND_DropTarget(DndInfo *info) { m_refCnt = 0; /* Reference count */ infoPtr = info; DataObject = NULL; #ifdef DND_ENABLE_DROP_TARGET_HELPER if (SUCCEEDED(DropHelper.CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER))) { UseDropHelper = 1; } else { UseDropHelper = 0; } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ return; } /* TkDND_DropTarget */ /* *---------------------------------------------------------------------- * TkDND_DropTarget::~TkDND_DropTarget * * Destructor *---------------------------------------------------------------------- */ TkDND_DropTarget::~TkDND_DropTarget(void) { if (DataObject != NULL) DataObject->Release(); return; } /* ~TkDND_DropTarget */ /* *---------------------------------------------------------------------- * TkDND_DropTarget::QueryInterface * * Does interface negotiation. IUnknown and IDropTarget are * the supported interfaces. * * Arguments: * * REFIID riid A reference to the interface being queried. * LPVOID *ppvObj Out parameter to return a pointer to interface. * * Results: * NOERROR if interface is supported, E_NOINTERFACE if it is not * *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DropTarget::QueryInterface(REFIID riid, LPVOID *ppv) { *ppv=NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDropTarget)) { *ppv=(LPVOID)this; } if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } /* TkDND_DropTarget::QueryInterface */ /* *---------------------------------------------------------------------- * TkDND_DropTarget::AddRef * * Increment the reference count on the object as well as on * the unknown object this enumerator is linked to. * * Results: * The current reference count on the object. *---------------------------------------------------------------------- */ STDMETHODIMP_(ULONG) TkDND_DropTarget::AddRef(void) { return ++m_refCnt; } /* AddRef */ /* *---------------------------------------------------------------------- * TkDND_DropTarget::Release * * Decrement the reference count on the object as well as on * the unknown object this enumerator is linked to. If the * reference count becomes 0, the object is deleted. * * Results: * The current reference count on the object. *---------------------------------------------------------------------- */ STDMETHODIMP_(ULONG) TkDND_DropTarget::Release(void) { m_refCnt--; if (m_refCnt == 0L) { delete this; return 0L; } return m_refCnt; } /* TkDND_DropTarget::Release */ /* *---------------------------------------------------------------------- * TkDND_DropTarget::DragEnter * * Determines whether the target window can accept the dragged object * and what effect the drop would have on the target window. * * Arguments: * pIDataObject An instance of the IDataObject interface through * which dragged data is accessible. (in) * grfKeyState Present state of keyboard modifiers (in) * pt Structure that holds mouse screen coordinates (in) * pdwEffect Points to where to return the effect of this * drag operation. * * Result: * S_OK if everything is OK. * *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DropTarget::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { IEnumFORMATETC *pEF; FORMATETC fetc; HRESULT hret; DndInfo *info; DndType *curr; char *formatName, *typeStringMatch = NULL; int i, j, found; #ifdef DND_DEBUG char name[1024]; int n; #endif /* DND_DEBUG */ XDND_DEBUG("############ ---- Drag Enter ---- ##############\n"); if (DataObject != NULL) DataObject->Release(); DataObject = NULL; XDND_DEBUG3("grfKeyState = 0x%08x -- KeyState = 0x%08x\n", grfKeyState, KeyState); KeyState = grfKeyState; dnd->CallbackStatus = TCL_OK; dnd->DraggerActions = *pdwEffect; dnd->x = pt.x; dnd->y = pt.y; fetc.ptd = NULL; fetc.dwAspect = DVASPECT_CONTENT; fetc.lindex = -1; fetc.tymed = TYMED_HGLOBAL; /* * Get one of the supported by the drag source actions... */ if (*pdwEffect & DROPEFFECT_COPY) strcpy(dnd->DesiredAction, "copy"); else if (*pdwEffect & DROPEFFECT_MOVE) strcpy(dnd->DesiredAction, "move"); else if (*pdwEffect & DROPEFFECT_LINK) strcpy(dnd->DesiredAction, "link"); else strcpy(dnd->DesiredAction, ""); /* * Iterate over all the types supported by the drag source... */ Tcl_DStringFree(&(dnd->DraggerTypes)); Tcl_DStringInit(&(dnd->DraggerTypes)); if (pIDataSource->EnumFormatEtc(DATADIR_GET, &pEF) == S_OK) { i = 0; TypeList[0] = 0; while (pEF->Next(1, &fetc, NULL) == S_OK) { if (pIDataSource->QueryGetData(&fetc) == S_OK) { /* Get the format name from windows */ formatName = TkDND_TypeToString(fetc.cfFormat); Tcl_DStringAppendElement(&(dnd->DraggerTypes), formatName); #ifdef DND_DEBUG XDND_DEBUG3("Checking for Drag source type: \"%s\" (0x%08x):\n", formatName, fetc.cfFormat); #endif /* DND_DEBUG */ /* Iterate over the types supported by the drop target... */ for (curr=infoPtr->head.next; i<99 && curr!=NULL;curr=curr->next) { if (curr->type == 0) { /* If the type is zero, then we should compare the strings with * string match... */ if (Tcl_StringCaseMatch(formatName, curr->typeStr, 1)) { for (found=0,j=0;j<=i;j++) if (TypeList[j]==fetc.cfFormat) { found = 1; break;} if (!found) { TypeList[i++] = fetc.cfFormat; /* Do not remove this, we don't have initialise the array */ TypeList[i]=0; } #ifdef DND_DEBUG XDND_DEBUG3(" Drop target type: \"%s\" (0x%08x): " "string match!\n", curr->typeStr, curr->type); #endif /* DND_DEBUG */ } } else if (curr->type == fetc.cfFormat) { for (found=0,j=0;j<=i;j++) if (TypeList[j]==fetc.cfFormat) { found = 1; break;} if (!found) { TypeList[i++] = fetc.cfFormat; /* Do not remove this, we don't have initialise the array */ TypeList[i]=0; } #ifdef DND_DEBUG XDND_DEBUG3(" Drop target type: \"%s\" (0x%08x): type equality!\n", curr->typeStr, curr->type); #endif /* DND_DEBUG */ } } } } pEF->Release(); } else { /* We failed to enumerate the drag source data object. Check what types of * the drop target are also supported by the drop source... */ for (i=0, curr=infoPtr->head.next; i<99 && curr!=NULL; curr=curr->next) { if (curr->type == 0) continue; fetc.cfFormat = curr->type; hret = pIDataSource->QueryGetData(&fetc); if (hret == S_OK) { for (found=0,j=0;j<=i;j++) if (TypeList[j]==fetc.cfFormat) { found = 1; break;} if (!found) TypeList[i++] = fetc.cfFormat; Tcl_DStringAppendElement(&(dnd->DraggerTypes), curr->typeStr); } #ifdef DND_DEBUG XDND_DEBUG3("Checking for type: \"%s\" (0x%08x): ", curr->typeStr, curr->type); if (hret == S_OK) { n = GetClipboardFormatName(fetc.cfFormat, name, sizeof(name)); XDND_DEBUG2("supported (%s)\n", n ? name : "???"); } else { XDND_DEBUG("not supported\n"); } #endif /* DND_DEBUG */ } /* for (curr = infoPtr->head.next;... */ } TypeList[i] = 0; dnd->DesiredTypeStr = ""; #ifdef DND_DEBUG XDND_DEBUG2("Checking done: %d types compatibles\n", i); for (j=0; TypeList && TypeList[j]; j++) { XDND_DEBUG4("Index=%d Type=\"%s\", Code=%d\n", j, TkDND_TypeToString(TypeList[j]), TypeList[j]); } XDND_DEBUG2("Drag Source Type List: %s\n", Tcl_DStringValue(&(dnd->DraggerTypes))); formatName = TkDND_GetSourceActions(); XDND_DEBUG2("Drag Source Action List: %s\n", formatName); Tcl_Free(formatName); #endif /* DND_DEBUG */ info = infoPtr; if (TkDND_FindMatchingScript(NULL, NULL, NULL, TypeList, TKDND_DRAGENTER, grfKeyState, False, &curr, &info) != TCL_OK) { dnd->CallbackStatus = TCL_ERROR; Tk_BackgroundError(infoPtr->interp); TkDND_Update(dnd->display, 0); return ResultFromScode(E_FAIL); } /* * Execute the binding... */ XDND_DEBUG3(": search result: info=%p, type=%p\n", info, curr); if (info != NULL && curr != NULL) { Tcl_Obj *dataObj = NULL; Tcl_DString dString; int ret; STGMEDIUM stgMedium; /* Memorize the parameters */ if (strcmp(dnd->DesiredAction,"copy")==0) *pdwEffect = DROPEFFECT_COPY; else if (strcpy(dnd->DesiredAction,"move")==0) *pdwEffect = DROPEFFECT_MOVE; else if (strcpy(dnd->DesiredAction,"link")==0) *pdwEffect = DROPEFFECT_LINK; else *pdwEffect = DROPEFFECT_COPY; dnd->DesiredType = curr->type; dnd->DesiredTypeStr = curr->typeStr; DataObject = pIDataSource; DataObject->AddRef(); if (dnd->DesiredType == 0) { strcpy(MatchedTypeStr, TkDND_TypeToString(dnd->DesiredType)); dnd->DesiredType = curr->matchedType; dnd->DesiredTypeStr = MatchedTypeStr; } /* * Try to retrieve the data to be dropped. */ stgMedium.tymed = TYMED_HGLOBAL; fetc.cfFormat = curr->type; if (pIDataSource->GetData(&fetc, &stgMedium) == S_OK) { char *str = (char *) GlobalLock(stgMedium.hGlobal); if (str != NULL) { dataObj = GetAndConvertData((IDataObject *) pIDataSource, curr, str, &fetc, &stgMedium); } GlobalUnlock(stgMedium.hGlobal); if (!stgMedium.pUnkForRelease) { GlobalFree(stgMedium.hGlobal); } } /* * Send the event... */ dnd->interp = infoPtr->interp; Tcl_DStringInit(&dString); TkDND_ExpandPercents(info, curr, curr->script, &dString, dnd->x,dnd->y); XDND_DEBUG2(": execute binding '%s'\n", Tcl_DStringValue(&dString)); if (dataObj != NULL) Tcl_IncrRefCount(dataObj); ret = TkDND_ExecuteBinding(dnd->interp, Tcl_DStringValue(&dString), -1, dataObj); if (dataObj != NULL) Tcl_DecrRefCount(dataObj); Tcl_DStringFree(&dString); if (ret == TCL_ERROR) { dnd->CallbackStatus = TCL_ERROR; Tk_BackgroundError(infoPtr->interp); TkDND_Update(dnd->display, 0); return ResultFromScode(E_FAIL); } *pdwEffect = ParseAction(); } else if (info == NULL && curr != NULL) { XDND_DEBUG(": no but a \n"); /* Supported type but no script for */ dnd->DesiredType = curr->type; dnd->DesiredTypeStr = curr->typeStr; DataObject = pIDataSource; DataObject->AddRef(); if (dnd->DesiredType == 0) { strcpy(MatchedTypeStr, TkDND_TypeToString(dnd->DesiredType)); dnd->DesiredType = curr->matchedType; dnd->DesiredTypeStr = MatchedTypeStr; } } else { /* * The data type is not supported by our target. No drop is allowed... */ XDND_DEBUG3(": Script not found, info=%p, type=%p\n", info,curr); dnd->DesiredType = -1; dnd->DesiredTypeStr = ""; *pdwEffect = DROPEFFECT_NONE; } #ifdef DND_ENABLE_DROP_TARGET_HELPER /* * If the is not rejected, try to call the IDropTargetHelper... */ if (UseDropHelper) { //IDataObject* pdo = pIDataSource->GetIDataObject(FALSE); DropHelper->DragEnter(Tk_GetHWND(Tk_WindowId(infoPtr->tkwin)), (IDataObject *) pIDataSource, (POINT*) &pt, *pdwEffect); } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ XDND_DEBUG(": returning\n"); (void)typeStringMatch; return S_OK; } /* TkDND_DropTarget::DragEnter */ /* *---------------------------------------------------------------------- * TkDND_DropTarget::DragOver * * Provides feedback to the user and to DoDragDrop about the state * of the drag operation within a drop target application. This * gets called when the mouse has moved within a window that was * already DragEnter'ed. * * Arguments: * grfKeyState Present state of the keyboard modifiers * pt Current mouse screen coordinates. * pdwEffect Points to where to return the effect of this * drag operation. * * Result: * S_OK * * Notes: * This routine is called on every WM_MOUSEMOVE, so it should be * quick. *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { DndInfo *info; DndType *curr; XDND_DEBUG("############ ---- Drag Over ---- ##############\n"); if (DataObject == NULL || dnd->DesiredType == (CLIPFORMAT)-1) { strcpy(dnd->DesiredAction, ""); *pdwEffect = DROPEFFECT_NONE; #ifdef DND_ENABLE_DROP_TARGET_HELPER if (UseDropHelper) { DropHelper->DragOver((POINT*) &pt, *pdwEffect); } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ return NOERROR; } XDND_DEBUG3("grfKeyState = 0x%08x -- KeyState = 0x%08x\n", grfKeyState, KeyState); KeyState = grfKeyState; dnd->x = pt.x; dnd->y = pt.y; /* Laurent Riesterer 06/07/2000: support for extended bindings */ info = infoPtr; if (TkDND_FindMatchingScript(NULL, NULL, NULL, TypeList, TKDND_DRAG, KeyState, False, &curr, &info) != TCL_OK) { dnd->CallbackStatus = TCL_ERROR; #ifdef DND_ENABLE_DROP_TARGET_HELPER if (UseDropHelper) { DropHelper->DragOver((POINT*) &pt, *pdwEffect); } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ Tk_BackgroundError(infoPtr->interp); TkDND_Update(dnd->display, 0); return ResultFromScode(E_FAIL); } /* * Execute the binding... */ if (info == NULL || curr == NULL) { /* * There is no binding for this event. Return the default action... */ if (strcmp(dnd->DesiredAction, "copy") == 0) { *pdwEffect = DROPEFFECT_COPY; } else if (strcmp(dnd->DesiredAction, "move") == 0) { *pdwEffect = DROPEFFECT_MOVE; } else if (strcmp(dnd->DesiredAction, "link") == 0) { *pdwEffect = DROPEFFECT_LINK; } else { *pdwEffect = DROPEFFECT_COPY; } XDND_DEBUG3(": Script not found, info=%p, type=%p\n", info, curr); } else { Tcl_Obj *dataObj = NULL; STGMEDIUM stgMedium; FORMATETC fetc; Tcl_DString dString; int ret; /* * Try to retrieve the data to be dropped. */ stgMedium.tymed = TYMED_HGLOBAL; fetc.ptd = NULL; fetc.dwAspect = DVASPECT_CONTENT; fetc.lindex = -1; fetc.tymed = TYMED_HGLOBAL; fetc.cfFormat = curr->type; if (DataObject->GetData(&fetc, &stgMedium) == S_OK) { char *str = (char *) GlobalLock(stgMedium.hGlobal); if (str != NULL) { dataObj = GetAndConvertData((IDataObject *) DataObject, curr, str, &fetc, &stgMedium); } GlobalUnlock(stgMedium.hGlobal); if (!stgMedium.pUnkForRelease) { GlobalFree(stgMedium.hGlobal); } } /* * Send the event... */ dnd->interp = infoPtr->interp; Tcl_DStringInit(&dString); TkDND_ExpandPercents(info, curr, curr->script, &dString, dnd->x,dnd->y); XDND_DEBUG2(": Executing (%s)\n", Tcl_DStringValue(&dString)); if (dataObj != NULL) Tcl_IncrRefCount(dataObj); ret = TkDND_ExecuteBinding(dnd->interp, Tcl_DStringValue(&dString), -1, dataObj); if (dataObj != NULL) Tcl_DecrRefCount(dataObj); Tcl_DStringFree(&dString); if (ret == TCL_ERROR) { dnd->CallbackStatus = TCL_ERROR; Tk_BackgroundError(infoPtr->interp); TkDND_Update(dnd->display, 0); return ResultFromScode(E_FAIL); } *pdwEffect = ParseAction(); } #ifdef DND_ENABLE_DROP_TARGET_HELPER if (UseDropHelper) { DropHelper->DragOver((POINT*) &pt, *pdwEffect); } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ return NOERROR; } /* TkDND_DropTarget::DragOver */ /* *---------------------------------------------------------------------- * TkDND_DropTarget::DragLeave * * This method is called when the mouse leaves the area of a given * target while a drag is in progress or when the drag operation is * canceled. Causes the drop target to remove its feedback. * * Arguments: * None * * Result: * Result from Callback *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DropTarget::DragLeave(void) { DndInfo *info; DndType *curr; XDND_DEBUG("############ ---- Drag Leave ---- ##############\n"); #ifdef DND_ENABLE_DROP_TARGET_HELPER if (UseDropHelper) { DropHelper->DragLeave(); } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ if (DataObject == NULL || dnd->DesiredType == (CLIPFORMAT)-1) { strcpy(dnd->DesiredAction, ""); return NOERROR; } XDND_DEBUG2("grfKeyState = ---------- -- KeyState = 0x%08x\n", KeyState); /* Laurent Riesterer 06/07/2000: support for extended bindings */ info = infoPtr; if (TkDND_FindMatchingScript(NULL, NULL, NULL, TypeList, TKDND_DRAGLEAVE, KeyState, False, &curr, &info) != TCL_OK) { dnd->CallbackStatus = TCL_ERROR; Tk_BackgroundError(infoPtr->interp); TkDND_Update(dnd->display, 0); DataObject->Release(); DataObject = NULL; return ResultFromScode(E_FAIL); } /* * Execute the binding... */ if (info == NULL || curr == NULL) { XDND_DEBUG3(": Script not found, info=%p, type=%p\n", infoPtr, curr); } else { Tcl_Obj *dataObj = NULL; STGMEDIUM stgMedium; FORMATETC fetc; Tcl_DString dString; int ret; /* * Try to retrieve the data to be dropped. */ stgMedium.tymed = TYMED_HGLOBAL; fetc.ptd = NULL; fetc.dwAspect = DVASPECT_CONTENT; fetc.lindex = -1; fetc.tymed = TYMED_HGLOBAL; fetc.cfFormat = curr->type; if (DataObject->GetData(&fetc, &stgMedium) == S_OK) { char *str = (char *) GlobalLock(stgMedium.hGlobal); if (str != NULL) { dataObj = GetAndConvertData((IDataObject *) DataObject, curr, str, &fetc, &stgMedium); } GlobalUnlock(stgMedium.hGlobal); if (!stgMedium.pUnkForRelease) { GlobalFree(stgMedium.hGlobal); } } /* * Send the event... */ dnd->interp = infoPtr->interp; Tcl_DStringInit(&dString); TkDND_ExpandPercents(info, curr, curr->script, &dString, dnd->x, dnd->y); XDND_DEBUG2(": Executing (%s)\n", Tcl_DStringValue(&dString)); if (dataObj != NULL) Tcl_IncrRefCount(dataObj); ret = TkDND_ExecuteBinding(dnd->interp, Tcl_DStringValue(&dString), -1, dataObj); if (dataObj != NULL) Tcl_DecrRefCount(dataObj); Tcl_DStringFree(&dString); if (ret == TCL_ERROR) { dnd->CallbackStatus = TCL_ERROR; Tk_BackgroundError(infoPtr->interp); TkDND_Update(dnd->display, 0); DataObject->Release(); DataObject = NULL; return ResultFromScode(E_FAIL); } } DataObject->Release(); DataObject = NULL; return NOERROR; } /* TkDND_DropTarget::DragLeave */ /* *---------------------------------------------------------------------- * TkDND_DropTarget::Drop * * Drops the source data, indicated by pIDataSource, on this target * application. * * Arguments: * pIDataSource Object through which the data is accessible. * grfKeyState Current keyboard/mouse state. * pt Mouse screen coordinates * pdwEffect Action that took place is stored here * * Result: * Result from Callback *---------------------------------------------------------------------- */ STDMETHODIMP TkDND_DropTarget::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { DndInfo *info; DndType *curr; XDND_DEBUG("############ ---- Drop ---- ##############\n"); if (DataObject == NULL || dnd->DesiredType == (CLIPFORMAT)-1) { strcpy(dnd->DesiredAction, ""); *pdwEffect = DROPEFFECT_NONE; #ifdef DND_ENABLE_DROP_TARGET_HELPER if (UseDropHelper) { DropHelper->Drop((IDataObject *) pIDataSource, (POINT*) &pt, *pdwEffect); } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ return ResultFromScode(E_FAIL); } /* the grfKeyState has the button release : we need to "reinject" it in order to correctly match the bindings */ grfKeyState |= (dnd->button == 1 ? MK_LBUTTON : dnd->button == 2 ? MK_MBUTTON : dnd->button == 3 ? MK_RBUTTON : 0); XDND_DEBUG3("grfKeyState = 0x%08x -- KeyState = 0x%08x\n", grfKeyState, KeyState); /* Laurent Riesterer 06/07/2000: support for extended bindings */ info = infoPtr; if (TkDND_FindMatchingScript(NULL, NULL, NULL, TypeList, TKDND_DROP, grfKeyState, False, &curr, &info) != TCL_OK) { dnd->CallbackStatus = TCL_ERROR; Tk_BackgroundError(infoPtr->interp); TkDND_Update(dnd->display, 0); *pdwEffect = DROPEFFECT_NONE; DataObject->Release(); DataObject = NULL; #ifdef DND_ENABLE_DROP_TARGET_HELPER if (UseDropHelper) { DropHelper->Drop((IDataObject *) pIDataSource, (POINT*) &pt, *pdwEffect); } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ return ResultFromScode(E_FAIL); } #ifdef DND_ENABLE_DROP_TARGET_HELPER if (UseDropHelper) { DropHelper->Drop((IDataObject *) pIDataSource, (POINT*) &pt, *pdwEffect); } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ /* * Execute the binding... */ XDND_DEBUG3("Ready to retrieve the data: Type= \"%s\" (0x%08x)\n", dnd->DesiredTypeStr, dnd->DesiredType); if (info == NULL || curr == NULL) { XDND_DEBUG3(": Script not found, info=%p, type=%p\n", infoPtr, curr); } else { FORMATETC fetc; HRESULT hret; STGMEDIUM stgMedium; UINT type; Tcl_Obj *dataObj = NULL; Tcl_DString dString; char *str; int ret; /* * Time to get the data from the data object... */ if (curr->type) type = curr->type; else type = curr->matchedType; fetc.cfFormat = type; fetc.ptd = NULL; fetc.dwAspect = DVASPECT_CONTENT; fetc.lindex = -1; fetc.tymed = TYMED_HGLOBAL; stgMedium.tymed = TYMED_HGLOBAL; if (type != (UINT)dnd->DesiredType) { /* * We have a script for another type, that best fits the current * buttons/modifiers. Is the type supported by the drag source? */ fetc.cfFormat = type; hret = pIDataSource->QueryGetData(&fetc); if (hret != S_OK) { fetc.cfFormat = dnd->DesiredType; } else { dnd->DesiredTypeStr = curr->typeStr; dnd->DesiredType = type; } } hret = pIDataSource->GetData(&fetc, &stgMedium); if (hret != S_OK) { *pdwEffect = DROPEFFECT_NONE; DataObject->Release(); DataObject = NULL; #ifdef DND_ENABLE_DROP_TARGET_HELPER if (UseDropHelper) { DropHelper->Drop((IDataObject *) pIDataSource, (POINT*) &pt,*pdwEffect); } #endif /* DND_ENABLE_DROP_TARGET_HELPER */ return ResultFromScode(E_FAIL); } /* * Dropped Data will be pointed by str... */ str = (char *) GlobalLock(stgMedium.hGlobal); /************************************************************************ * ###################################################################### * # Make the necessary data convertions... * ###################################################################### ***********************************************************************/ if (str != NULL) { dataObj = GetAndConvertData((IDataObject *) pIDataSource, curr, str, &fetc, &stgMedium); } GlobalUnlock(stgMedium.hGlobal); if (!stgMedium.pUnkForRelease) { GlobalFree(stgMedium.hGlobal); } /* * Send the event... */ dnd->interp = infoPtr->interp; Tcl_DStringInit(&dString); TkDND_ExpandPercents(info, curr, curr->script, &dString, dnd->x, dnd->y); if (dataObj != NULL) Tcl_IncrRefCount(dataObj); XDND_DEBUG2(": Executing (%s)\n", Tcl_DStringValue(&dString)); ret = TkDND_ExecuteBinding(dnd->interp, Tcl_DStringValue(&dString), -1, dataObj); Tcl_DStringFree(&dString); if (dataObj != NULL) Tcl_DecrRefCount(dataObj); if (ret == TCL_ERROR) { dnd->CallbackStatus = TCL_ERROR; *pdwEffect = DROPEFFECT_NONE; DataObject->Release(); DataObject = NULL; Tk_BackgroundError(infoPtr->interp); TkDND_Update(dnd->display, 0); return ResultFromScode(E_FAIL); } } *pdwEffect = DROPEFFECT_NONE; DataObject->Release(); DataObject = NULL; (void)pt; return NOERROR; } /* TkDND_DropTarget::Drop */ /* *---------------------------------------------------------------------- * TkDND_DropTarget::GetAndConvertData * * Gets the data to be dropped from the data source object and tries to * convert it into something we can understand. * * Arguments: * pIDataSource Object through which the data is accessible. * grfKeyState Current keyboard/mouse state. * pt Mouse screen coordinates * pdwEffect Action that took place is stored here * * Result: * A Tcl object holding the converted data. Must be freed by the * caller. *---------------------------------------------------------------------- */ Tcl_Obj *TkDND_DropTarget::GetAndConvertData(LPDATAOBJECT pIDataSource, DndType *curr, char *str, FORMATETC *fetc, STGMEDIUM *stgMedium) { Tcl_Obj *dataObj = NULL; Tcl_DString dString; HRESULT hret; char *s, *ip, *op; int len; void *loc; Tcl_DStringInit(&dString); /********************************************************************* * ################################################################### * # CF_TEXT & CF_OEMTEXT * ################################################################### ********************************************************************/ if (dnd->DesiredType == CF_TEXT || dnd->DesiredType == CF_OEMTEXT) { int locale; Tcl_DString ds; Tcl_DStringInit(&ds); len = (int)strlen(str) + 1; s = (char *) Tcl_Alloc(sizeof(char) * len); memcpy(s, str, len); /* * Can we retrieve locale information from our object? */ loc = NULL; if (dnd->DesiredType == CF_TEXT) { fetc->cfFormat = CF_LOCALE; hret = pIDataSource->QueryGetData(fetc); if (hret == S_OK) { hret = pIDataSource->GetData(fetc, stgMedium); if (hret != S_OK) { char *data; Tcl_DStringAppend(&ds, "cp######", -1); data = (char *) GlobalLock(stgMedium->hGlobal); locale = LANGIDFROMLCID(*((int*)data)); GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, Tcl_DStringValue(&ds)+2, Tcl_DStringLength(&ds)-2); GlobalUnlock(stgMedium->hGlobal); loc = Tcl_DStringValue(&ds); } } } else { Tcl_DStringAppend(&ds, "cp######", -1); locale = GetSystemDefaultLCID(); GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, Tcl_DStringValue(&ds)+2, Tcl_DStringLength(&ds)-2); loc = Tcl_DStringValue(&ds); } for (ip = str, op = s; *ip != 0; ) { if (*ip == '\r') { if (ip[1] != '\n') { *op++ = '\n'; } ip++; } else { *op++ = *ip++; } } *op = 0; Tcl_DStringAppend(&dString, s, -1); Tcl_Free(s); curr->matchedType = dnd->DesiredType; dataObj = TkDND_CreateDataObjAccordingToType(curr, loc, (unsigned char *) Tcl_DStringValue(&dString), Tcl_DStringLength(&dString)); curr->matchedType = 0; Tcl_DStringFree(&ds); } else if (dnd->DesiredType == CF_UNICODETEXT) { /********************************************************************* * ################################################################### * # CF_UNICODETEXT * ################################################################### ********************************************************************/ curr->matchedType = dnd->DesiredType; dataObj = TkDND_CreateDataObjAccordingToType(curr, NULL, (unsigned char*) str, lstrlenW((LPCWSTR) str)); curr->matchedType = 0; } else if (dnd->DesiredType == CF_HDROP) { /* Handle files drop... */ /********************************************************************* * ################################################################### * # CF_HDROP * ################################################################### ********************************************************************/ Tcl_DString ds; HDROP hDrop = (HDROP) str; char szFile[_MAX_PATH], *p; UINT cFiles = DragQueryFile(hDrop, 0xFFFFFFFF, szFile, _MAX_PATH); UINT i; Tcl_DStringInit(&ds); for (i = 0; i < cFiles; ++i) { DragQueryFile(hDrop, i, szFile, _MAX_PATH); /* * Convert to forward slashes for easier access in scripts... */ for (p=szFile; *p!='\0'; p=(char *) CharNext(p)) { if (*p == '\\') *p = '/'; } Tcl_DStringAppendElement(&dString, szFile); } /* * Can we retrieve locale information from our object? */ fetc->cfFormat = CF_LOCALE; loc = NULL; hret = pIDataSource->QueryGetData(fetc); if (hret == S_OK) { hret = pIDataSource->GetData(fetc, stgMedium); if (hret != S_OK) { char *data; int locale; Tcl_DStringAppend(&ds, "cp######", -1); data = (char *) GlobalLock(stgMedium->hGlobal); locale = LANGIDFROMLCID(*((int*)data)); GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, Tcl_DStringValue(&ds)+2, Tcl_DStringLength(&ds)-2); GlobalUnlock(stgMedium->hGlobal); loc = Tcl_DStringValue(&ds); } } curr->matchedType = dnd->DesiredType; dataObj = TkDND_CreateDataObjAccordingToType(curr, loc, (unsigned char*) Tcl_DStringValue(&dString), Tcl_DStringLength(&dString)); curr->matchedType = 0; Tcl_DStringFree(&ds); } else if (dnd->DesiredType == dnd->FileGroupDescriptor) { /********************************************************************* * ################################################################### * # FileGroupDescriptor * ################################################################### ********************************************************************/ LPFILEGROUPDESCRIPTOR fileGroupDescrPtr = (LPFILEGROUPDESCRIPTOR) str; FILEDESCRIPTOR fileDescrPtr; UINT i; Tcl_Obj *elements[2], *element; dataObj = Tcl_NewListObj(0, NULL); /* * The result of the drop will be a list of elements. Each element * will be also a list of two elements: * 1) The file name. * 2) The file contents as a binary object. */ for (i = 0; i < fileGroupDescrPtr->cItems; ++i) { fileDescrPtr = fileGroupDescrPtr->fgd[i]; elements[0] = Tcl_NewStringObj(fileDescrPtr.cFileName, -1); elements[1] = Tcl_NewObj(); element = Tcl_NewListObj(2, elements); Tcl_ListObjAppendElement(dnd->interp, dataObj, element); } } else if (dnd->DesiredType == dnd->FileGroupDescriptorW) { /********************************************************************* * ################################################################### * # FileGroupDescriptorW * ################################################################### ********************************************************************/ LPFILEGROUPDESCRIPTORW fileGroupDescrPtr = (LPFILEGROUPDESCRIPTORW) str; LPFILEDESCRIPTORW fileDescrPtr; UINT i; Tcl_Obj *elements[2], *element; dataObj = Tcl_NewListObj(0, NULL); /* * The result of the drop will be a list of elements. Each element * will be also a list of two elements: * 1) The file name. * 2) The file contents as a binary object. */ for (i = 0; i < fileGroupDescrPtr->cItems; ++i) { if (i == 0) { fileDescrPtr = &(fileGroupDescrPtr->fgd[0]); } else { ++fileDescrPtr; } elements[0] = Tcl_NewUnicodeObj((const Tcl_UniChar *) fileDescrPtr->cFileName, -1); elements[1] = Tcl_NewObj(); element = Tcl_NewListObj(2, elements); Tcl_ListObjAppendElement(dnd->interp, dataObj, element); } } else if (dnd->DesiredType == CF_DIB) { /********************************************************************* * ################################################################### * # CF_DIB * ################################################################### ********************************************************************/ /* * A memory object containing a BITMAPINFO structure followed by * the bitmap bits. */ LPBITMAPINFO bmi = (LPBITMAPINFO) str; Tk_PhotoHandle photo; Tk_PhotoImageBlock block; unsigned char *pixelPtr; char *pColor; unsigned char *pData; long width, height, bpp, colors; int x, y, index, lineSize; /* * Read Header... */ if (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) || (bmi->bmiHeader.biCompression != BI_RGB && bmi->bmiHeader.biCompression != BI_BITFIELDS) ) { char tmp_str[128]; sprintf(tmp_str, "Unsupported bitmap format (%d)!", bmi->bmiHeader.biCompression); dataObj = Tcl_NewStringObj(tmp_str, -1); } else { width = bmi->bmiHeader.biWidth; height = bmi->bmiHeader.biHeight; bpp = bmi->bmiHeader.biBitCount; colors = bmi->bmiHeader.biClrUsed; /* * Create a new photo image... */ if (Tcl_Eval(infoPtr->interp, "image create photo") != TCL_OK) { return NULL; } dataObj = Tcl_GetObjResult(infoPtr->interp); Tcl_IncrRefCount(dataObj); photo = Tk_FindPhoto(infoPtr->interp, Tcl_GetString(dataObj)); if (width != 0 && height != 0) { Tk_PhotoExpand( #ifdef HAVE_TCL85 infoPtr->interp, #endif photo, width, (height>0) ? height: -height); block.width = width; block.height = 1; block.pitch = width*3; block.pixelSize = 3; /* Have DIBs transparency? */ block.offset[0] = 2; block.offset[1] = 1; block.offset[2] = 0; block.offset[3] = block.offset[0]; lineSize = ((width*(bpp/8)-1)/4+1)*4; pColor = (char *) ((LPSTR)bmi + (WORD)(bmi->bmiHeader.biSize)); pData = (unsigned char *) pColor + sizeof(RGBQUAD) * colors; if (bmi->bmiHeader.biCompression == BI_RGB) { /* * Uncompressed. If height is positive, the bitmap is a * bottom-up DIB and its origin is the lower-left corner. If * height is negative, the bitmap is a top-down DIB and its * origin is the upper-left corner. Note that each 3-byte triplet * in the bitmap array represents the relative intensities of * blue, green, and red, respectively, for a pixel. */ switch (bpp) { case 24: { for (y=0; y 0) { Tk_PhotoPutBlock( #ifdef HAVE_TCL85 infoPtr->interp, #endif photo, &block, 0, height-y-1, width, 1, TK_PHOTO_COMPOSITE_OVERLAY); } else { Tk_PhotoPutBlock( #ifdef HAVE_TCL85 infoPtr->interp, #endif photo, &block, 0, y, width, 1, TK_PHOTO_COMPOSITE_OVERLAY); } } break; } case 8: { /* * We have to look up pixels in the indexed palette... */ block.pixelPtr = pixelPtr = (unsigned char *) ckalloc(3*width); for(y=0; y 0) { Tk_PhotoPutBlock( #ifdef HAVE_TCL85 infoPtr->interp, #endif photo, &block, 0, height-y-1, width, 1, TK_PHOTO_COMPOSITE_OVERLAY); } else { Tk_PhotoPutBlock( #ifdef HAVE_TCL85 infoPtr->interp, #endif photo, &block, 0, y, width, 1, TK_PHOTO_COMPOSITE_OVERLAY); } pixelPtr = block.pixelPtr; } ckfree((char *) block.pixelPtr); break; } case 4: { /* * We have to look up pixels in the indexed palette... */ block.pixelPtr = pixelPtr = (unsigned char *) ckalloc(3*width); for(y=0; y> 4; } memcpy(pixelPtr, pColor+(4*index),3); pixelPtr += 3; } if (height > 0) { Tk_PhotoPutBlock( #ifdef HAVE_TCL85 infoPtr->interp, #endif photo, &block, 0, height-y-1, width, 1, TK_PHOTO_COMPOSITE_OVERLAY); } else { Tk_PhotoPutBlock( #ifdef HAVE_TCL85 infoPtr->interp, #endif photo, &block, 0, y, width, 1, TK_PHOTO_COMPOSITE_OVERLAY); } pixelPtr = block.pixelPtr; } ckfree((char *) block.pixelPtr); break; } case 1: { /* * Black and White image. We have to look up pixels in the * indexed palette... */ block.pixelPtr = pixelPtr = (unsigned char *) ckalloc(3*width); for(y=0; y> (7-(x%8))) & 1; memcpy(pixelPtr, pColor+(4*index),3); pixelPtr += 3; } if (height > 0) { Tk_PhotoPutBlock( #ifdef HAVE_TCL85 infoPtr->interp, #endif photo, &block, 0, height-y-1, width, 1, TK_PHOTO_COMPOSITE_OVERLAY); } else { Tk_PhotoPutBlock( #ifdef HAVE_TCL85 infoPtr->interp, #endif photo, &block, 0, y, width, 1, TK_PHOTO_COMPOSITE_OVERLAY); } pixelPtr = block.pixelPtr; } ckfree((char *) block.pixelPtr); break; } default: { char tmp_str[128]; sprintf(tmp_str, "Unsupported Bitmap bits per pixel (%d)!", bpp); dataObj = Tcl_NewStringObj(tmp_str, -1); } } /* switch (bpp) */ } else if (bmi->bmiHeader.biCompression == BI_BITFIELDS) { /* * Specifies that the bitmap is not compressed and that the color * table consists of three DWORD color masks that specify the * red, green, and blue components, respectively, of each pixel. * This is valid when used with 16- and 32-bit-per-pixel bitmaps. */ dataObj = Tcl_NewStringObj("Unsupported bitmap format (BI_BITFIELDS)!", -1); } } } } else { /********************************************************************* * ################################################################### * # UNHANDLED :-) * ################################################################### ********************************************************************/ XDND_DEBUG2("Unhandled Data type \"%s\"\n", dnd->DesiredTypeStr); curr->matchedType = dnd->DesiredType; dataObj = TkDND_CreateDataObjAccordingToType(curr, NULL, (unsigned char*) str, (int)strlen(str)); curr->matchedType = 0; } Tcl_DStringFree(&dString); return dataObj; }; /* TkDND_DropTarget::GetAndConvertData */ /* *---------------------------------------------------------------------- * * ParseAction -- (Laurent Riesterer 06/07/2000) * * Analyze the result of a script to find the requested action * * Results: * True if OK / False else. * *---------------------------------------------------------------------- */ DWORD TkDND_DropTarget::ParseAction(void) { DWORD wanted_action; static char *Actions[] = { "none", "default", "copy", "move", "link", "ask", "private", (char *) NULL }; enum actions {NONE, DEFAULT, COPY, MOVE, LINK, ASK, PRIVATE}; int index; XDND_DEBUG2("<>: Wanted Action = '%s'\n", Tcl_GetStringResult(dnd->interp)); if (Tcl_GetIndexFromObj(infoPtr->interp, Tcl_GetObjResult(infoPtr->interp), (CONST84 char **) Actions, "action", 0, &index) == TCL_OK) { switch ((enum actions) index) { case NONE: { strcpy(dnd->DesiredAction, "none"); dnd->CallbackStatus = TCL_BREAK; return DROPEFFECT_NONE; } case DEFAULT: { if (strcmp(dnd->DesiredAction, "copy") == 0) { wanted_action = DROPEFFECT_COPY; } else if (strcmp(dnd->DesiredAction, "move") == 0) { wanted_action = DROPEFFECT_MOVE; } else if (strcmp(dnd->DesiredAction, "link") == 0) { wanted_action = DROPEFFECT_LINK; } else { wanted_action = DROPEFFECT_COPY; } break; } case COPY: { strcpy(dnd->DesiredAction, "copy"); wanted_action = DROPEFFECT_COPY; break; } case MOVE: { strcpy(dnd->DesiredAction, "move"); wanted_action = DROPEFFECT_MOVE; break; } case LINK: { strcpy(dnd->DesiredAction, "link"); wanted_action = DROPEFFECT_LINK; break; } case ASK: { strcpy(dnd->DesiredAction, "copy"); wanted_action = DROPEFFECT_COPY; break; } case PRIVATE: { strcpy(dnd->DesiredAction, "copy"); wanted_action = DROPEFFECT_COPY; break; } default: { strcpy(dnd->DesiredAction, "none"); wanted_action = DROPEFFECT_NONE; } } } else { strcpy(dnd->DesiredAction, "none"); wanted_action = DROPEFFECT_NONE; } /* * Is the action returned by the script supported by the drag * source? */ if (dnd->DraggerActions & wanted_action) { return wanted_action; } strcpy(dnd->DesiredAction, "none"); return DROPEFFECT_NONE; } /* TkDND_DropTarget::ParseAction */ /* * OleDND.cpp: EOF */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/win/OleDND.h0000644000175000017500000002067710562164011022163 0ustar domibeldomibel/* * tkOleDND.cpp -- * * This file implements the windows portion of the drag&drop mechanish * for the tk toolkit. The protocol in use under windows is the * OLE protocol. Based on code wrote by Gordon Chafee. * * This software is copyrighted by: * George Petasis, National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * Laurent Riesterer, Rennes, France. * e-mail: laurent.riesterer@free.fr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ #ifndef _OLE_DND_H #define _OLE_DND_H #include "vtkTcl.h" #include "vtkTk.h" #include #include #ifdef DND_ENABLE_DROP_TARGET_HELPER #include #include /* for IDropTargetHelper */ #include /* We need this declaration for CComPtr, which uses __uuidof() */ struct __declspec(uuid("{4657278B-411B-11d2-839A-00C04FD918D0}")) IDropTargetHelper; #endif /* DND_ENABLE_DROP_TARGET_HELPER */ #include #include #include "tkDND.h" #include "tkOleDND_TEnumFormatEtc.h" #ifdef DND_DEBUG extern FILE *TkDND_Log; #endif typedef struct _OLEDND_Struct { Tk_Window MainWindow; /* The main window of our application */ Tcl_Interp *interp; /* A Tcl Interpreter */ Display *display; /* Display Pointer */ int x; /* Current position of the mouse */ int y; /* Current position of the mouse */ int button; /* Current button used for drag operation */ Tk_Window CursorWindow; /* A window to replace cursor */ char * CursorCallback; /* A Callback to update cursor window */ Tk_Window DraggerWindow; /* Window of the drag source */ DWORD DraggerActions; /* Actions supported by the drag source */ Tcl_DString DraggerTypes; /* The list of types of the drag source */ CLIPFORMAT DesiredType; /* The drop desired type */ char *DesiredTypeStr; /* The drop desired type (string) */ char DesiredAction[10]; /* The drop desired action */ int CallbackStatus; /* The return value of last tcl callback */ Tcl_Obj *data; /* The object contained data to be dropped */ int length; /* length of the data */ /* Some useful CLIPFORMATS... */ CLIPFORMAT UniformResourceLocator; /* Netscape, IE */ CLIPFORMAT FileName; /* Windows Explorer */ CLIPFORMAT HTML_Format; /* Word, IE */ CLIPFORMAT RichTextFormat; /* Word, IE */ CLIPFORMAT FileGroupDescriptor; /* Explorer, files not in the file */ CLIPFORMAT FileGroupDescriptorW; /* system */ } OleDND; #define DndClass OleDND /***************************************************************************** * Drop Source Related Class. ****************************************************************************/ class TkDND_DropSource: public IDropSource { private: ULONG m_refCnt; /* Reference count */ DndInfo *infoPtr; /* Pointer to hash table entry */ public: TkDND_DropSource(DndInfo *infoPtr); ~TkDND_DropSource(void); /* IUnknown interface members */ STDMETHODIMP QueryInterface(REFIID, LPVOID *); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); /* IDropSource interface members */ STDMETHODIMP QueryContinueDrag(BOOL, DWORD); STDMETHODIMP GiveFeedback(DWORD); }; /* TkDND_DropSource */ /***************************************************************************** * Data object Related Class (needed by Drag Source for OLE DND)... ****************************************************************************/ class TkDND_DataObject: public IDataObject { private: ULONG m_refCnt; /* Reference Count */ DndInfo *infoPtr; /* Pointer to hash table entry */ /* The clipboard formats that can be handled */ UINT m_numTypes; /* Number of types in list */ UINT m_maxTypes; /* Number of types that fit */ FORMATETC *m_typeList; /* List of types */ public: TkDND_DataObject(DndInfo *infoPtr); ~TkDND_DataObject(void); /* IUnknown interface members */ STDMETHODIMP QueryInterface(REFIID, LPVOID *); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); /* IDataObject interface methods */ STDMETHODIMP GetData(LPFORMATETC, LPSTGMEDIUM); STDMETHODIMP GetDataHere(LPFORMATETC, LPSTGMEDIUM); STDMETHODIMP QueryGetData(LPFORMATETC); STDMETHODIMP GetCanonicalFormatEtc(LPFORMATETC, LPFORMATETC); STDMETHODIMP SetData(LPFORMATETC, LPSTGMEDIUM, BOOL); STDMETHODIMP EnumFormatEtc(DWORD, LPENUMFORMATETC *); STDMETHODIMP DAdvise(LPFORMATETC, DWORD, LPADVISESINK, DWORD *); STDMETHODIMP DUnadvise(DWORD); STDMETHODIMP EnumDAdvise(IEnumSTATDATA **); /* TkDND additional interface methods */ int AddDataType(UINT clipFormat); int DelDataType(UINT clipFormat); }; /* TkDND_DataObject */ /***************************************************************************** * Drop Target Related Class. ****************************************************************************/ class TkDND_DropTarget; typedef class TkDND_DropTarget *PTDropTarget; class TkDND_DropTarget: public IDropTarget { private: ULONG m_refCnt; /* Reference count */ DndInfo *infoPtr; /* Pointer to hash table entry */ DWORD KeyState; /* Remember KeyState for */ LPDATAOBJECT DataObject; /* Keep data object available */ #ifdef DND_ENABLE_DROP_TARGET_HELPER CComPtr DropHelper; /* IDropTargetHelper support. This helper does some interesting things, like drawing explorer icons during drops... */ int UseDropHelper; /* A flag whether to use the helper or not... */ #endif /* DND_ENABLE_DROP_TARGET_HELPER */ public: TkDND_DropTarget(DndInfo *info); ~TkDND_DropTarget(void); /* IUnknown interface members */ STDMETHODIMP QueryInterface(REFIID, LPVOID *); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); /* IDropTarget interface members */ STDMETHODIMP DragEnter(LPDATAOBJECT, DWORD, POINTL,LPDWORD); STDMETHODIMP DragOver(DWORD, POINTL, LPDWORD); STDMETHODIMP DragLeave(void); STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD); /* TkDND additional interface methods */ DWORD ParseAction(void); Tcl_Obj *GetAndConvertData(LPDATAOBJECT, DndType *, char *, FORMATETC *, STGMEDIUM *); }; /* TkDND_DropTarget */ #endif _OLE_DND_H kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/win/tkOleDND_TEnumFormatEtc.h0000644000175000017500000000335510562163641025441 0ustar domibeldomibel/* *---------------------------------------------------------------------- * File: tenumformatetc.h * * This file defines the TEnumFormatEtc, an enerator class for the * IEnumFORMATETC object. The IEnumFORMATETC object has the standard * enumerator interface. The only creation oddity it has it the * IUnknown interface it takes as its first parameter. This allows * the object to increase the reference count of the object that is * being enumerated. Only after this enumerator is destroyed can the * object that created it be destroyed. This object should only be * created by the IDataObject::EnumFormatEtc function. *---------------------------------------------------------------------- */ #ifndef _TENUMFORMATETC_H_ #define _TENUMFORMATETC_H_ class TEnumFormatEtc; typedef class TEnumFormatEtc *PTEnumFormatEtc; class TEnumFormatEtc: public IEnumFORMATETC { private: ULONG m_refCnt; /* Reference count */ LPUNKNOWN m_pUnknownObj; /* IUnknown for ref counting */ ULONG m_currElement; /* Current element */ ULONG m_numFormats; /* Number of FORMATETCs in us */ LPFORMATETC m_formatList; /* List of formats */ public: TEnumFormatEtc(LPUNKNOWN, ULONG, LPFORMATETC); ~TEnumFormatEtc(void); /* IUnknown members */ STDMETHODIMP QueryInterface(REFIID, LPVOID *); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); /* IEnumFORMATETC members */ STDMETHODIMP Next(ULONG, LPFORMATETC, ULONG *); STDMETHODIMP Skip(ULONG); STDMETHODIMP Reset(void); STDMETHODIMP Clone(IEnumFORMATETC **); }; extern LPENUMFORMATETC CreateFormatEtcEnumerator(LPUNKNOWN, ULONG, LPFORMATETC); #endif /* _TENUMFORMATETC_H_ */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/win/tkOleDND.cpp0000644000175000017500000011455111044115433023050 0ustar domibeldomibel/* * tkOleDND.cpp -- * * This file implements the windows portion of the drag&drop mechanish * for the tk toolkit. The protocol in use under windows is the * OLE protocol. Based on code wrote by Gordon Chafee. * * This software is copyrighted by: * George Petasis, National Centre for Scientific Research "Demokritos", * Aghia Paraskevi, Athens, Greece. * e-mail: petasis@iit.demokritos.gr * Laurent Riesterer, Rennes, France. * e-mail: laurent.riesterer@free.fr * * The following terms apply to all files associated * with the software unless explicitly disclaimed in individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ #include "vtkTcl.h" #include "vtkTk.h" #include #include #include "tkDND.h" #include "OleDND.h" #ifndef CF_DIBV5 /* this is only in the latest Windows headers */ #define CF_DIBV5 17 #endif extern Tcl_HashTable TkDND_TargetTable; extern Tcl_HashTable TkDND_SourceTable; #ifdef DND_DEBUG FILE *TkDND_Log; #endif DndClass *dnd; /* * For C++ compilers, use extern "C" */ #ifdef __cplusplus extern "C" { #endif void TkDND_DestroyEventProc(ClientData clientData, XEvent *eventPtr); #ifdef __cplusplus } #endif extern int TkDND_DelHandler(DndInfo *infoPtr, char *typeStr, char *eventStr, unsigned long eventType, unsigned long eventMask); extern int TkDND_DelHandlerByName(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask); extern int TkDND_FindMatchingScript(Tk_Window tkwin, Tcl_HashTable *table, char *windowPath, char *typeStr, CLIPFORMAT type, unsigned long eventType, unsigned long eventMask, int matchExactly, DndType **typePtrPtr, DndInfo **infoPtrPtr); extern int TkDND_GetCurrentTypes(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath); extern void TkDND_ExpandPercents(DndInfo *infoPtr, DndType *typePtr, char *before, Tcl_DString *dsPtr, LONG x, LONG y); extern int TkDND_ExecuteBinding(Tcl_Interp *interp, char *script, int numBytes, Tcl_Obj *data); extern char *TkDND_GetDataAccordingToType(DndInfo *info, Tcl_Obj *ResultObj, DndType *typePtr, int *length); extern Tcl_Obj *TkDND_CreateDataObjAccordingToType(char *type, unsigned char *data, int length); extern int TkDND_Update(Display *display, int idle); #ifdef TKDND_ENABLE_SHAPE_EXTENSION int Shape_Init(Tcl_Interp *interp); #endif /* TKDND_ENABLE_SHAPE_EXTENSION */ /* *---------------------------------------------------------------------- * * TkDND_TypeToString -- * * Returns a string corresponding to the given type atom. * * Results: * A string in a static memory area holding the string. * Should never be freed or modified. * * Side effects: * - * *---------------------------------------------------------------------- */ char *TkDND_TypeToString(int type) { static char typeName[256]; strcpy(typeName, ""); switch (type) { case CF_TEXT : {strcpy(typeName, "CF_TEXT"); break;} case CF_BITMAP : {strcpy(typeName, "CF_BITMAP"); break;} case CF_METAFILEPICT : {strcpy(typeName, "CF_METAFILEPICT"); break;} case CF_SYLK : {strcpy(typeName, "CF_SYLK"); break;} case CF_DIF : {strcpy(typeName, "CF_DIF"); break;} case CF_TIFF : {strcpy(typeName, "CF_TIFF"); break;} case CF_OEMTEXT : {strcpy(typeName, "CF_OEMTEXT"); break;} case CF_DIB : {strcpy(typeName, "CF_DIB"); break;} case CF_PALETTE : {strcpy(typeName, "CF_PALETTE"); break;} case CF_PENDATA : {strcpy(typeName, "CF_PENDATA"); break;} case CF_RIFF : {strcpy(typeName, "CF_RIFF"); break;} case CF_WAVE : {strcpy(typeName, "CF_WAVE"); break;} case CF_UNICODETEXT : {strcpy(typeName, "CF_UNICODETEXT"); break;} case CF_ENHMETAFILE : {strcpy(typeName, "CF_ENHMETAFILE"); break;} case CF_HDROP : {strcpy(typeName, "CF_HDROP"); break;} case CF_LOCALE : {strcpy(typeName, "CF_LOCALE"); break;} case CF_DIBV5 : {strcpy(typeName, "CF_DIBV5"); break;} case CF_OWNERDISPLAY : {strcpy(typeName, "CF_OWNERDISPLAY"); break;} case CF_DSPTEXT : {strcpy(typeName, "CF_DSPTEXT"); break;} case CF_DSPBITMAP : {strcpy(typeName, "CF_DSPBITMAP"); break;} case CF_DSPMETAFILEPICT: {strcpy(typeName, "CF_DSPMETAFILEPICT"); break;} case CF_DSPENHMETAFILE : {strcpy(typeName, "CF_DSPENHMETAFILE"); break;} default: { if (((CLIPFORMAT) type) == dnd->UniformResourceLocator) { strcpy(typeName, "UniformResourceLocator"); } else if (((CLIPFORMAT) type) == dnd->FileName) { strcpy(typeName, "FileName"); } else if (((CLIPFORMAT) type) == dnd->HTML_Format) { strcpy(typeName, "HTML Format"); } else if (((CLIPFORMAT) type) == dnd->RichTextFormat) { strcpy(typeName, "Rich Text Format"); } else GetClipboardFormatName((CLIPFORMAT) type, typeName, 256); } } return &typeName[0]; } /* TkDND_TypeToString */ /* *---------------------------------------------------------------------- * * TkDND_StringToType -- * * Returns a type code corresponding to the given type string. * * Results: * * Side effects: * - * *---------------------------------------------------------------------- */ CLIPFORMAT TkDND_StringToType(char *typeStr) { if (strcmp(typeStr, "CF_TEXT") == 0) return CF_TEXT; else if (strcmp(typeStr, "CF_OEMTEXT") == 0) return CF_OEMTEXT; else if (strcmp(typeStr, "CF_UNICODETEXT") == 0) return CF_UNICODETEXT; else if (strcmp(typeStr, "CF_HDROP") == 0) return CF_HDROP; else if (strcmp(typeStr, "CF_DIB") == 0) return CF_DIB; else if (strcmp(typeStr, "CF_BITMAP") == 0) return CF_BITMAP; else if (strcmp(typeStr, "CF_METAFILEPICT") == 0) return CF_METAFILEPICT; else if (strcmp(typeStr, "CF_SYLK") == 0) return CF_SYLK; else if (strcmp(typeStr, "CF_TIFF") == 0) return CF_TIFF; else if (strcmp(typeStr, "CF_PALETTE") == 0) return CF_PALETTE; else if (strcmp(typeStr, "CF_PENDATA") == 0) return CF_PENDATA; else if (strcmp(typeStr, "CF_RIFF") == 0) return CF_RIFF; else if (strcmp(typeStr, "CF_WAVE") == 0) return CF_WAVE; else if (strcmp(typeStr, "CF_ENHMETAFILE") == 0) return CF_ENHMETAFILE ; else if (strcmp(typeStr, "CF_HDROP") == 0) return CF_HDROP; else if (strcmp(typeStr, "CF_LOCALE") == 0) return CF_LOCALE; else if (strcmp(typeStr, "CF_DIBV5") == 0) return CF_DIBV5; else if (strcmp(typeStr, "CF_OWNERDISPLAY") == 0) return CF_OWNERDISPLAY; else if (strcmp(typeStr, "CF_DSPTEXT") == 0) return CF_DSPTEXT; else if (strcmp(typeStr, "CF_DSPBITMAP") == 0) return CF_DSPBITMAP; else if (strcmp(typeStr, "CF_DSPMETAFILEPICT")== 0) return CF_DSPMETAFILEPICT; else if (strcmp(typeStr, "CF_DSPENHMETAFILE") == 0) return CF_DSPENHMETAFILE; else return RegisterClipboardFormat(typeStr); // return 0; // unreachable } /* TkDND_StringToType */ /* *---------------------------------------------------------------------- * * TkDND_Init -- * * Initialize the drag and drop platform specific protocol. * Under windows, this is the OLE protocol. * * Results: * A structure that holds platform specific information. * * Side effects: * - * *---------------------------------------------------------------------- */ void *TkDND_Init(Tcl_Interp *interp, Tk_Window topwin) { HRESULT hret; #ifdef DND_DEBUG Tcl_Eval(interp, "file mkdir C:/Temp"); Tcl_Eval(interp, "file native C:/Temp/tkdndLog_[pid].txt"); TkDND_Log = fopen(Tcl_GetString(Tcl_GetObjResult(interp)), "w"); XDND_DEBUG("\n-=-=-=-=-=-=-=-=-=-=-=-=-= Log opened =-=-=-=-=-=-=-=-=-=-=\n"); #endif /* * Initialise OLE */ hret = OleInitialize(NULL); /* * If OleInitialize returns S_FALSE, OLE has already been initialized */ if (hret != S_OK && hret != S_FALSE) { Tcl_AppendResult(interp, "unable to initialize OLE2", (char *) NULL); return NULL; } dnd = (DndClass *) Tcl_Alloc(sizeof(DndClass)); dnd->MainWindow = topwin; dnd->data = NULL; dnd->length = -1; Tcl_DStringInit(&(dnd->DraggerTypes)); dnd->UniformResourceLocator = RegisterClipboardFormat("UniformResourceLocator"); dnd->FileName = RegisterClipboardFormat("FileName"); dnd->HTML_Format = RegisterClipboardFormat("HTML Format"); dnd->RichTextFormat = RegisterClipboardFormat("Rich Text Format"); /* The correct type to use is CFSTR_FILEDESCRIPTOR, but this depends on how the code gets compiled. So, we use directly the individual names... */ dnd->FileGroupDescriptor = RegisterClipboardFormat("FileGroupDescriptor"); dnd->FileGroupDescriptorW = RegisterClipboardFormat("FileGroupDescriptorW"); #ifdef TKDND_ENABLE_SHAPE_EXTENSION /* Load the shape extension... */ if (Shape_Init(interp) != TCL_OK) { /* TODO: Provide the shape command, even if does not work... */ } #endif /* TKDND_ENABLE_SHAPE_EXTENSION */ return dnd; } /* TkDND_Init */ /* *---------------------------------------------------------------------- * * TkDND_AddHandler -- * * Add a drag&drop handler to a window, freeing up any memory and * objects that need to be cleaned up. * * Arguments: * interp: Tcl interpreter * topwin: The main window * table: Hash table we are adding the window/type to * windowPath: String pathname of window * typeStr: The data type to add. * script: Script to run * isDropTarget: Is this target a drop target? * priority: Priority of this type * * Results: * A standard Tcl result * * Notes: * The table that is passed in must have been initialized. * Inserts a new node in the typelist for the window with the * highest priorities listed first. * *---------------------------------------------------------------------- */ int TkDND_AddHandler(Tcl_Interp *interp, Tk_Window topwin, Tcl_HashTable *table, char *windowPath, char *typeStr, unsigned long eventType, unsigned long eventMask, char *script, int isDropTarget, int priority) { Tcl_HashEntry *hPtr; DndInfo *infoPtr; Tk_Window tkwin; DndType *head, *prev, *curr, *tnew; #define TkDND_ACTUAL_TYPE_NU 10 int ActualType[TkDND_ACTUAL_TYPE_NU]; int created, len, i, removed = False; UINT atom; HRESULT hret; tkwin = Tk_NameToWindow(interp, windowPath, topwin); if (tkwin == NULL) return TCL_ERROR; Tk_MakeWindowExist(tkwin); /* * Do we already have a binding script for this type of type/event? * Remember that we have to search all entries in order to remove all of * them that have the same typeStr but different actual types... */ hPtr = Tcl_CreateHashEntry(table, windowPath, &created); if (!created) { infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); for (curr = (&infoPtr->head)->next; curr != NULL; curr = curr->next) { if (strcmp(curr->typeStr, typeStr) == 0 && curr->eventType == eventType && curr->eventMask == eventMask) { /* * Replace older script... */ Tcl_Free(curr->script); len = (int)strlen(script) + 1; curr->script = (char *) Tcl_Alloc(sizeof(char)*len); memcpy(curr->script, script, len); removed = True; } } } if (removed) return TCL_OK; /* * In order to ensure portability among different protocols, we have to * register more than one type for each "platform independed" type requested * by the user... */ i = 0; if (strcmp(typeStr, "text/plain;charset=UTF-8") == 0) { /* * Here we handle our platform independed way to transer UTF strings... */ ActualType[i++] = CF_UNICODETEXT; /* OLE DND Protocol */ ActualType[i++] = NULL; } else if (strcmp(typeStr, "text/plain") == 0) { /* * Here we handle our platform independed way to transer ASCII strings... */ ActualType[i++] = CF_TEXT; /* OLE DND Protocol */ ActualType[i++] = CF_OEMTEXT; /* OLE DND Protocol */ ActualType[i++] = NULL; } else if (strcmp(typeStr, "text/uri-list") == 0 || strcmp(typeStr, "Files") == 0) { /* * Here we handle our platform independed way to transer File Names... */ ActualType[i++] = CF_HDROP; /* OLE DND Protocol */ ActualType[i++] = NULL; } else if (strcmp(typeStr, "Text") == 0) { /* * Here we handle our platform independed way to all supported text * formats... */ ActualType[i++] = CF_UNICODETEXT; /* OLE DND Protocol */ ActualType[i++] = CF_OEMTEXT; /* OLE DND Protocol */ ActualType[i++] = CF_TEXT; /* OLE DND Protocol */ ActualType[i++] = NULL; } else if (strcmp(typeStr, "FilesWithContent") == 0) { ActualType[i++] = dnd->FileGroupDescriptorW; /* OLE DND Protocol */ ActualType[i++] = dnd->FileGroupDescriptor; /* OLE DND Protocol */ ActualType[i++] = NULL; } else if (strcmp(typeStr, "Image") == 0) { /* * Here we handle our platform independed way to all supported text * formats... */ ActualType[i++] = CF_DIB; /* OLE DND Protocol */ //ActualType[i++] = CF_BITMAP; /* OLE DND Protocol */ //ActualType[i++] = CF_TIFF; /* OLE DND Protocol */ //ActualType[i++] = CF_METAFILEPICT; /* OLE DND Protocol */ ActualType[i++] = NULL; } else { /* * This is a platform specific type. Is it a known type? */ if (strchr(typeStr, '*') != NULL) ActualType[i++] = -1; else ActualType[i++] = TkDND_StringToType(typeStr); ActualType[i++] = NULL; } for (i=0; ipriority = priority; len = (int)strlen(typeStr) + 1; tnew->matchedType = 0; tnew->typeStr = (char *) Tcl_Alloc(sizeof(char)*len); memcpy(tnew->typeStr, typeStr, len); tnew->eventType = eventType; tnew->eventMask = eventMask; len = (int)strlen(script) + 1; tnew->script = (char *) Tcl_Alloc(sizeof(char)*len); memcpy(tnew->script, script, len); tnew->next = NULL; tnew->EnterEventSent = 0; if (ActualType[i] < 0) { atom = 0; } else { atom = (UINT) ActualType[i]; if (atom == 0) { Tcl_AppendResult(interp, "unable to register clipboard format ", typeStr, (char *) NULL); return TCL_ERROR; } } tnew->type = atom; XDND_DEBUG5(" type='%-16s',%5d / event=%2d / mask=%08x\n", typeStr, atom, eventType, eventMask); if (created) { infoPtr = (DndInfo *) Tcl_Alloc(sizeof(DndInfo)); infoPtr->head.next = NULL; infoPtr->interp = interp; infoPtr->tkwin = tkwin; infoPtr->hashEntry = hPtr; if (isDropTarget) { infoPtr->DropTarget = new TkDND_DropTarget(infoPtr); infoPtr->DropTarget->AddRef(); hret = RegisterDragDrop(Tk_GetHWND(Tk_WindowId(tkwin)), infoPtr->DropTarget); if (hret != S_OK) { infoPtr->DropTarget->Release(); Tcl_Free((char *) infoPtr); Tcl_AppendResult(interp, "unable to register \"", windowPath, "\" as a droppable window", (char *) NULL); Tcl_DeleteHashEntry(hPtr); return TCL_ERROR; } } else { infoPtr->DropTarget = NULL; } Tk_CreateEventHandler(tkwin, StructureNotifyMask, TkDND_DestroyEventProc, (ClientData) infoPtr); Tcl_SetHashValue(hPtr, infoPtr); infoPtr->head.next = tnew; created = False; } else { infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); infoPtr->tkwin = tkwin; head = prev = &infoPtr->head; for (curr = head->next; curr != NULL; prev = curr, curr = curr->next) { if (curr->priority > priority) break; } tnew->next = prev->next; prev->next = tnew; } } /* for (i=0; iDesiredTypeStr; } /* TkDND_GetCurrentTypeName */ /* *---------------------------------------------------------------------- * TkDND_GetCurrentTypeCode -- * Returns a string that describes the current dnd type code in hex. * * Results: * A dynamic string. Should be freed. * * Notes: *---------------------------------------------------------------------- */ char *TkDND_GetCurrentTypeCode(void) { char tmp[64], *str; sprintf(tmp, "0x%08x", dnd->DesiredType); str = Tcl_Alloc((int)(sizeof(char) * (strlen(tmp)+1))); strcpy(str, tmp); return str; } /* TkDND_GetCurrentTypeCode */ /* *---------------------------------------------------------------------- * TkDND_GetCurrentActionName -- * Returns a string that describes the current dnd action. * * Results: * A static string. Should never be freed. * * Notes: *---------------------------------------------------------------------- */ char *TkDND_GetCurrentActionName(void) { return dnd->DesiredAction; } /* TkDND_GetCurrentActionName */ /* *---------------------------------------------------------------------- * TkDND_GetCurrentButton -- * Returns a integer that describes the current button used * for the drag operation. (Laurent Riesterer, 24/06/2000) * * Results: * An integer. * * Notes: *---------------------------------------------------------------------- */ int TkDND_GetCurrentButton(void) { return dnd->button; } /* TkDND_GetCurrentButton */ /* *---------------------------------------------------------------------- * TkDND_GetCurrentModifiers -- * Returns a string that describes the modifiers that are currently * pressed during a drag and drop operation. * (Laurent Riesterer, 24/06/2000) * Results: * A dynamic string. Should be freed. * * Notes: *---------------------------------------------------------------------- */ char *TkDND_GetCurrentModifiers(Tk_Window tkwin) { Tcl_DString ds; char *str; Tcl_DStringInit(&ds); if (GetKeyState(VK_SHIFT) & 0x8000) Tcl_DStringAppendElement(&ds,"Shift"); if (GetKeyState(VK_CONTROL) & 0x8000) Tcl_DStringAppendElement(&ds,"Control"); if (GetKeyState(VK_MENU) & 0x8000) Tcl_DStringAppendElement(&ds,"Alt"); str = Tcl_Alloc(sizeof(char) * (Tcl_DStringLength(&ds)+1)); memcpy(str, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)+1); Tcl_DStringFree(&ds); (void)tkwin; return str; } /* TkDND_GetCurrentModifiers */ /* *---------------------------------------------------------------------- * TkDND_GetSourceActions -- * Returns a string that describes the supported by the source actions. * * Results: * A dynamic string. Should be freed. * *---------------------------------------------------------------------- */ char *TkDND_GetSourceActions(void) { Tcl_DString ds; char *str; Tcl_DStringInit(&ds); if (dnd->DraggerActions & DROPEFFECT_COPY) { Tcl_DStringAppendElement(&ds, "copy"); } if (dnd->DraggerActions & DROPEFFECT_MOVE) { Tcl_DStringAppendElement(&ds, "move"); } if (dnd->DraggerActions & DROPEFFECT_LINK) { Tcl_DStringAppendElement(&ds, "link"); } str = Tcl_Alloc(sizeof(char) * (Tcl_DStringLength(&ds)+1)); memcpy(str, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)+1); Tcl_DStringFree(&ds); return str; } /* TkDND_GetSourceActions */ /* *---------------------------------------------------------------------- * TkDND_GetSourceActionDescriptions -- * Returns a string that describes the supported by the source action * descriptions. * * Results: * A dynamic string. Should be freed. * * Notes: * *---------------------------------------------------------------------- */ char *TkDND_GetSourceActionDescriptions(void) { char *descriptions = NULL; Tcl_DString ds; char *str; Tcl_DStringInit(&ds); if (dnd->DraggerActions & DROPEFFECT_COPY) { Tcl_DStringAppendElement(&ds, "copy"); } else if (dnd->DraggerActions & DROPEFFECT_MOVE) { Tcl_DStringAppendElement(&ds, "move"); } else if (dnd->DraggerActions & DROPEFFECT_LINK) { Tcl_DStringAppendElement(&ds, "link"); } str = Tcl_Alloc(sizeof(char) * (Tcl_DStringLength(&ds)+1)); memcpy(str, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)+1); Tcl_DStringFree(&ds); (void)descriptions; return str; } /* TkDND_GetSourceActionDescriptions */ /* *---------------------------------------------------------------------- * TkDND_GetSourceTypeList -- * Returns a string that describes the supported by the drag source * types. * * Results: * A dynamic string. Should be freed. * * Notes: * Feature not supported by OLE DND. Simulated. *---------------------------------------------------------------------- */ char *TkDND_GetSourceTypeList(void) { char *str; str = Tcl_Alloc(sizeof(char) * (Tcl_DStringLength(&(dnd->DraggerTypes))+1)); memcpy(str, Tcl_DStringValue(&(dnd->DraggerTypes)), Tcl_DStringLength(&(dnd->DraggerTypes))+1); return str; } /* TkDND_GetSourceTypeList */ /* *---------------------------------------------------------------------- * TkDND_GetSourceTypeCodeList -- * Returns a string that describes the supported by the target action * descriptions. * * Results: * A dynamic string. Should be freed. * * Notes: * Feature not supported by OLE DND. Simulated. *---------------------------------------------------------------------- */ char *TkDND_GetSourceTypeCodeList(void) { Tcl_Obj *listObj, **type; Tcl_DString ds; char tmp[64], *str, *list; int items, i; list = TkDND_GetSourceTypeList(); listObj = Tcl_NewStringObj(list, -1); Tcl_Free(list); Tcl_DStringInit(&ds); Tcl_ListObjGetElements(NULL, listObj, &items, &type); for (i=0; ibutton = button; } else { /* * Get the current pressed button... */ if (GetKeyState(VK_LBUTTON) & 0x8000) dnd->button = 1; if (GetKeyState(VK_MBUTTON) & 0x8000) dnd->button = 2; if (GetKeyState(VK_RBUTTON) & 0x8000) dnd->button = 3; } /* * Create the Data object, also required by the OLE protocol... */ infoPtr = (DndInfo *) Tcl_GetHashValue(hPtr); DataObject = new TkDND_DataObject(infoPtr); if (DataObject == NULL) { Tcl_AppendResult(interp, "unable to create OLE Data object", (char *) NULL); return TCL_ERROR; } DataObject->AddRef(); /* * Create the Drag Source object, required by the OLE protocol... */ DropSource = new TkDND_DropSource(infoPtr); if (DropSource == NULL) { Tcl_AppendResult(interp, "unable to create OLE Drop Source object", (char *) NULL); return TCL_ERROR; } DropSource->AddRef(); /* * Handle User-requested Actions... */ if (Actions == NULL) { /* The User has not specified any actions: defaults to copy... */ actions |= DROPEFFECT_COPY; memset(Descriptions, '\0', TKDND_MAX_DESCRIPTIONS_LENGTH); strcpy(Descriptions, "Copy\0\0"); strcpy(dnd->DesiredAction, "copy"); } else { Tcl_ListObjGetElements(interp, Actions, &elem_nu, &elem); strcpy(dnd->DesiredAction, Tcl_GetString(elem[0])); for (i = 0; i < elem_nu; i++) { action = Tcl_GetString(elem[i]); if (strcmp(action,"copy")==0) actions |= DROPEFFECT_COPY; else if (strcmp(action,"move")==0) actions |= DROPEFFECT_MOVE; else if (strcmp(action,"link")==0) actions |= DROPEFFECT_LINK; else if (strcmp(action,"ask" )==0) {/* "ask" not supported */} else {/* "private" not supported */} } } /* * Finally, do the drag & drop operation... */ dnd->interp = interp; dnd->x = 0; dnd->y = 0; dnd->CursorWindow = cursor_window; dnd->CursorCallback = cursor_callback; dnd->DraggerWindow = infoPtr->tkwin; dnd->DesiredType = infoPtr->head.next->type; dnd->DesiredTypeStr = infoPtr->head.next->typeStr; dnd->CallbackStatus = TCL_OK; if (dnd->length != -1 || dnd->data != NULL) { if (dnd->data != NULL) Tcl_DecrRefCount(dnd->data); dnd->data = NULL; dnd->length = -1; } hr = DoDragDrop(DataObject, DropSource, actions, &FinalAction); /* * Free unwanted objects... */ DropSource->Release(); DataObject->Release(); (void)hr; return TCL_OK; } /* TkDND_DndDrag */ /* *---------------------------------------------------------------------- * * TkDND_WidgetGetData -- * * This function is responsible for executing the tcl binding that will * return the data to be dropped to us... * * Results: * A standart tcl result. * * Side effects: * The data is retrieved from widget and is stored inside the dnd * structure... * *---------------------------------------------------------------------- */ int TkDND_WidgetGetData(DndInfo *infoPtr, char **data, int *length, CLIPFORMAT type) { Tcl_DString dString; DndType *curr; int ret; for (curr = infoPtr->head.next; curr != NULL; curr = curr->next) { if (curr->type == type) { Tcl_DStringInit(&dString); TkDND_ExpandPercents(infoPtr, curr, curr->script, &dString,dnd->x,dnd->y); XDND_DEBUG2(": %s\n", Tcl_DStringValue(&dString)); ret = TkDND_ExecuteBinding(infoPtr->interp, Tcl_DStringValue(&dString),-1, NULL); Tcl_DStringFree(&dString); dnd->CallbackStatus = ret; if (ret == TCL_ERROR) { Tk_BackgroundError(infoPtr->interp); } else if (ret == TCL_BREAK) { *data = NULL; *length = 0; XDND_DEBUG("TkDND_WidgetGetData: Widget refused to send data " "(returned TCL_BREAK)\n"); return False; } if (curr->matchedType == 0) { curr->matchedType = type; } *data = TkDND_GetDataAccordingToType(infoPtr, Tcl_GetObjResult(infoPtr->interp), curr, length); curr->matchedType = 0; dnd->DesiredTypeStr = curr->typeStr; return True; } } return False; } /* TkDND_WidgetGetData */ /* *---------------------------------------------------------------------- * * TkDND_GetDataFromImage -- * * This function tries to retrieve from a Tk image handle a suitable * platform specific string (possibly related to the specified type) * that we can use in order to transfer images to other applications... * * Results: * A boolean value, whether we have succeded or not. * * Side effects: * This function must allocates a new buffer with Tcl_Alloc in order to * place the image data. Also, length must be set to the data length... * *---------------------------------------------------------------------- */ typedef union { int type; struct {int type; HWND handle; Tk_Window *winPtr;} window; struct {int type; HBITMAP handle; Colormap colormap; int depth;} bitmap; struct {int type; HDC hdc;} winDC; } Dnd_TkWinDrawable; HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal, int *length); int TkDND_GetDataFromImage(DndInfo *info, char *imageName, char *type, char **result, int *length) { *result = NULL; *length = 0; if (strcmp(type, "Image") == 0 || strcmp(type, "CF_DIB") == 0) { /* * This function does nothing. The whole job is done by * TkDND_DataObject::GetData in win/OleDND.cpp... */ *length = (int)strlen(imageName)+1; *result = Tcl_Alloc(*length*sizeof(char)); if (*result != NULL) { strcpy(*result, imageName); } return 1; } (void)info; return 0; } /* TkDND_GetDataFromImage */ #define WIDTHBYTES(i) ((i+31)/32*4) /**************************************************************************** * * * FUNCTION : DibNumColors(VOID FAR * pv) * * * * PURPOSE : Determines the number of colors in the DIB by looking at * * the BitCount filed in the info block. * * * * RETURNS : The number of colors in the DIB. * * * ****************************************************************************/ WORD DibNumColors (VOID FAR * pv) { INT bits; LPBITMAPINFOHEADER lpbi; LPBITMAPCOREHEADER lpbc; lpbi = ((LPBITMAPINFOHEADER)pv); lpbc = ((LPBITMAPCOREHEADER)pv); /* With the BITMAPINFO format headers, the size of the palette * is in biClrUsed, whereas in the BITMAPCORE - style headers, it * is dependent on the bits per pixel ( = 2 raised to the power of * bits/pixel). */ if (lpbi->biSize != sizeof(BITMAPCOREHEADER)){ if (lpbi->biClrUsed != 0) return (WORD)lpbi->biClrUsed; bits = lpbi->biBitCount; } else bits = lpbc->bcBitCount; switch (bits){ case 1: return 2; case 4: return 16; case 8: return 256; default: /* A 24 bitcount DIB has no color table */ return 0; } } /* DibNumColors */ /**************************************************************************** * * * FUNCTION : PaletteSize(VOID FAR * pv) * * * * PURPOSE : Calculates the palette size in bytes. If the info. block * * is of the BITMAPCOREHEADER type, the number of colors is * * multiplied by 3 to give the palette size, otherwise the * * number of colors is multiplied by 4. * * * * RETURNS : Palette size in number of bytes. * * * ****************************************************************************/ WORD PaletteSize (VOID FAR * pv) { LPBITMAPINFOHEADER lpbi; WORD NumColors; lpbi = (LPBITMAPINFOHEADER)pv; NumColors = DibNumColors(lpbi); if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) return (WORD)(NumColors * sizeof(RGBTRIPLE)); else return (WORD)(NumColors * sizeof(RGBQUAD)); } /* PaletteSize */ /**************************************************************************** * * * FUNCTION : DibFromBitmap() * * * * PURPOSE : Will create a global memory block in DIB format that * * represents the Device-dependent bitmap (DDB) passed in. * * * * RETURNS : A handle to the DIB * * * ****************************************************************************/ HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal, int *length) { BITMAP bm; BITMAPINFOHEADER bi; BITMAPINFOHEADER FAR *lpbi; DWORD dwLen; HANDLE hdib; HANDLE h; HDC hdc; if (!hbm) return NULL; if (hpal == NULL) hpal = (HPALETTE) GetStockObject(DEFAULT_PALETTE); GetObject(hbm,sizeof(bm),(LPSTR)&bm); if (biBits == 0) biBits = bm.bmPlanes * bm.bmBitsPixel; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bm.bmWidth; bi.biHeight = bm.bmHeight; bi.biPlanes = 1; bi.biBitCount = biBits; bi.biCompression = biStyle; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; dwLen = bi.biSize + PaletteSize(&bi); hdc = GetDC(NULL); hpal = SelectPalette(hdc,hpal,FALSE); RealizePalette(hdc); hdib = GlobalAlloc(GHND,dwLen); if (!hdib) { SelectPalette(hdc,hpal,FALSE); ReleaseDC(NULL,hdc); return NULL; } lpbi = (BITMAPINFOHEADER FAR *) GlobalLock(hdib); *lpbi = bi; /* call GetDIBits with a NULL lpBits param, so it will calculate the * biSizeImage field for us */ GetDIBits(hdc, hbm, 0L, (DWORD)bi.biHeight, (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS); bi = *lpbi; GlobalUnlock(hdib); /* If the driver did not fill in the biSizeImage field, make one up */ if (bi.biSizeImage == 0){ bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight; if (biStyle != BI_RGB) bi.biSizeImage = (bi.biSizeImage * 3) / 2; } /* realloc the buffer big enough to hold all the bits */ dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage; h = GlobalReAlloc(hdib,dwLen,0); if (h) hdib = h; else{ GlobalFree(hdib); hdib = NULL; SelectPalette(hdc,hpal,FALSE); ReleaseDC(NULL,hdc); return hdib; } /* call GetDIBits with a NON-NULL lpBits param, and actualy get the * bits this time */ lpbi = (BITMAPINFOHEADER FAR *)GlobalLock(hdib); if (GetDIBits( hdc, hbm, 0L, (DWORD)bi.biHeight, (LPBYTE)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS) == 0){ GlobalUnlock(hdib); hdib = NULL; SelectPalette(hdc,hpal,FALSE); ReleaseDC(NULL,hdc); return NULL; } bi = *lpbi; GlobalUnlock(hdib); SelectPalette(hdc,hpal,FALSE); ReleaseDC(NULL,hdc); *length = dwLen; return hdib; } /* DibFromBitmap */ /* * End of tkOleDND.cpp */ kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/win/tkOleDND_TEnumFormatEtc.cpp0000644000175000017500000002077310562634644026005 0ustar domibeldomibel/* *---------------------------------------------------------------------- * Filename: tenumformatetc.cpp * * Implements the TEnumFormatEtc class, an IEnumFormatEtc object * * Copyright (c) 1995 LAS Incorporated. * All rights reserved. * * Copyright (c) 1995 University of California, Berkeley. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * IN NO EVENT SHALL LAS INCORPORATED BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * LAS INCORPORATED SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND LAS INCORPORATED HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. *---------------------------------------------------------------------- */ #include #include #include "tkOleDND_TEnumFormatEtc.h" /* *---------------------------------------------------------------------- * CreateFormatEtcEnumerator -- * * Creates an enumerator. * * Arguments: * pUnknownObj The object this enumerator is associated with * numFormats The number of format types passed in * formatList List of the formats. *---------------------------------------------------------------------- */ LPENUMFORMATETC CreateFormatEtcEnumerator(LPUNKNOWN pUnknownObj, ULONG numFormats, LPFORMATETC formatList) { LPENUMFORMATETC pNew; pNew = new TEnumFormatEtc(pUnknownObj, numFormats, formatList); if (pNew == NULL) { return NULL; } pNew->AddRef(); pUnknownObj->AddRef(); return pNew; } /* *---------------------------------------------------------------------- * TEnumFormatEtc::TEnumFormatEtc * * Constructor *---------------------------------------------------------------------- */ TEnumFormatEtc::TEnumFormatEtc(LPUNKNOWN pUnknownObj, ULONG numFormats, LPFORMATETC formatList) { UINT i; m_refCnt = 0; m_currElement = 0; m_pUnknownObj = pUnknownObj; m_numFormats = numFormats; m_formatList = new FORMATETC[numFormats]; if (m_formatList != NULL) { for (i=0; i < numFormats; i++) { m_formatList[i] = formatList[i]; } } pUnknownObj->AddRef(); } /* *---------------------------------------------------------------------- * TEnumFormatEtc::~TEnumFormatEtc * * Destructor *---------------------------------------------------------------------- */ TEnumFormatEtc::~TEnumFormatEtc(void) { if (m_formatList == NULL) { delete [] m_formatList; } } /* *---------------------------------------------------------------------- * TEnumFormatEtc::QueryInterface * * Does interface negotiation. IUnknown and IEnumFORMATETC are * the supported interfaces. * * Arguments: * * REFIID riid A reference to the interface being queried. * LPVOID *ppvObj Out parameter to return a pointer to interface. * * Results: * S_OK if interface is supported, E_NOINTERFACE if it is not * *---------------------------------------------------------------------- */ STDMETHODIMP TEnumFormatEtc::QueryInterface(REFIID riid, LPVOID *ppv) { if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEnumFORMATETC)) { *ppv = (LPVOID) this; ((LPUNKNOWN)*ppv)->AddRef(); return S_OK; } *ppv = NULL; return ResultFromScode(E_NOINTERFACE); } /* *---------------------------------------------------------------------- * TEnumFormatEtc::AddRef * * Increment the reference count on the object as well as on * the unknown object this enumerator is linked to. * * Results: * The current reference count on the object. *---------------------------------------------------------------------- */ STDMETHODIMP_(ULONG) TEnumFormatEtc::AddRef(void) { m_refCnt++; m_pUnknownObj->AddRef(); return m_refCnt; } /* *---------------------------------------------------------------------- * TEnumFormatEtc::Release * * Decrement the reference count on the object as well as on * the unknown object this enumerator is linked to. If the * reference count becomes 0, the object is deleted. * * Results: * The current reference count on the object. *---------------------------------------------------------------------- */ STDMETHODIMP_(ULONG) TEnumFormatEtc::Release(void) { m_refCnt--; m_pUnknownObj->Release(); if (m_refCnt == 0L) { delete this; return 0L; } return m_refCnt; } /* *---------------------------------------------------------------------- * TEnumFormatEtc::Next * * Retrieves the specified number of items in the enumeration * sequence * * Arguments: * numFormats Maximum number of FORMATETCs to return. * pOutList Where to store the outgoing data * numOut Returns how many were enumerated. * * Return Value: * HRESULT S_OK if successful, S_FALSE otherwise, *---------------------------------------------------------------------- */ STDMETHODIMP TEnumFormatEtc::Next(ULONG numFormats, LPFORMATETC pOutList, ULONG *pNumOut) { ULONG i; ULONG cReturn=0L; if (pNumOut) { *pNumOut = 0L; } if (m_formatList == NULL) { return ResultFromScode(S_FALSE); } if (pOutList == NULL) { if (numFormats == 1) { return ResultFromScode(S_FALSE); } else { return ResultFromScode(E_POINTER); } } if (m_currElement >= m_numFormats) { return ResultFromScode(S_FALSE); } for (i = 0; i < numFormats && m_currElement < m_numFormats; i++, m_currElement++) { *pOutList = m_formatList[m_currElement]; pOutList++; } if (pNumOut != NULL) { *pNumOut = i; } (void)cReturn; return S_OK; } /* *---------------------------------------------------------------------- * TEnumFormatEtc::Skip * * Skips over a specified number of elements in the enumeration * sequence. * * Arguments: * numSkip ULONG number of elements to skip. * * Result: * S_OK if successful, S_FALSE if we could not skip enough elements *---------------------------------------------------------------------- */ STDMETHODIMP TEnumFormatEtc::Skip(ULONG numSkip) { m_currElement += numSkip; if (m_currElement > m_numFormats) { m_currElement = m_numFormats; return ResultFromScode(S_FALSE); } return S_OK; } /* *---------------------------------------------------------------------- * TEnumFormatEtc::Reset * * Resets the enumeration sequence to the beginning * * Result: * S_OK *---------------------------------------------------------------------- */ STDMETHODIMP TEnumFormatEtc::Reset(void) { m_currElement = 0L; return S_OK; } /* *---------------------------------------------------------------------- * TEnumFormatEtc::Clone * * Returns another enumerator containing the same state as the * current container. * * Arguments: * ppNewObject New object is returned through here * * Result: * S_OK if all's well that ends well, else an error value. *---------------------------------------------------------------------- */ STDMETHODIMP TEnumFormatEtc::Clone(LPENUMFORMATETC *ppNewObject) { PTEnumFormatEtc pNew; pNew = new TEnumFormatEtc(m_pUnknownObj, m_numFormats, m_formatList); *ppNewObject = pNew; if (pNew == NULL) { return ResultFromScode(E_OUTOFMEMORY); } pNew->AddRef(); pNew->m_currElement = m_currElement; return S_OK; } kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/README.kww.txt0000644000175000017500000000262210562434154022453 0ustar domibeldomibelThe changes to TkDnD for KWWidgets are: - in generic rename all .c to .cpp (they are C++ files) - in generic/TkDND.h replace: extern "C" HWND Tk_GetHWND(Window win); with EXTERN HWND Tk_GetHWND(Window win); - in all files that include either tcl.h or tk.h add the following two lines *before* any other #include: #include "vtkTcl.h" #include "vtkTk.h" - in unix/tkXDND.c replace: result = TkDND_GetDataAccordingToType(infoPtr, by: result = (unsigned char *)TkDND_GetDataAccordingToType(infoPtr, replace: static TkDND_LocalErrorHandler(Display *display, XErrorEvent *error) { by static int TkDND_LocalErrorHandler(Display *display, XErrorEvent *error) { - in unix/XDND.c replace: XChangeProperty(dnd->display, request->requestor, request->property, request->target, 8, PropModeReplace, dnd->data, dnd->index); by: XChangeProperty(dnd->display, request->requestor, request->property, request->target, 8, PropModeReplace, (const unsigned char*)dnd->data, dnd->index); replace: dnd->data = data; dnd->index = read; by: dnd->data = (char*)data; dnd->index = read; - in unix/tkXDND.c replace: DndClass *TkDND_Init(Tcl_Interp *interp, Tk_Window topwin) { by: void *TkDND_Init(Tcl_Interp *interp, Tk_Window topwin) { - in generic/tkDND.cpp and generic/tkDNDBind.cpp replace all Tcl_SetResult(interp, "...", ...); with Tcl_SetResult(interp, (char*)"...", ...);kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/library/0000755000175000017500000000000011461110203021571 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/library/tkdnd.tcl0000644000175000017500000002351210562164011023413 0ustar domibeldomibel# # tkdnd.tcl -- # # This file implements some utility procedures that are used by the tkDND # package. # # This software is copyrighted by: # George Petasis, National Centre for Scientific Research "Demokritos", # Aghia Paraskevi, Athens, Greece. # e-mail: petasis@iit.demokritos.gr # # The following terms apply to all files associated # with the software unless explicitly disclaimed in individual files. # # The authors hereby grant permission to use, copy, modify, distribute, # and license this software and its documentation for any purpose, provided # that existing copyright notices are retained in all copies and that this # notice is included verbatim in any distributions. No written agreement, # license, or royalty fee is required for any of the authorized uses. # Modifications to this software may be copyrighted by their authors # and need not follow the licensing terms described here, provided that # the new terms are clearly indicated on the first page of each file where # they apply. # # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE # IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE # NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR # MODIFICATIONS. # namespace eval ::dnd { variable AskSelectedAction # This procedure is used just to ensure that the object given as its # argument can be accessed as a binary object. Many thanks to Paul Duffin # for the idea :-) proc ConvertToBinary {object} { binary scan $object {} return $object } # This procedure handles the special case where we want items into a canvas # widget to be drop targets. It emulates this case as follows: # # The tkDND extension is able to deliver events only to real windows # (that means tk widgets). This procedure can be the binding script of all # dnd events we are interested in being received by the canvas items. # When this function is called, it tries to find the item that the mouse # is over (if any). Then it examines its bindings, and if it finds the # dnd related event that is processing it delivers this event to the # particular item. Fianlly, it tries to emulate / # on every canvas item... proc CanvasDeliverEvent { event actions action button source_codes curr_code data descriptions mods type source_types win X x Y y } { # This function will find the topmost item that the mouse is over, and # Deliver the event specified by the "event" arg to this item... global CanvasDeliverEventStatus switch $event { - <> {set CanvasDeliverEventStatus(item) {}} default {} } # Translate mouse coordinates to canvas coordinates... set cx [$win canvasx $x] set cy [$win canvasy $y] set cx_1 [expr {$cx+1}] set cy_1 [expr {$cy+1}] # Find all tags that are under the mouse... set tags [$win find overlapping $cx $cy $cx_1 $cy_1] # ... and select the topmost... set length [llength $tags] # If no tags under the mouse, return... if {!$length} { #puts -->$CanvasDeliverEventStatus(item) if {[string length $CanvasDeliverEventStatus(item)]} { # Send <>... set _id $CanvasDeliverEventStatus(item) set _binding {} foreach _tag [concat $_id [$win gettags $_id]] { set _binding [$win bind $_tag <>] if {[string length $_binding]} {break} } # puts "Sending (1) to $_id ($_binding)" set script {} foreach element $_binding { switch $element { %% {lappend script %} %A {lappend script $action} %a {lappend script $actions} %b {lappend script $button} %C {lappend script $source_codes} %c {lappend script $curr_code} %D {lappend script $data} %d {lappend script $descriptions} %m {lappend script $mods} %T {lappend script $type} %t {lappend script $source_types} %W {lappend script $win} %X {lappend script $X} %x {lappend script $x} %Y {lappend script $Y} %y {lappend script $y} %I {lappend script $_id} default {lappend script $element} } } if {[llength $script]} {uplevel 1 $script} } set CanvasDeliverEventStatus(item) {} update if {[string equal $event <>]} { return -code break } return $action } if {$length == 1} { set id $tags } else { set id [$win find closest $cx $cy] } # Now in "id" we have the tag of the item below the mouse... # Has this item a binding? foreach tag [concat $id [$win gettags $id]] { set binding [$win bind $tag $event] if {[string length $binding]} {break} } # Is this tag the same as the last one? If is different, we # have to send a leave event to the previous item and an enter # event to this one... if {$CanvasDeliverEventStatus(item) != $id} { if {[string length $CanvasDeliverEventStatus(item)]} { # Send <>... set _id $CanvasDeliverEventStatus(item) set _binding {} foreach _tag [concat $_id [$win gettags $_id]] { set _binding [$win bind $_tag <>] if {[string length $_binding]} {break} } # puts "Sending (2) to $_id ($_binding)" set script {} foreach element $_binding { switch $element { %% {lappend script %} %A {lappend script $action} %a {lappend script $actions} %b {lappend script $button} %C {lappend script $source_codes} %c {lappend script $curr_code} %D {lappend script $data} %d {lappend script $descriptions} %m {lappend script $mods} %T {lappend script $type} %t {lappend script $source_types} %W {lappend script $win} %X {lappend script $X} %x {lappend script $x} %Y {lappend script $Y} %y {lappend script $y} %I {lappend script $_id} default {lappend script $element} } } if {[llength $script]} {uplevel 1 $script} } # Send <>... set _id $id set _binding {} foreach _tag [concat $_id [$win gettags $_id]] { set _binding [$win bind $_tag <>] if {[string length $_binding]} {break} } # puts "Sending to $tag ($_binding)" set script {} foreach element $_binding { switch $element { %% {lappend script %} %A {lappend script $action} %a {lappend script $actions} %b {lappend script $button} %C {lappend script $source_codes} %c {lappend script $curr_code} %D {lappend script $data} %d {lappend script $descriptions} %m {lappend script $mods} %T {lappend script $type} %t {lappend script $source_types} %W {lappend script $win} %X {lappend script $X} %x {lappend script $x} %Y {lappend script $Y} %y {lappend script $y} %I {lappend script $_id} default {lappend script $element} } } if {[llength $script]} {uplevel 1 $script} set CanvasDeliverEventStatus(item) $id } set script {} foreach element $binding { switch $element { %% {lappend script %} %A {lappend script $action} %a {lappend script $actions} %b {lappend script $button} %C {lappend script $source_codes} %c {lappend script $curr_code} %D {lappend script $data} %d {lappend script $descriptions} %m {lappend script $mods} %T {lappend script $type} %t {lappend script $source_types} %W {lappend script $win} %X {lappend script $X} %x {lappend script $x} %Y {lappend script $Y} %y {lappend script $y} %I {lappend script $id} default {lappend script $element} } } if {[llength $script]} { return [uplevel 1 $script] } set CanvasDeliverEventStatus(item) {} update if {[string equal $event <>]} { return -code break } return $action } # ChooseAskAction -- # This procedure displays a dialog with the help of which the user can # select one of the supported actions... proc ChooseAskAction {window x y actions descriptions args} { variable AskSelectedAction set title {Please Select Action:} foreach action $actions descr $descriptions { if {[string equal $action ask]} { set title $descr break } } set menu $window.__tk_dnd[pwd]__action_ask__Drop_window_[pid] catch {destroy $menu} menu $menu -title $title -tearoff 0 -disabledforeground darkgreen $menu add command -font {helvetica 12 bold} \ -label $title -command "destroy $menu" -state disabled $menu add separator set items 0 foreach action $actions descr $descriptions { if {[string equal $action ask]} continue $menu add command -label $descr -command \ "set ::dnd::AskSelectedAction $action; destroy $menu" incr items } if {!$items} { # The drag source accepts the ask action, but has no defined # action list? Add copy action at least... $menu add command -label Copy -command \ "set ::dnd::AskSelectedAction copy; destroy $menu" } $menu add separator $menu add command -label {Cancel Drop} -command \ "set ::dnd::AskSelectedAction none; destroy $menu" set AskSelectedAction none tk_popup $menu $x $y update bind $menu {after idle {catch {destroy %W}}} tkwait window $menu return $AskSelectedAction } };# namespace eval ::dnd # EOF kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/vtkKWTkDnDInit.h0000644000175000017500000000255110562126346023100 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTkDnDInit.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWTkDnDInit - class used to initialize TkDnD // .SECTION Description // This class is used to initialize the TkDnD library. #ifndef __vtkKWTkDnDInit_h #define __vtkKWTkDnDInit_h #include "vtkObject.h" #include "vtkKWWidgets.h" // Needed for export symbols directives #include "vtkTcl.h" // Needed for Tcl interpreter class KWWidgets_EXPORT vtkKWTkDnDInit : public vtkObject { public: static vtkKWTkDnDInit* New(); vtkTypeRevisionMacro(vtkKWTkDnDInit,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Load the TkDnD library. static void Initialize(Tcl_Interp*); protected: vtkKWTkDnDInit() {}; ~vtkKWTkDnDInit() {}; static int Initialized; private: vtkKWTkDnDInit(const vtkKWTkDnDInit&); // Not implemented. void operator=(const vtkKWTkDnDInit&); // Not implemented. }; #endif kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/vtkKWTkDnDInit.cxx0000644000175000017500000000325710562163641023456 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTkDnDInit.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWTkDnDInit.h" #include "vtkObjectFactory.h" #include "vtkKWTkUtilities.h" #include "vtkTk.h" #include "Utilities/tkdnd/vtkKWTkDnDTclLibrary.h" extern "C" int Tkdnd_Init(Tcl_Interp *interp); //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWTkDnDInit ); vtkCxxRevisionMacro(vtkKWTkDnDInit, "$Revision: 1.3 $"); int vtkKWTkDnDInit::Initialized = 0; //---------------------------------------------------------------------------- void vtkKWTkDnDInit::Initialize(Tcl_Interp* interp) { if (vtkKWTkDnDInit::Initialized) { return; } if (!interp) { vtkGenericWarningMacro( "An interpreter is needed to initialize the TkDnD library."); return; } vtkKWTkDnDInit::Initialized = 1; // Evaluate the library vtkKWTkUtilities::EvaluateEncodedString( interp, file_tkdnd_tcl, file_tkdnd_tcl_length, file_tkdnd_tcl_decoded_length); Tkdnd_Init(interp); } //---------------------------------------------------------------------------- void vtkKWTkDnDInit::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/ConvertResources.sh0000644000175000017500000000013410562163641024011 0ustar domibeldomibelKWConvertImageToHeader --zlib --base64 \ vtkKWTkDnDTclLibrary.h \ library/tkdnd.tcl kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/doc/0000755000175000017500000000000011461110203020672 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/doc/tkDND_Manual.html0000644000175000017500000006353610562201202024037 0ustar domibeldomibelManpage of dnd  

NAME

dnd - Tk Drag and Drop Interface  

SYNOPSIS

dnd bindtarget window
dnd bindtarget window type ?event?
dnd bindtarget window type event script ?priority?
dnd cleartarget window

dnd bindsource window
dnd bindsource window type
dnd bindsource window type script ?priority?
dnd clearsource window

dnd drag window ?-button button? ?-actions list ?-descriptions list?? ?-cursorwindow window? ?-callback script?

 

INTRODUCTION

The dnd command provides a Tcl interface to native, platform specific drag and drop mechanism. Under unix the drag & drop protocol in use is the XDND protocol (also used by the QT toolkit, KDE & GNOME Desktops). Basic interaction (currently drops) with Motif applications is also provided. Under Windows, the OLE drag & drop interfaces are used. The Macindosh platform is not yet supported.

With the dnd command the user is able to register existing Tk widgets as drag sources or drop targets, that are able to send or receive data encoded in specific types. Also through this command drag and drop related information can be retrieved, regarding the drag and drop registered widgets.

The legal forms for the dnd command are:

dnd bindtarget window
This command will return a list of all the registered types that the specified window can accept during a drop operation. An empty list will be returned if the window is not yet registered as a drop target.
dnd bindtarget window type ?event?
This command will return a the binding script for the specified event. If event is not specified, it defaults to the <Drop> event. An empty string will be returned if the window is not yet registered as a drop target.
dnd bindtarget window type event script ?priority?
This command will register a binding script for the event specified by event and for the specified type. Valid events are any of the following events: <DragEnter>, <Drag>, <DragLeave>, <Ask> and <Drop>.

The events support modifiers as in Tk. You can use a combination of Shift, Alt, Meta, Control, Mod[1-5], Button[1-5] to bind specific scripts when these modifiers are used. As in Tk, the closest matching script will be executed. If there is no exact match, the following algorithm will be applied: find an event without key modifiers but with buttons modifiers, then find an event without buttons modifiers but with the key modifiers, then at last find an event without key modifiers and without buttons (i.e. a raw event as listed above).

The <DragEnter> event will be delivered when the mouse enters the window during a drag operartion. The <Drag> event will be delivered when the mouse moves inside the widget during a drag operartion and the <DragLeave> event will be delivered if the mouse pointer leaves the window during a drag operation. Finally, the <Drop> event will be delivered if a drop over the window occurs.

If there is already a binding script for the same event, this script is replaced by the new one. If the script is an empty string, then any previous binding script is deleted and the specified event is no longer reported to the specified window. The user can optionally specify a priority for this specific type (an integer value ranging from 1 to 100). Priorities have meaning only when more than one types are registered for the same event. During a drag operartion the specified event will be delivered by executing the binding script associated with the type that has the higher priority (or the lower integer value: priority 1 is the highest priority while 100 is the lowest available priority). If priority is ommited, it defaults to 50. If more than one types have the same priority, the actual type that will be used cannot be pre-determined.

dnd cleartarget window
This command will unregister a registered drop target. The window will stop to respond to drops and all binding scripts for all drop target related events will be removed. It is not an error to use this command on a window that has never been registered as a drop target.
dnd bindsource window
This command will return a list of all the registered types that the specified window can drop on drop targets during a drop operation. An empty list will be returned if the window is not yet registered as a drag source.
dnd bindsource window type
This command will return the binding script that will be used for collecting the data that will be dropped during a drop operartion onto the drop target. Each script is associated with a specific type, providing the ability to have different scripts for different types.
dnd bindsource window type script ?priority?
This command will register a binding script for the specified type. This binding script will be used during a drop operation, in order to provide the actual data that will be dropped to the drop target. As a result, this binding script must returns the data to be dropped and the returned data must be encoding in a proper format, according to the specified type.

If the script is an empty string, then the specified type will be removed from the type list of supported by the drag source types.

Finally, the user can arrange the types that the drag source supports according to priorities. Valid priorities are integers in the range [1,100], with 100 denoting the highest possible priority. If priority is ommited, it defaults to 50. If more than one types have the same priority, only one of them will be used for a drop action. In this case the actual type that will be used cannot be pre-determined.

dnd clearsource window
This command will unregister a registered drag source. Subsequent attempts to initiate drag operations from this window with the dnd drag command will fail. The binding script associated for retrieving the data will be removed. It is not an error to use this command on a window that has never been registered as a drag source.
dnd drag window ?-button button? ?-actions list ?-descriptions list?? ?-cursorwindow window? ?-callback script?
This command will initiate a drag operartion having as source a window registered as a drag source. It is an error to use this command with a window that has not been registered as a drag source.

The user can also specify a Cursor window. A Cursor window is a toplevel window that will appear near the mouse cursor and will follow the cursor, as the mouse cursor moves during the drag operation. This window must exist when the dnd drag command will be executed. If a Cursor window is specified, the user can also register a callback through the -callback option. This callback will be called when the mouse pointer is moved and can be used in order to update the contents of the window. All available substitutions can also be used with this callback. For more information please refer to the BINDING SCRIPTS AND SUBSTITUTIONS section. One difference with the usual substitutions is that in this context, the %A substitution can also take as value the empty string, meaning that the cursor is over a window that cannot accept a drop action. It is advised that this particular callback should be as fast as possible, as it is called very frequently. That is also the reason why the position of the cursor window is managed by the dnd drag command. Also, dnd drag command ensures that the cursor window will always be visible (above all other windows).

Finally, the user can optionally specify a list of actions that will be associated with the current drag and drop operation. Valid actions are the following: copy, move, link and ask. It is up to the drop target to deside which action will be actually used for the drop operartion. It is also responsibility of the drop target to do the required actions implied by the drop action. For example, if the drop action during a file name drop is move, the window that accepts the drop is responsible for deleting the old file and create the new file at the dropped location.

If the ask action is included in the specified action list, then a description list can be also specified. The meaning of the ask action is that when the drop finally occurs, the widget that will accept the drop should display a window that will enable the user to select the action that desires from the available list. The ask action should not be listed and also a way to cancel the drop should provided to the user. The descriptions provided with the description list are the text that should be displayed for the corresponding individual action entries in the presented window. As a result, the description list must contain the same number of items as the action list and the its text elements must describe the corresponding actions specified by the -actions option. For example, a drop that offers all available actions should be defined as follows:


dnd drag .dragSource -actions {ask copy move link} \ 
  -descriptions {{Please Select Action:} {Copy} {Move} {Link}
}

 

DRAG AND DROP TYPES

In order to declare the format that the data that will encoded during a drag and drop operation, all drag and drop protocols use the notion of types. Unfortunately, each protocol defines its own, usually platform specific, types. The Tk toolkit, trying to maintain its portability among different platforms, offers some predefined types for some basic kinds of data, like text, filenames and images. These types are represented by their MIME types and are available under all platforms that Tk is available. Currently, the following predifined values are available:

text/plain:
This is the type understood by the majority of applications. With this type plain ASCII strings can be transfered. The system encoding will be used in order these strings to be mapped from the utf-8 encoding into ASCII and from ASCII into utf-8 strings used internally by tcl.
text/plain;charset=UTF-8:
With this type utf-8 strings can be transfered. No conversion is performed before the string is transmitted or after it is received.
text/uri-list:
This type is able to handle a list of filenames. The system encoding will be used in order to convert these strings from/to utf-8 strings.

Besides the predefined types, the user is free to use the platform specific types. For example under windows the type "FILENAME" can be used in order to receive a single filename from the Explorer or the type "NetscapeURL" can be used in order to receive a bookmark drop from Netscape Navigator. Under Unix, the type "FILE_NAME" can be used in order to receive a filename from a Motif application. The dnd command will make no conversion to types other than the predefined ones. Instead it will place received data into tcl byte-arrays and extract data from tcl after it converts objects into byte-arrays. Also note that the script should make the proper arrangements in order to maintain portability under different platforms. Procceed with platform depended types only if you are absolutely sure that the data you want to excange is not supported by the predefined, platform independed, types.

 

BINDING SCRIPTS AND SUBSTITUTIONS

Any script argument to dnd is a Tcl script, which will be executed in order for the given event to be delivered to the associated window. The script will be executed in the same interpreter that the dnd command was executed in order to specify the binding, and it will run at global level (only global variables will be accessible).

If script contains any % characters, then the script will not be executed directly. Instead, a new script will be generated by replacing each %, and the character following it, with information from the current event. The replacement depends on the character following the %, as defined in the list below. Some of the substitutions are only valid for certain types of events; if they are used for other types of events the value substituted is the empty string.

%%
Replaced with a single percent.
%A
The current action of the drag and drop operation.
%a
The action list supported by the drag source.
%b
The mouse button that is pressed during a drag and drop operation. Note that always a single mouse button is reported as pressed, even if more than one mouse buttons are actually pressed.
%c
The codes of the list of types supported by the drag source. All codes are in octal format and have the same order as the list of types obtained through the %t substitution.
%C
The code (in octal format) of the current type of the drag and drop operation.
%D
The data that has been dropped. Under some platforms the data will be available before the drop has occured. The format of the data is the current type of the drop operation.
%d
The list of descriptions, provided by the drag source. If not empty, it provides description text for the actions supported by the drag source.
%L
The list of types supported by the drag source.
%m
The list of modifier keyboard keys that are pressed. Modifier keys are some special keys, like Shift, Control or Alt. Valid modifiers are "Shift", "Control", "Alt", "Meta", "Mod1", "Mod2", "Mod3", "Mod4" and "Mod5". It is useful for binding scripts of drop target events to examine this list of modifiers, as it is quite usuall to change the action according to the state of some modifier keys. An alternative is to use modifiers directly when defining an event into the bindtarget command.
%t
The list of types supported by the drag source.
%T
The current type of the drag and drop operation.
%W
The window that the event is delivered to.
%X
The mouse pointer x coordinate, relative to the root window.
%x
The mouse pointer x coordinate, relative to the window that receives the event.
%Y
The mouse pointer y coordinate, relative to the root window.
%y
The mouse pointer y coordinate, relative to the window that receives the event.

 

DRAG AND DROP EVENTS

There are four events that are associated with drop targets and a single event associated with drag sources. The four events that are delivered to drop targets are:

<DragEnter>:
The binding script associated with this event will be executed when the mouse pointer during a drag operation enters the widget and at least one of the types supported by the drag source is supported as a drop target by the widget. The binding script is responsible for changing the appearence of the widget, according to whether the widget will accept the drop or not. If the widget will accept the drop, the return value of this script must be a value of the action list supported by the drag source (which can be obtained with %A), the current action (which can be obtained with %a), "private" or "default". If the widget will not accept the drop, then "none" must be returned. In the special case where the widget refuses the drop at the particular point that the mouse pointer is currently over but wants to be requested again when the mouse moves, the binding script must return a break code:


return -code break action

The main use of this feature is the ability to allow drops over specific items of a canvas widget.

<Drag>:
The binding script associated with this event will be executed when the mouse pointer during a drag operation moves over the widget and at least one of the types supported by the drag source is supported as a drop target by the widget. The binding script is responsible for reporting if the widget will accept a drop at the specific location that the mouse pointer is currently over. If the widget is going to accept a drop, the return value must be the action that will be used for the drop. This action must be an action also supported by the drag source, whose list of supported actions canbe obtained by the %a substitution. If the widget wants to utilise an action not supported by the drag source, the action "private" must be returned. If you want to use the default action specified by the user, the action "default" must be returned. If the widget does not want a drop to occur over the specific coordinates that the mouse pointer is currently over, "none" should be returned. The <Drag> event will be reported to the widget again, when the mouse pointer moves.
<DragLeave>:
The binding script associated with this event will be executed when the mouse pointer during a drag operation leaves the widget. The only responsibility of this script is to reset the visual appearence of the widget to its default state. This event will also be delivered if the mouse pointer is inside a widget that accepts drop during a drag operation and the whole drag nad drop operation is canceled (i.e. by pressing the Escape keyboard key).
<Ask>:
The binding script associated with this event will be executed when the mouse button during a drag operation has been released (meaning a drop), over a widget that can accept a drop of the specific type and the "ask" action. This event is only delivered if the drop action is ask. The main responsibility of the script is to get the actions supported by the drag source and their descriptions (through %a and %d respectively) and to display a dialog where the user can select the actual action that will be used for the drop operartion. The return value of the script must be the selected by the user action or "none" if the user canceled the drop.

It is an error to return the action "ask". If a binding script is not registered for this event, then this functionality will be provided by the Tk core library.

<Drop>:
The binding script associated with this event will be executed when the mouse button is release over a widget that can accept a drop of the specific type and action. In simple words, when a drop occurs over a widget that can accept the data. The binding script is responsible for reseting the visual appearence of the widget to its default state and to handle the dropped data. The dropped data can be obtained through the %D substitution directive.

 

SPECIFYING DROP TARGETS

In order to register a data type that can be handled by a target window, the bindtarget option can be used. For example, to handle plain dropped text, the following command can be used:


dnd bindtarget .tgt text/plain <Drop> {puts "Drop-Action=%A, Data=%D"}

When a drop occurs from a source that supports the "text/plain" type, the script associated with the <Drop> event will be executed. In this case, if the dropped data was a sentence such as "The quick brown fox jumped over the moon", the command that will be executed is:


puts {Drop-Action=copy, Data="The quick brown fox jumped over the moon"}

You can specify anything as a data type. The recommended names that can be used as data types are the corresponding MIME types. Internally, the MIME types will be converted to the apropriate types understood by the operating system. For example, if the user requests the type text/plain, the dnd command passes the type "text/plain" to the X server under unix (the XDND protocol defines types by their mime type names). But under windows, the type CF_TEXT will be registered. CF_TEXT is a special type that represents all simple ASCII text that can be dragged and dropped. Creating a handler for CF_TEXT on a window will allow that window to handle text drags and drops from another OLE enabled application that also uses the standard CF_TEXT mechanism. The user can also request explicitly to use the type "CF_TEXT". But such an approach will not be portable.

Some common types the are currently supported by the current version of tkDND are "text/uri-list" for dragging and dropping files, "text/plain;charset=utf-8" for handling utf-8 text and "image/xpm" for transfering images. Please refer to the section "DRAG AND DROP TYPES" for more information. Some other Windows specific common types for dragging and dropping to and from web browsers are "UniformResourceLocator" and "Netscape Bookmark". The type "FileName" is used by Explorer to drag and drop a single file. (Note that this type will transfer a single file. Many files (or just one file) can be transfered with the predefined type "text/uri-list")

You can register more than a single type to be handled by a window. Just run the command again with a different data type. Here is another example for the same window:


dnd bindtarget .tgt TK_COLOR <Drop> {.tgt config -bg %D}

In this case, if a an object gets dropped on window .tgt, .tgt will ask the source if it supports either text/plain or TK_COLOR. If it does, it will run the script for the match. It is possible that more than one type would be matched between the source and target. For this case, you can use the priority option to specify the order in which you want the search for matches to occur. Priorities range from 1 to 100. 1 is the highest priority, 50 is the default priority, and 100 is the lowest priority. If two target data types have the same priority, it is undetermined which one will be checked for first. In the above example, if you want to check for the TK_COLOR datatype before text/plain, give a higher priority to the TK_COLOR datatype:


dnd bindtarget .tgt TK_COLOR <Drop> {.tgt config -bg %D} 1

 

SPECIFYING DRAG SOURCES

For drag sources, the data types that can be provided by a window can be registered with the bindsource option. For example, in order to register a window as a drop source for ASCII text, the follwowing command can be used:


dnd bindsource .src text/plain {return "Some text"}

More than one datatype can be registered with a source window. To go along with our example, setup the window as a provider of data of type "TK_COLOR":


dnd bindsource .src TK_COLOR {return red}

 

THE DRAG OPERATION

Now that both the target window and the source window have been configured, one as a data source and the other as a drop area, we still need to do something to initiate the drag operation. If the application that is being dragged from is not part of Tk, we let it handle the drag & drop operation. If we want to drag something from the ".src" window to the ".tgt" window, we must initiate the drag and drop operation with the drag option. Here, we start the operation on a press of mouse button 1.


bind .src <1> {dnd drag %W}

Once button 1 is pressed on the ".src" window, the drag operation begins. When the button is released, a different button is pressed, or a modifier key is pressed during the operation, then a drop operation occurs. If the drop occurs over a window that has a type that matches the source window, then the script for the source window gets run first. If you do not want the source window to send data, it can do a:


return -code break

If the return value is not an error or a break code, the target window script for the matched datatype is then run. For the example above, the datatype that matched would be "TK_COLOR". First, the script registered for data type "TK_COLOR" on window ".src" would be executed. This is the "return red" statement. The string "red" will now substitute the "%D" token to the command for the datatype "TK_COLOR" on the target window .tgt. The command that will be executed will be:



In our simple example, the background color of the .tgt window will be changed to red on a drag and drop operation from the .src window to the .tgt window.

 

BUGS

Unix:
During drops from Motif applications, the only action that is allowed is the copy action.

If during a drag operation the mouse pointer is over a foreign window and the application that owns the window crashes, we may end with a BadWindow error, as it is very possible messages delivered to that window to exist in the message queue of the X Server.

 

KEYWORDS

dnd, drag and drop, shape, update kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/doc/License.txt0000644000175000017500000000317510562163641023042 0ustar domibeldomibelThis software (tkdnd) is copyrighted by: George Petasis, National Centre for Scientific Research "Demokritos", Aghia Paraskevi, Athens, Greece. e-mail: petasis@iit.demokritos.gr and Laurent Riesterer, Rennes, France. e-mail: (laurent.riesterer@free.fr) The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/doc/FAQ.txt0000644000175000017500000000325210562163641022063 0ustar domibeldomibel SOME COMMON PROBLEMS AND THEIR ANSWERS --------------------------------------------- George Petasis, petasis@iit.demokritos.gr 1) What is tkdnd? "tkdnd" is a tk extension that adds native support for drag and drop (dnd) under some platforms (typically unix and windows). Under unix there is support for the Motif and the XDND protocol. Under windows, OLE dnd is used. 2) I have a widget that is able to accept a specific type as a drop target, but dropping on this widget from another application does not seem to work correctly. What is wrong? Try to define a binding script for the event. Remember that a well behaved drop target widget must have a binding script for each one of the following events: , , . is not important for drag & drop, but it is important for reseting the widget to its normal appearence. ## UNIX Related Questions: ----------------------------------- 3) Other Unix applications do not recognise my toplevels as drop targets. I am able to use dnd within the same tk application, but not with other apps. You probably have forget to call "update" before defining drag sources/drop targets. Usually, after doing a drag from a tk toplevel, the widgets in this toplevel are then recognised by other applications as drop targets. Make sure that you use "update" before using the "dnd" command on any tk widget. The recomended strategy is to first create all widgets in the window, place them, call update and then arrange the dnd stuff... ## Windows Related Questions: ---------------------------------- None. kwwidgets-1.0.0~cvs20100930/Utilities/tkdnd/vtkKWTkDnDTclLibrary.h0000644000175000017500000003715310562126346024252 0ustar domibeldomibel/* * Resource generated for file: * tkdnd.tcl (zlib, base64) (text file) */ static const unsigned long file_tkdnd_tcl_length = 3784; static const unsigned long file_tkdnd_tcl_decoded_length = 10950; static const unsigned char file_tkdnd_tcl[] = "eNrtWW1X28oR/u5fMRdMmrTgvH3jpmmFbYJOwXYtOYRDOD6ytRgVWXIlGXB9/d/7zO7qzS" "9A7o2TfijHB0va3ZlnnpnZGa13K7uU3LqBW0uGPh0c4BYf/Nk3XkzXni/IG098MRZBElMc" "jgVNE8/3khlNonAo3GkkYkpunIScCGOxcGkwwwNB9m2j1VDCJs7w1hmJWmUX91JyHF4n97" "wC18NwMou80U0i1x5iyicRRiNBHZE4sRfvU8tJvDBwfKoDBhZdhxFZQw833rU3pK6IhRMN" "b2inIcbhbeQlYbyzDznG6MZzqONETnwr7rx9MgAsgMBPkRBDxkPiYOx4/iFNlK6/e15Scz" "MptVGkMbNS3w/vvWBEiYjGMTmTiQ9LQ3J8XzKFR3EcDj0HhmDNvZfcSCIyW6cBJsUkHia+" "N/QSrHa9eOg73hiWewE+rnfnuVNHy6tlup1pchNGMd2ISIDeUeQECSBHYy+OwQyjAPX7ks" "p9Goeud41vSE8ibzBNBJPhBC5BL+wXgFX0AY94cK8bDqfsaMm2JNkJ4OdpNAlZOBwOdNI2" "6XDxAPnMR+ZACsIEGmIZCxEY9QJlGVOEWR4PQZlczhggSi3hOPCCoT+FfLoT0QAYxnJlMM" "vtAKy4Rq2Q7uGdRGB0BEcyZDZQG7dPAB6FM8dHkF4LKToS/556EUSnRoXX0jWKV+8/GAF/" "TDidMXneUHIQM7FlrsbOjAZiKWZZlhelXtJcBwJjsE4HjtSnIOYx5Ip4CMswkT2bUywZkj" "wLyLlPIw76hz5CHZHDsTLkSCN2P4enF8WICaQZGyccpINM33uWrETNVMzWVJKbLWq1qfm5" "2bLJOjFOT8k+aZLRs0/aXYvaXWqYlt01j3o23x816dQ0jk6bZLfJaF1Qx+jaFxBzLGd2m3" "V7HyLTK6vTrJvGKT+qmw2o4GvMrLdbVvOfPTzAKDWMM+NT0+JM7ZqW2fpE7Z5N7WOJpGc1" "1aVpkdU+ts+NbhPybIsa7XrvjGXaZrslxQIQhDSaXfMzHn5uWiyh22wf70sDyTwuGXdifG" "7CIgwYjc+m1WxonZDRaVuWeWSemvYFP7R69RMNU9NWlGO0GmWWpNnHZh1sXvBI/dQwzyRd" "QN81YHXT2pfc1097DRi8T1gJP9hg98y0gcRu70sd5lnn1MR9vpDxnDW79RPcGgoiyzo27V" "bTsqQjDOkWs947NbrU6XVhDThjmK1268BsHXehs8nc1ajMLIOyqNNtf4a7wAeoadGOYeHp" "Dh0ZlmkpOY+az7xCEMKqfXRqfpL+4XjRYunMMFt2s2W06kBl9Tqddhex0us0DBu8ULN1wk" "MMz2K3cja2G5JPlmTxfljRtSRNaZSZSiVwxiLGgCBxh81TFjSaV4junMhzBsiCfhJO7mmn" "5kbOaKc84AzCSVx6FGMHFKUnD29Kt7Py7cR3Emws436GozTsRuGkz7nYT8R40ne9qDSMXS" "PsTycudNLbCoYGyG1VPfsNwH1LH46mSRIGHZTa+ODtR5pLAw8P+wMx8oI+24Sdg0sL7Z3T" "Xkx7X2jvYrFe1NuDs5D3to9cmNeKGsvxJ0S9K6N69wdQsah33wfV+zKq938AFYt6/ztR4b" "OLZur7/UmBVA/HY1k+FQ4v8BLP8b1YHJKZXee9V952bQEOd3+UI6A5qnREC5l1T+bGk9lB" "NPLDAVJZBHcVeb/LXWFCvVhEf0IfxI0opophEkazQzqH2ZFsxvyQq6IkARDRIoEF9GHXUT" "gmh2KICK9TgRDuRWEgWx4/gxTXajU5A7BlGcUAzU/aZ03ifx3DPuHa1MWmdmyiHmKv51sr" "u+/wfmakVBB51zS/9ILrUHVMMet9WYXUV1f5JD1NddxxZhpV108maQqzcQIqGqA+n1iYNI" "AFt9n9olL8XqQ09AIXNKGzdcP7mO4F3Th3QjW2cYhOZ4zMENL2Buprk15kPKRMMfRfSiYW" "kF3RixeUY7rkXg4NELZvkF7Fa0cWIy/Ti1cpGl5bWJprkBxmkF5JHeuGGWWRuUdIzqVVN6" "3ewPqmlevpPmF2wbKKVFf3eIK7Pg7Vvz2D0RzRMp7Lyb17VdCXKrVL2eEQ51oYOdEsz6K1" "YW//g/dDu3nW6aO1I74g+6zz/YNbOlA1rOjt5dbwaOiv2Td+bwqscr1GeAFCSpDUeelzuF" "ULPnh9CpJ9skTCL0fxaxsS6HWCf18zGPXD1+doltvnlhrGffrNExtLw43D7BvDV0/zKhGv" "o3TJlEfZzPbibRG5UTOzaUwmDa1fSd80W5kY4IXtThq4qjHPhBgv5fBc9fBww76TQpsG3g" "NudjOSwmmE9rIKca99b8CZ81qW4T7P5MOT0haxpuzRA2bnAv3QcTNxUtK7NzVst+rUpMxx" "ujU/C4+e/CxIoS+eBuXi3X0V1UKt2owDdQPbmYax+HW30CxU0v4BFb0Bdx3DWxzfjSyA52" "s6iQ2NQiSSaRSsdXxFgZWqrM2q1jcuG9RtjNlcX4WtzUmWdFQq37kDW20HuR/tK398b2WS" "wVU14G4cukJ1WHNKZhOBIF0wmXgRQ1dFb2mhqWXeEmcU0yX32fKqyuuu9JjnPqDA+/ogry" "on7OTd+J935ESVvgcHVJWK5zoCRths0MIUaxJVWeIvf6WDt1Tc78raoTESSAwOYfWUV8l/" "ue6qtOUqDX8SfiwekTgMAxRZLW+jlMIWqHi7zPIznoghH0H11UBVfl0VFoS+q8ckmVrxhw" "+sxpKesXn048erpYrFi7S85RqSMZ8LlxOv6AO9AYG+M5kI6FoaXizZ8ziegvTCxj4NtuLB" "q5UKtZCZuSZdfkRyYsdInGgkku0mZ6Zmc3LqhFybS98YjyuOe3aBzUps3mD0U2mpIuXfe9" "lQJOHERwb5etfQKFbakWKxLEjuaskckVwGlJRic8Nx+6Eh8HISzj5q1fO/pLxCwF14K7Ll" "e+eLDZ3QUxkaTmzpnv+VDF3C8+wM/f2OftJVJabLjvpGY+Ybcz/Pxu3nfuG8aJu5XzyWSu" "uvrtPyQJO+0IXO/ecebKqD0PJmoQQrl6mDtFI7//CGL6tfis9m6tlF8ZmCtCMl7BRCTR+o" "lQrB0juFXHpVqgn6V0V8/jXlt/+HJHK470vQ5EFcjX9Ei8CDEGN+DR6IwspI/qzixEgY+V" "uJfCHXMNDE4vFAcHrqMyXgrWWrVfO5FJQS89IxR9neMng53xnEL6tg76D65RV9pPf022/6" "2QzPLtSzNS9uWq4bBmKnmEbcbatYqKY9uppa/ZJ7Yt1rXClRiqH7AxIlA73VPMmpmZcTJA" "rD5Iv8nybKLtX5p0v2vGpn+Jy1Pnaxt/DWAwfXdP86HLvpXq9lLi3gnV7u4zowfBGMsG1V" "sTB7Jc4E6TljZ6IPGPbOM7l7cKBCunehri4KJwt7VurovVXMewZ9nX9dFKcna1GXu8grhT" "KDKLPxcqoL8tfdN4Vx3bnxDLRuOzu0em6CYB/qX1dlmXKdxME0tWiuzhn+WIOs5NNlvxHm" "hSRNg1S5rrJVVp8u7qOAlrMGHZNeIS8lVr7QyaQcobywIYXyoP4BGZTi32oCZSRl+aNbTk" "2UbGIkU9jtpn5S2JfKf5vSjn2onr4p3F3Iu5WUbAbuN2VkOv/nJWSGWOajDq+vi/+n2XKa" "bcioLMi3n1AbyNhmem3iP32HW27h1v7Cpk/FLqvzNeMLcPiUlxe/0u5TJPxA+pHGgt9u0H" "v+QA+saN2WE1YVPeqHVTZ+Vib8+ETQLthqGugX62ckwc/MgZ+SAluif0XNYx5YIeK/DZSo" "bg=="; /* * Resource generated for file: * tkdnd_compat.tcl (zlib, base64) (text file) */ static const unsigned long file_tkdnd_compat_tcl_length = 2364; static const unsigned long file_tkdnd_compat_tcl_decoded_length = 6191; static const unsigned char file_tkdnd_compat_tcl[] = "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"; /* * Resource generated for file: * tkdnd_unix.tcl (zlib, base64) (text file) */ static const unsigned long file_tkdnd_unix_tcl_length = 3896; static const unsigned long file_tkdnd_unix_tcl_decoded_length = 14323; static const unsigned char file_tkdnd_unix_tcl[] = "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"; /* * Resource generated for file: * tkdnd_windows.tcl (zlib, base64) (text file) */ static const unsigned long file_tkdnd_windows_tcl_length = 3800; static const unsigned long file_tkdnd_windows_tcl_decoded_length = 14766; static const unsigned char file_tkdnd_windows_tcl[] = "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" "3Sj8YEMcbDX+D8bYe70="; kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/0000755000175000017500000000000011461110203021044 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/shellicon/0000755000175000017500000000000011461110203023024 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/shellicon/pkgIndex.tcl0000644000175000017500000000020610562100027025303 0ustar domibeldomibelif {[catch {package require Tcl 8.4}]} return package ifneeded shellicon 2.2.1 [list load [file join $dir shellicon22.dll] shellicon] kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/shellicon/shellicon.c0000644000175000017500000005513511044115431025166 0ustar domibeldomibel/* * shellicon.c -- * * This is a Tk extension that adds a new element type to TkTreeCtrl. * The element type's name is "shellicon". A shellicon element can * display the icon for a file or folder using Win32 Shell API calls. * * Copyright (c) 2005 Tim Baker * * RCS: @(#) $Id: shellicon.c,v 1.2 2008-07-30 16:47:21 barre Exp $ */ #include "tkTreeCtrl.h" #include "tkTreeElem.h" #include "tkWinInt.h" #ifndef _WIN32_IE #define _WIN32_IE 0x0501 #endif #include #include #include #include #ifndef SHGFI_ADDOVERLAYS #if (_WIN32_IE >= 0x0500) #define SHGFI_ADDOVERLAYS 0x000000020 #define SHGFI_OVERLAYINDEX 0x000000040 #endif #endif #ifndef SHIL_LARGE #define SHIL_LARGE 0 #define SHIL_SMALL 1 #define SHIL_EXTRALARGE 2 #if 0 const GUID IID_IImageList = {0x2C247F21, 0x8591, 0x11D1,{ 0xB1, 0x6A, 0x00,0xC0, 0xF0, 0x28,0x36, 0x28} }; HRESULT (*SHGetImageListProc)(int iImageList, REFIID riid, void **ppv); #endif #endif HIMAGELIST gImgListSmall = NULL; HIMAGELIST gImgListLarge = NULL; TreeCtrlStubs *stubs; extern int BooleanCO_Init(Tk_OptionSpec *, CONST char *); extern int TreeCtrl_RegisterElementType(Tcl_Interp *, ElementType *); #if 0 #define TreeCtrl_RegisterElementType(i,t) \ stubs->TreeCtrl_RegisterElementType(i,t) #define Tree_RedrawElement(t,i,e) \ stubs->Tree_RedrawElement(t,i,e) #define Tree_ElementIterateBegin(t,et) \ stubs->Tree_ElementIterateBegin(t,et) #define Tree_ElementIterateNext(i) \ stubs->Tree_ElementIterateNext(i) #define Tree_ElementIterateGet(i) \ stubs->Tree_ElementIterateGet(i) #define Tree_ElementIterateChanged(i,m) \ stubs->Tree_ElementIterateChanged(i,m) #define PerStateInfo_Free(t,ty,in) \ stubs->PerStateInfo_Free(t,ty,in) #define PerStateInfo_FromObj(t,pr,ty,in) \ stubs->PerStateInfo_FromObj(t,pr,ty,in) #define PerStateInfo_ForState(t,ty,in,st,ma) \ stubs->PerStateInfo_ForState(t,ty,in,st,ma) #define PerStateInfo_ObjForState(t,ty,in,st,ma) \ stubs->PerStateInfo_ObjForState(t,ty,in,st,ma) #define PerStateInfo_Undefine(t,ty,in,st) \ stubs->PerStateInfo_Undefine(t,ty,in,st) #define pstBoolean \ (*stubs->pstBoolean) #define PerStateBoolean_ForState(t,in,st,ma) \ stubs->PerStateBoolean_ForState(t,in,st,ma) #define PSTSave(in,sa) \ stubs->PSTSave(in,sa) #define PSTRestore(t,ty,in,sa) \ stubs->PSTRestore(t,ty,in,sa) #define TreeStateFromObj \ stubs->TreeStateFromObj #define BooleanCO_Init(ot,on) \ stubs->BooleanCO_Init(ot,on) #define StringTableCO_Init(ot,on,ta) \ stubs->StringTableCO_Init(ot,on,ta) #endif static void AdjustForSticky(int sticky, int cavityWidth, int cavityHeight, int expandX, int expandY, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr) { int dx = 0; int dy = 0; if (cavityWidth > *widthPtr) { dx = cavityWidth - *widthPtr; } if (cavityHeight > *heightPtr) { dy = cavityHeight - *heightPtr; } if ((sticky & STICKY_W) && (sticky & STICKY_E)) { if (expandX) *widthPtr += dx; else sticky &= ~(STICKY_W | STICKY_E); } if ((sticky & STICKY_N) && (sticky & STICKY_S)) { if (expandY) *heightPtr += dy; else sticky &= ~(STICKY_N | STICKY_S); } if (!(sticky & STICKY_W)) { *xPtr += (sticky & STICKY_E) ? dx : dx / 2; } if (!(sticky & STICKY_N)) { *yPtr += (sticky & STICKY_S) ? dy : dy / 2; } } /* This macro gets the value of a per-state option for an element, then * looks for a better match from the master element if it exists */ #define OPTION_FOR_STATE(xFUNC,xTYPE,xVAR,xFIELD,xSTATE) \ xVAR = xFUNC(tree, &elemX->xFIELD, xSTATE, &match); \ if ((match != MATCH_EXACT) && (masterX != NULL)) { \ xTYPE varM = xFUNC(tree, &masterX->xFIELD, xSTATE, &match2); \ if (match2 > match) \ xVAR = varM; \ } #define BOOLEAN_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateBoolean_ForState,int,xVAR,xFIELD,xSTATE) /* This macro gets the object for a per-state option for an element, then * looks for a better match from the master element if it exists */ #define OBJECT_FOR_STATE(xVAR,xTYPE,xFIELD,xSTATE) \ xVAR = PerStateInfo_ObjForState(tree, &xTYPE, &elemX->xFIELD, xSTATE, &match); \ if ((match != MATCH_EXACT) && (masterX != NULL)) { \ Tcl_Obj *objM = PerStateInfo_ObjForState(tree, &xTYPE, &masterX->xFIELD, xSTATE, &matchM); \ if (matchM > match) \ xVAR = objM; \ } typedef struct ElementShellIcon ElementShellIcon; struct ElementShellIcon { Element header; PerStateInfo draw; Tcl_Obj *pathObj; /* path of file or directory */ char *path; Tcl_Obj *widthObj; int width; Tcl_Obj *heightObj; int height; #define TYPE_DIRECTORY 0 #define TYPE_FILE 1 int type; /* If specified, 'path' is assumed to exist */ #define SIZE_LARGE 0 #define SIZE_SMALL 1 int size; /* SIZE_LARGE if unspecified */ HIMAGELIST hImgList; /* the system image list */ int iIcon; /* index into hImgList */ int addOverlays; /* only when useImgList is FALSE */ int useImgList; /* if false, create icons */ HICON hIcon; /* icon */ HICON hIconSel; /* selected icon */ }; #define SHELLICON_CONF_ICON 0x0001 #define SHELLICON_CONF_SIZE 0x0002 #define SHELLICON_CONF_DRAW 0x0004 static CONST char *sizeST[] = { "large", "small", (char *) NULL }; static CONST char *typeST[] = { "directory", "file", (char *) NULL }; static Tk_OptionSpec shellIconOptionSpecs[] = { {TK_OPTION_CUSTOM, "-addoverlays", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementShellIcon, addOverlays), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_STRING, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementShellIcon, draw.obj), -1, TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_DRAW}, {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementShellIcon, heightObj), Tk_Offset(ElementShellIcon, height), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_SIZE}, {TK_OPTION_STRING, "-path", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementShellIcon, pathObj), Tk_Offset(ElementShellIcon, path), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_CUSTOM, "-size",(char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementShellIcon, size), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_CUSTOM, "-type", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementShellIcon, type), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_CUSTOM, "-useimagelist", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementShellIcon, useImgList), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementShellIcon, widthObj), Tk_Offset(ElementShellIcon, width), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_SIZE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void LoadIconIfNeeded(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ElementShellIcon *masterX = (ElementShellIcon *) elem->master; SHFILEINFO sfi; Tcl_DString dString1, dString2; UINT uFlags = SHGFI_SYSICONINDEX; DWORD dwFileAttributes = 0; char *nativePath; int size = SIZE_LARGE; int overlays = 1; int type = -1; int useImgList = TRUE; DWORD_PTR result; /* HRESULT result; */ /* -useimagelist boolean */ if (elemX->useImgList != -1) useImgList = elemX->useImgList; else if (masterX != NULL && masterX->useImgList != -1) useImgList = masterX->useImgList; /* Not using the system image list. */ if (!useImgList) { /* Already have an icon, or no path is given so no icon used */ if ((elemX->hIcon != NULL) || (elemX->path == NULL)) return; /* Equivalent to "file nativename $path" */ nativePath = Tcl_TranslateFileName(tree->interp, elemX->path, &dString1); if (nativePath == NULL) return; /* This will be passed to system calls, so convert from UTF8 */ nativePath = Tcl_UtfToExternalDString(NULL, nativePath, -1, &dString2); uFlags = SHGFI_ICON; /* -addoverlays boolean */ if (elemX->addOverlays != -1) overlays = elemX->addOverlays; else if (masterX != NULL && masterX->addOverlays != -1) overlays = masterX->addOverlays; if (overlays) uFlags |= SHGFI_ADDOVERLAYS; /* -size small or large */ if (elemX->size != -1) size = elemX->size; else if (masterX != NULL && masterX->size != -1) size = masterX->size; switch (size) { case SIZE_LARGE: uFlags |= SHGFI_LARGEICON | SHGFI_SHELLICONSIZE; break; case SIZE_SMALL: uFlags |= SHGFI_SMALLICON | SHGFI_SHELLICONSIZE; break; } /* -type file or -type directory */ if (elemX->type != -1) type = elemX->type; else if (masterX != NULL && masterX->type != -1) type = masterX->type; /* If SHGFI_USEFILEATTRIBUTES is set, SHGetFileInfo is supposed to * assume that the file is real but not look for it on disk. This * can be used to get the icon for a certain type of file, ex *.exe. * In practice, lots of files get a non-generic icon when a * valid file path is given. */ if (type != -1) { dwFileAttributes = (type == TYPE_FILE) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_DIRECTORY; uFlags |= SHGFI_USEFILEATTRIBUTES; } /* MSDN says SHGFI_OPENICON returns the image list containing the * small open icon. In practice the large open icon gets returned * for SHGFI_LARGEICON, so we support it. */ if (/*(size == SIZE_SMALL) && */(args->state & STATE_OPEN)) uFlags |= SHGFI_OPENICON; CoInitialize(NULL); result = SHGetFileInfo( nativePath, dwFileAttributes, &sfi, sizeof(sfi), uFlags); if (result) { elemX->hIcon = sfi.hIcon; /* Remember the image list so we can get the icon size */ elemX->hImgList = (size == SIZE_LARGE) ? gImgListLarge : gImgListSmall; } result = SHGetFileInfo( nativePath, dwFileAttributes, &sfi, sizeof(sfi), uFlags | SHGFI_SELECTED); if (result) elemX->hIconSel = sfi.hIcon; CoUninitialize(); Tcl_DStringFree(&dString1); Tcl_DStringFree(&dString2); return; } /* Using the system image list */ if ((elemX->hImgList == NULL) && (elemX->path != NULL)) { /* Equivalent to "file nativename $path" */ nativePath = Tcl_TranslateFileName(tree->interp, elemX->path, &dString1); if (nativePath == NULL) return; /* This will be passed to system calls, so convert from UTF8 */ nativePath = Tcl_UtfToExternalDString(NULL, nativePath, -1, &dString2); /* -size small or large */ if (elemX->size != -1) size = elemX->size; else if (masterX != NULL && masterX->size != -1) size = masterX->size; switch (size) { case SIZE_SMALL: uFlags |= SHGFI_SMALLICON | SHGFI_SHELLICONSIZE; break; case SIZE_LARGE: uFlags |= SHGFI_LARGEICON | SHGFI_SHELLICONSIZE; break; } /* -type file or -type directory */ if (elemX->type != -1) type = elemX->type; else if (masterX != NULL && masterX->type != -1) type = masterX->type; /* If SHGFI_USEFILEATTRIBUTES is set, SHGetFileInfo is supposed to * assume that the file is real but not look for it on disk. This * can be used to get the icon for a certain type of file, ex *.exe. * In practice, lots of files get a non-generic icon when a * valid file path is given. */ if (type != -1) { dwFileAttributes = (type == TYPE_FILE) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_DIRECTORY; uFlags |= SHGFI_USEFILEATTRIBUTES; } /* MSDN says SHGFI_OPENICON returns the image list containing the * small open icon. In practice the large open icon gets returned * for SHGFI_LARGEICON. */ if (/*(size == SIZE_SMALL) && */(args->state & STATE_OPEN)) uFlags |= SHGFI_OPENICON; CoInitialize(NULL); elemX->hImgList = (HIMAGELIST) SHGetFileInfo( nativePath, dwFileAttributes, &sfi, sizeof(sfi), uFlags); if (elemX->hImgList != NULL) { elemX->iIcon = sfi.iIcon; } CoUninitialize(); Tcl_DStringFree(&dString1); Tcl_DStringFree(&dString2); } } static void ForgetIcon(ElementShellIcon *elemX) { if (elemX->hIcon != NULL) DestroyIcon(elemX->hIcon); if (elemX->hIconSel != NULL) DestroyIcon(elemX->hIconSel); elemX->hImgList = NULL; elemX->hIcon = elemX->hIconSel = NULL; } static void DeleteProcShellIcon(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; PerStateInfo_Free(tree, &pstBoolean, &elemX->draw); ForgetIcon(elemX); } static int WorldChangedProcShellIcon(ElementArgs *args) { ElementShellIcon *elemX = (ElementShellIcon *) args->elem; int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & (SHELLICON_CONF_ICON | SHELLICON_CONF_SIZE)) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & (SHELLICON_CONF_DRAW)) mask |= CS_DISPLAY; if ((flagS | flagM) & SHELLICON_CONF_ICON) { ForgetIcon(elemX); } return mask; } static int ConfigProcShellIcon(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ElementShellIcon savedX; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } if (args->config.flagSelf & SHELLICON_CONF_DRAW) PSTSave(&elemX->draw, &savedX.draw); if (args->config.flagSelf & SHELLICON_CONF_DRAW) { if (PerStateInfo_FromObj(tree, TreeStateFromObj, &pstBoolean, &elemX->draw) != TCL_OK) continue; } if (args->config.flagSelf & SHELLICON_CONF_DRAW) PerStateInfo_Free(tree, &pstBoolean, &savedX.draw); Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); if (args->config.flagSelf & SHELLICON_CONF_DRAW) PSTRestore(tree, &pstBoolean, &elemX->draw, &savedX.draw); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcShellIcon(ElementArgs *args) { ElementShellIcon *elemX = (ElementShellIcon *) args->elem; elemX->type = -1; elemX->size = -1; elemX->addOverlays = -1; elemX->useImgList = -1; return TCL_OK; } static void DisplayProcShellIcon(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ElementShellIcon *masterX = (ElementShellIcon *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width, height; int match, match2; int draw; HDC hDC; TkWinDCState dcState; UINT fStyle = ILD_TRANSPARENT; HICON hIcon; BOOLEAN_FOR_STATE(draw, draw, state) if (!draw) return; LoadIconIfNeeded(args); if (elemX->hImgList == NULL) return; (void) ImageList_GetIconSize(elemX->hImgList, &width, &height); AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); hDC = TkWinGetDrawableDC(tree->display, args->display.drawable, &dcState); hIcon = (state & STATE_SELECTED) ? elemX->hIconSel : elemX->hIcon; if (hIcon != NULL) { #if 1 /* If DI_DEFAULTSIZE is used, small icons get stretched */ DrawIconEx(hDC, x, y, hIcon, 0, 0, FALSE, NULL, DI_IMAGE | DI_MASK /*| DI_DEFAULTSIZE*/); #else /* Works fine for large, but not for small (they get stretched) */ DrawIcon(hDC, x, y, hIcon); #endif } else { if (state & STATE_SELECTED) fStyle |= ILD_SELECTED; ImageList_Draw(elemX->hImgList, elemX->iIcon, hDC, x, y, fStyle); } TkWinReleaseDrawableDC(args->display.drawable, hDC, &dcState); /* If this is a master element, forget the icon being used because the * appearance may change between items based on the open state */ if (masterX == NULL) { ForgetIcon(elemX); } } static void NeededProcShellIcon(ElementArgs *args) { Element *elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ElementShellIcon *masterX = (ElementShellIcon *) elem->master; int width = 0, height = 0; int size = SIZE_LARGE; HIMAGELIST hImgList = NULL; /* The icon is not loaded until it is actually going to be displayed. * This is a good thing since loading the icons can take a while */ /* LoadIconIfNeeded(args);*/ if (elemX->hImgList != NULL) { hImgList = elemX->hImgList; } else if (elemX->path != NULL) { if (elemX->size != -1) size = elemX->size; else if (masterX != NULL && masterX->size != -1) size = masterX->size; switch (size) { case SIZE_SMALL: hImgList = gImgListSmall; break; case SIZE_LARGE: hImgList = gImgListLarge; break; } } if (hImgList != NULL) { (void) ImageList_GetIconSize(hImgList, &width, &height); } if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; args->needed.width = width; args->needed.height = height; } static int StateProcShellIcon(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ElementShellIcon *masterX = (ElementShellIcon *) elem->master; int match, match2; int draw1, draw2; int sel1, sel2; int open1, open2; int mask = 0; BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) if (draw1 == -1) draw1 = 1; open1 = (args->states.state1 & STATE_OPEN) != 0; sel1 = (args->states.state1 & STATE_SELECTED) != 0; BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if (draw2 == -1) draw2 = 1; open2 = (args->states.state2 & STATE_OPEN) != 0; sel2 = (args->states.state2 & STATE_SELECTED) != 0; if (elemX->path == NULL) open1 = open2 = sel1 = sel2 = 0; if ((draw1 != draw2) || (sel1 != sel2) || (open1 != open2)) mask |= CS_DISPLAY; /* Directories may have an open and closed icon. */ if (open1 != open2) { ForgetIcon(elemX); } return mask; } static int UndefProcShellIcon(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementShellIcon *elemX = (ElementShellIcon *) args->elem; int modified = 0; modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); return modified; } static int ActualProcShellIcon(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementShellIcon *elemX = (ElementShellIcon *) args->elem; ElementShellIcon *masterX = (ElementShellIcon *) args->elem->master; static CONST char *optionName[] = { "-draw", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } ElementType elemTypeShellIcon = { "shellicon", sizeof(ElementShellIcon), shellIconOptionSpecs, NULL, CreateProcShellIcon, DeleteProcShellIcon, ConfigProcShellIcon, DisplayProcShellIcon, NeededProcShellIcon, NULL, /* heightProc */ WorldChangedProcShellIcon, StateProcShellIcon, UndefProcShellIcon, ActualProcShellIcon, NULL /* onScreenProc */ }; DLLEXPORT int Shellicon_Init(Tcl_Interp *interp) { #if 1 SHFILEINFO sfi; #else HMODULE hLib; #endif #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, "8.4", 0) == NULL) { return TCL_ERROR; } #endif #ifdef USE_TK_STUBS if (Tk_InitStubs(interp, "8.4", 0) == NULL) { return TCL_ERROR; } #endif /* InitCommonControlsEx must be called to use the ImageList functions */ /* This is already done by Tk on NT */ if (TkWinGetPlatformId() != VER_PLATFORM_WIN32_NT) { INITCOMMONCONTROLSEX comctl; ZeroMemory(&comctl, sizeof(comctl)); (void) InitCommonControlsEx(&comctl); } #if 1 /* Get the sytem image lists (small and large) */ CoInitialize(NULL); gImgListSmall = (HIMAGELIST) SHGetFileInfo(".exe", FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_SMALLICON); gImgListLarge = (HIMAGELIST) SHGetFileInfo(".exe", FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_LARGEICON); CoUninitialize(); #else /* FIXME: WinXP only */ /* This is broken somewhere */ hLib = LoadLibraryA("shell32"); SHGetImageListProc = (FARPROC) GetProcAddress(hLib, (LPCSTR) 727); SHGetImageListProc(SHIL_SMALL, &IID_IImageList, &gImgListSmall); SHGetImageListProc(SHIL_LARGE, &IID_IImageList, &gImgListLarge); SHGetImageListProc(SHIL_EXTRALARGE, &IID_IImageList, &gImgListXtraLarge); dbwin("small %p large %p xtralarge %p\n", gImgListSmall, gImgListLarge, gImgListXtraLarge); FreeLibrary(hLib); #endif /* Load TkTreeCtrl */ if (Tcl_PkgRequire(interp, "treectrl", "2.2.1", TRUE) == NULL) return TCL_ERROR; /* Get the stubs table from TkTreeCtrl */ stubs = Tcl_GetAssocData(interp, "TreeCtrlStubs", NULL); if (stubs == NULL) return TCL_ERROR; /* Initialize the options table */ BooleanCO_Init(shellIconOptionSpecs, "-addoverlays"); BooleanCO_Init(shellIconOptionSpecs, "-useimagelist"); StringTableCO_Init(shellIconOptionSpecs, "-size", sizeST); StringTableCO_Init(shellIconOptionSpecs, "-type", typeST); /* Add the "shellicon" element type */ if (TreeCtrl_RegisterElementType(interp, &elemTypeShellIcon) != TCL_OK) return TCL_ERROR; if (Tcl_PkgProvide(interp, "treectrl", "2.2.1") != TCL_OK) { return TCL_ERROR; } return TCL_OK; } DLLEXPORT int Shellicon_SafeInit(Tcl_Interp *interp) { return Shellicon_Init(interp); } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/0000755000175000017500000000000011461110203022460 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeNotify.c0000644000175000017500000005065710674273024025310 0ustar domibeldomibel/* * tkTreeNotify.c -- * * This module implements "qebind.c" events for treectrl widgets. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: tkTreeNotify.c,v 1.2 2007-09-19 19:18:44 barre Exp $ */ #include "tkTreeCtrl.h" #include "tclInt.h" /* TclFormatInt */ static int EVENT_EXPAND, DETAIL_EXPAND_BEFORE, DETAIL_EXPAND_AFTER; static int EVENT_COLLAPSE, DETAIL_COLLAPSE_BEFORE, DETAIL_COLLAPSE_AFTER; static int EVENT_SELECTION; static int EVENT_ACTIVEITEM; static int EVENT_SCROLL, DETAIL_SCROLL_X, DETAIL_SCROLL_Y; static int EVENT_ITEM_DELETE; static int EVENT_ITEM_VISIBILITY; /* *---------------------------------------------------------------------- * * ExpandItem -- * * Append an item ID to a dynamic string. * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void ExpandItem( TreeCtrl *tree, /* Widget info. */ int id, /* Item ID. */ Tcl_DString *result /* Gets appended. Caller must initialize. */ ) { if (tree->itemPrefixLen) { char buf[10 + TCL_INTEGER_SPACE]; (void) sprintf(buf, "%s%d", tree->itemPrefix, id); Tcl_DStringAppend(result, buf, -1); } else QE_ExpandNumber(id, result); } /* *---------------------------------------------------------------------- * * DumpPercents -- * * Appends a sublist to a dynamic string. The sublist contains * %-char,value pairs. This is to handle the %? substitution. * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void DumpPercents( QE_ExpandArgs *args, /* %-substitution args. */ QE_ExpandProc proc, /* Function to return value for a given * %-char. */ CONST char *chars /* NULL-terminated list of %-chars. */ ) { char which = args->which; char buf[2]; int i; buf[1] = '\0'; Tcl_DStringStartSublist(args->result); for (i = 0; chars[i]; i++) { args->which = chars[i]; buf[0] = chars[i]; Tcl_DStringAppendElement(args->result, buf); Tcl_DStringAppend(args->result, " ", 1); (*proc)(args); } Tcl_DStringEndSublist(args->result); args->which = which; } /* *---------------------------------------------------------------------- * * Percents_Any -- * * Append a value for a single %-char to a dynamic string. This * function handles the default %-chars (d,e,P,W,T, and ?) and * calls QE_ExpandUnknown() for any unrecognized %-char. * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_Any( QE_ExpandArgs *args, /* %-substitution args. */ QE_ExpandProc proc, /* Function to return value for a given * %-char. */ CONST char *chars /* NULL-terminated list of %-chars. */ ) { struct { TreeCtrl *tree; } *data = args->clientData; char chars2[64]; switch (args->which) { case 'd': /* detail */ QE_ExpandDetail(args->bindingTable, args->event, args->detail, args->result); break; case 'e': /* event */ QE_ExpandEvent(args->bindingTable, args->event, args->result); break; case 'P': /* pattern */ QE_ExpandPattern(args->bindingTable, args->event, args->detail, args->result); break; case 'W': /* object */ QE_ExpandString((char *) args->object, args->result); break; case 'T': /* tree */ QE_ExpandString(Tk_PathName(data->tree->tkwin), args->result); break; case '?': strcpy(chars2, "TWPed"); strcat(chars2, chars); DumpPercents(args, proc, chars2); break; default: QE_ExpandUnknown(args->which, args->result); break; } } /* *---------------------------------------------------------------------- * * Percents_Expand -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_Expand( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ int id; } *data = args->clientData; switch (args->which) { case 'I': ExpandItem(data->tree, data->id, args->result); break; default: Percents_Any(args, Percents_Expand, "I"); break; } } /* *---------------------------------------------------------------------- * * Percents_ItemVisibility -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_ItemVisibility( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *v; TreeItemList *h; } *data = args->clientData; TreeCtrl *tree = data->tree; TreeItemList *table; int i, count; switch (args->which) { case 'v': case 'h': table = (args->which == 'v') ? data->v : data->h; Tcl_DStringStartSublist(args->result); count = TreeItemList_Count(table); for (i = 0; i < count; i++) { TreeItem item = TreeItemList_Nth(table, i); if (tree->itemPrefixLen) { char buf[10 + TCL_INTEGER_SPACE]; (void) sprintf(buf, "%s%d", tree->itemPrefix, TreeItem_GetID(tree, item)); Tcl_DStringAppendElement(args->result, buf); } else { char string[TCL_INTEGER_SPACE]; TclFormatInt(string, TreeItem_GetID(tree, item)); Tcl_DStringAppendElement(args->result, string); } } Tcl_DStringEndSublist(args->result); break; default: Percents_Any(args, Percents_ItemVisibility, "vh"); break; } } /* *---------------------------------------------------------------------- * * Percents_Selection -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_Selection( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *select; TreeItemList *deselect; int count; } *data = args->clientData; TreeCtrl *tree = data->tree; TreeItemList *itemList; int i, count; switch (args->which) { case 'c': QE_ExpandNumber(data->count, args->result); break; case 'D': case 'S': itemList = (args->which == 'D') ? data->deselect : data->select; if (itemList == NULL) { Tcl_DStringAppend(args->result, "{}", 2); break; } Tcl_DStringStartSublist(args->result); count = TreeItemList_Count(itemList); for (i = 0; i < count; i++) { TreeItem item = TreeItemList_Nth(itemList, i); if (tree->itemPrefixLen) { char buf[10 + TCL_INTEGER_SPACE]; (void) sprintf(buf, "%s%d", tree->itemPrefix, TreeItem_GetID(tree, item)); Tcl_DStringAppendElement(args->result, buf); } else { char string[TCL_INTEGER_SPACE]; TclFormatInt(string, TreeItem_GetID(tree, item)); Tcl_DStringAppendElement(args->result, string); } } Tcl_DStringEndSublist(args->result); break; default: Percents_Any(args, Percents_Selection, "cSD"); break; } } /* *---------------------------------------------------------------------- * * Percents_ActiveItem -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_ActiveItem( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ int prev; int current; } *data = args->clientData; switch (args->which) { case 'c': ExpandItem(data->tree, data->current, args->result); break; case 'p': ExpandItem(data->tree, data->prev, args->result); break; default: Percents_Any(args, Percents_ActiveItem, "cp"); break; } } /* *---------------------------------------------------------------------- * * Percents_Scroll -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_Scroll( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ double lower; double upper; } *data = args->clientData; switch (args->which) { case 'l': QE_ExpandDouble(data->lower, args->result); break; case 'u': QE_ExpandDouble(data->upper, args->result); break; default: Percents_Any(args, Percents_Scroll, "lu"); break; } } /* *---------------------------------------------------------------------- * * TreeNotifyCmd -- * * This procedure is invoked to process the [notify] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeNotifyCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandName[] = { "bind", "configure", "detailnames", "eventnames", "generate", "install", "linkage", "unbind", "uninstall", (char *) NULL }; enum { COMMAND_BIND, COMMAND_CONFIGURE, COMMAND_DETAILNAMES, COMMAND_EVENTNAMES, COMMAND_GENERATE, COMMAND_INSTALL, COMMAND_LINKAGE, COMMAND_UNBIND, COMMAND_UNINSTALL }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandName, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_BIND: { return QE_BindCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_CONFIGURE: { return QE_ConfigureCmd(tree->bindingTable, 2, objc, objv); } /* T notify detailnames $eventName */ case COMMAND_DETAILNAMES: { char *eventName; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "eventName"); return TCL_ERROR; } eventName = Tcl_GetString(objv[3]); return QE_GetDetailNames(tree->bindingTable, eventName); } /* T notify eventnames */ case COMMAND_EVENTNAMES: { if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } return QE_GetEventNames(tree->bindingTable); } case COMMAND_GENERATE: { return QE_GenerateCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_INSTALL: { return QE_InstallCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_LINKAGE: { return QE_LinkageCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_UNBIND: { return QE_UnbindCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_UNINSTALL: { return QE_UninstallCmd(tree->bindingTable, 2, objc, objv); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeNotify_OpenClose -- * * Generate an or event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_OpenClose( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int state, /* STATE_OPEN or 0 */ int before /* TRUE for event, FALSE for * event. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ int id; } data; data.tree = tree; data.id = TreeItem_GetID(tree, item); if (state & STATE_OPEN) { event.type = EVENT_EXPAND; event.detail = before ? DETAIL_EXPAND_BEFORE : DETAIL_EXPAND_AFTER; } else { event.type = EVENT_COLLAPSE; event.detail = before ? DETAIL_COLLAPSE_BEFORE : DETAIL_COLLAPSE_AFTER; } event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_Selection -- * * Generate a event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_Selection( TreeCtrl *tree, /* Widget info. */ TreeItemList *select, /* List of items or NULL. */ TreeItemList *deselect /* List of items or NULL. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *select; TreeItemList *deselect; int count; } data; data.tree = tree; data.select = select; data.deselect = deselect; data.count = tree->selectCount; event.type = EVENT_SELECTION; event.detail = 0; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_ActiveItem -- * * Generate an event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_ActiveItem( TreeCtrl *tree, /* Widget info. */ TreeItem itemPrev, /* Previous active item. */ TreeItem itemCur /* Current active item. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ int prev; int current; } data; data.tree = tree; data.prev = TreeItem_GetID(tree, itemPrev); data.current = TreeItem_GetID(tree, itemCur); event.type = EVENT_ACTIVEITEM; event.detail = 0; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_Scroll -- * * Generate a event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_Scroll( TreeCtrl *tree, /* Widget info. */ double fractions[2], /* Fractions suitable for a scrollbar's * [set] command. */ int vertical /* TRUE for , FALSE for * . */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ double lower; double upper; } data; data.tree = tree; data.lower = fractions[0]; data.upper = fractions[1]; event.type = EVENT_SCROLL; event.detail = vertical ? DETAIL_SCROLL_Y : DETAIL_SCROLL_X; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * Percents_ItemDelete -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_ItemDelete( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *items; } *data = args->clientData; TreeCtrl *tree = data->tree; int i, count; switch (args->which) { case 'i': Tcl_DStringStartSublist(args->result); count = TreeItemList_Count(data->items); for (i = 0; i < count; i++) { TreeItem item = TreeItemList_Nth(data->items, i); if (tree->itemPrefixLen) { char buf[10 + TCL_INTEGER_SPACE]; (void) sprintf(buf, "%s%d", tree->itemPrefix, TreeItem_GetID(tree, item)); Tcl_DStringAppendElement(args->result, buf); } else { char string[TCL_INTEGER_SPACE]; TclFormatInt(string, TreeItem_GetID(tree, item)); Tcl_DStringAppendElement(args->result, string); } } Tcl_DStringEndSublist(args->result); break; default: Percents_Any(args, Percents_ItemDelete, "i"); break; } } /* *---------------------------------------------------------------------- * * TreeNotify_ItemDeleted -- * * Generate an event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_ItemDeleted( TreeCtrl *tree, /* Widget info. */ TreeItemList *items /* List of items. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *items; } data; data.tree = tree; data.items = items; event.type = EVENT_ITEM_DELETE; event.detail = 0; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_ItemVisibility -- * * Generate an event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_ItemVisibility( TreeCtrl *tree, /* Widget info. */ TreeItemList *v, /* List of newly-visible items. */ TreeItemList *h /* List of newly-hidden items. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *v; TreeItemList *h; } data; data.tree = tree; data.v = v; data.h = h; event.type = EVENT_ITEM_VISIBILITY; event.detail = 0; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_Init -- * * Perform event-related initialization when a new TreeCtrl is * created. * * Results: * Installs all the static events and details. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ int TreeNotify_Init( TreeCtrl *tree /* Widget info. */ ) { tree->bindingTable = QE_CreateBindingTable(tree->interp); EVENT_EXPAND = QE_InstallEvent(tree->bindingTable, "Expand", Percents_Expand); DETAIL_EXPAND_BEFORE = QE_InstallDetail(tree->bindingTable, "before", EVENT_EXPAND, NULL); DETAIL_EXPAND_AFTER = QE_InstallDetail(tree->bindingTable, "after", EVENT_EXPAND, NULL); EVENT_COLLAPSE = QE_InstallEvent(tree->bindingTable, "Collapse", Percents_Expand); DETAIL_COLLAPSE_BEFORE = QE_InstallDetail(tree->bindingTable, "before", EVENT_COLLAPSE, NULL); DETAIL_COLLAPSE_AFTER = QE_InstallDetail(tree->bindingTable, "after", EVENT_COLLAPSE, NULL); EVENT_SELECTION = QE_InstallEvent(tree->bindingTable, "Selection", Percents_Selection); EVENT_ACTIVEITEM = QE_InstallEvent(tree->bindingTable, "ActiveItem", Percents_ActiveItem); EVENT_SCROLL = QE_InstallEvent(tree->bindingTable, "Scroll", Percents_Scroll); DETAIL_SCROLL_X = QE_InstallDetail(tree->bindingTable, "x", EVENT_SCROLL, NULL); DETAIL_SCROLL_Y = QE_InstallDetail(tree->bindingTable, "y", EVENT_SCROLL, NULL); EVENT_ITEM_DELETE = QE_InstallEvent(tree->bindingTable, "ItemDelete", Percents_ItemDelete); EVENT_ITEM_VISIBILITY = QE_InstallEvent(tree->bindingTable, "ItemVisibility", Percents_ItemVisibility); return TCL_OK; } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeCtrl.c0000644000175000017500000036037211044115430024726 0ustar domibeldomibel/* * tkTreeCtrl.c -- * * This module implements treectrl widgets for the Tk toolkit. * * Copyright (c) 2002-2006 Tim Baker * Copyright (c) 2002-2003 Christian Krone * Copyright (c) 2003-2005 ActiveState, a division of Sophos * * RCS: @(#) $Id: tkTreeCtrl.c,v 1.4 2008-07-30 16:47:20 barre Exp $ */ #include "tkTreeCtrl.h" #ifdef WIN32 #include #endif #if defined(MAC_TCL) || defined(MAC_OSX_TK) #include #endif /* * TIP #116 altered Tk_PhotoPutBlock API to add interp arg. * We need to remove that for compiling with 8.4. */ #if (TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION < 5) #define TK_PHOTOPUTBLOCK(interp, hdl, blk, x, y, w, h, cr) \ Tk_PhotoPutBlock(hdl, blk, x, y, w, h, cr) #define TK_PHOTOPUTZOOMEDBLOCK(interp, hdl, blk, x, y, w, h, \ zx, zy, sx, sy, cr) \ Tk_PhotoPutZoomedBlock(hdl, blk, x, y, w, h, \ zx, zy, sx, sy, cr) #else #define TK_PHOTOPUTBLOCK Tk_PhotoPutBlock #define TK_PHOTOPUTZOOMEDBLOCK Tk_PhotoPutZoomedBlock #endif /* This structure is used for reference-counted images. */ typedef struct TreeImageRef { int count; /* Reference count. */ Tk_Image image; /* Image token. */ Tcl_HashEntry *hPtr; /* Entry in tree->imageNameHash. */ } TreeImageRef; static CONST84 char *bgModeST[] = { "column", "order", "ordervisible", "row", #ifdef DEPRECATED "index", "visindex", #endif (char *) NULL }; static CONST84 char *columnResizeModeST[] = { "proxy", "realtime", (char *) NULL }; static CONST84 char *doubleBufferST[] = { "none", "item", "window", (char *) NULL }; static CONST84 char *lineStyleST[] = { "dot", "solid", (char *) NULL }; static CONST84 char *orientStringTable[] = { "horizontal", "vertical", (char *) NULL }; extern Tk_ObjCustomOption columnCO_NOT_TAIL; static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", "white", -1, Tk_Offset(TreeCtrl, border), 0, (ClientData) "white", TREE_CONF_REDISPLAY}, {TK_OPTION_STRING, "-backgroundimage", "backgroundImage", "BackgroundImage", (char *) NULL, -1, Tk_Offset(TreeCtrl, backgroundImageString), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_BG_IMAGE | TREE_CONF_REDISPLAY}, {TK_OPTION_STRING_TABLE, "-backgroundmode", "backgroundMode", "BackgroundMode", "row", -1, Tk_Offset(TreeCtrl, backgroundMode), 0, (ClientData) bgModeST, TREE_CONF_REDISPLAY}, {TK_OPTION_STRING_TABLE, "-columnresizemode", "columnResizeMode", "ColumnResizeMode", "proxy", -1, Tk_Offset(TreeCtrl, columnResizeMode), 0, (ClientData) columnResizeModeST, 0}, {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"}, {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) "-background"}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_LISTBOX_BORDER_WIDTH, Tk_Offset(TreeCtrl, borderWidthObj), Tk_Offset(TreeCtrl, borderWidth), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_COLOR, "-buttoncolor", "buttonColor", "ButtonColor", "#808080", -1, Tk_Offset(TreeCtrl, buttonColor), 0, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_REDISPLAY}, {TK_OPTION_CUSTOM, "-buttonbitmap", "buttonBitmap", "ButtonBitmap", (char *) NULL, Tk_Offset(TreeCtrl, buttonBitmap.obj), Tk_Offset(TreeCtrl, buttonBitmap), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_BUTBMP | TREE_CONF_RELAYOUT}, {TK_OPTION_CUSTOM, "-buttonimage", "buttonImage", "ButtonImage", (char *) NULL, Tk_Offset(TreeCtrl, buttonImage.obj), Tk_Offset(TreeCtrl, buttonImage), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_BUTIMG | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-buttonsize", "buttonSize", "ButtonSize", "9", Tk_Offset(TreeCtrl, buttonSizeObj), Tk_Offset(TreeCtrl, buttonSize), 0, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-buttonthickness", "buttonThickness", "ButtonThickness", "1", Tk_Offset(TreeCtrl, buttonThicknessObj), Tk_Offset(TreeCtrl, buttonThickness), 0, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_REDISPLAY}, {TK_OPTION_STRING, "-columnprefix", "columnPrefix", "ColumnPrefix", "", -1, Tk_Offset(TreeCtrl, columnPrefix), 0, (ClientData) NULL, 0}, {TK_OPTION_PIXELS, "-columnproxy", "columnProxy", "ColumnProxy", (char *) NULL, Tk_Offset(TreeCtrl, columnProxy.xObj), Tk_Offset(TreeCtrl, columnProxy.x), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_PROXY}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", (char *) NULL, -1, Tk_Offset(TreeCtrl, cursor), TK_OPTION_NULL_OK, (ClientData) NULL, 0}, #ifdef DEPRECATED {TK_OPTION_STRING, "-defaultstyle", "defaultStyle", "DefaultStyle", (char *) NULL, Tk_Offset(TreeCtrl, defaultStyle.stylesObj), -1, TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_DEFSTYLE}, #endif /* DEPRECATED */ {TK_OPTION_STRING_TABLE, "-doublebuffer", "doubleBuffer", "DoubleBuffer", "item", -1, Tk_Offset(TreeCtrl, doubleBuffer), 0, (ClientData) doubleBufferST, TREE_CONF_REDISPLAY}, {TK_OPTION_SYNONYM, "-fg", (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) "-foreground"}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_LISTBOX_FONT, Tk_Offset(TreeCtrl, fontObj), Tk_Offset(TreeCtrl, tkfont), 0, (ClientData) NULL, TREE_CONF_FONT | TREE_CONF_RELAYOUT}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", DEF_LISTBOX_FG, Tk_Offset(TreeCtrl, fgObj), Tk_Offset(TreeCtrl, fgColorPtr), 0, (ClientData) NULL, TREE_CONF_FG | TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-height", "height", "Height", "200", Tk_Offset(TreeCtrl, heightObj), Tk_Offset(TreeCtrl, height), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, -1, Tk_Offset(TreeCtrl, highlightBgColorPtr), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", DEF_LISTBOX_HIGHLIGHT, -1, Tk_Offset(TreeCtrl, highlightColorPtr), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, Tk_Offset(TreeCtrl, highlightWidthObj), Tk_Offset(TreeCtrl, highlightWidth), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-indent", "indent", "Indent", "19", Tk_Offset(TreeCtrl, indentObj), Tk_Offset(TreeCtrl, indent), 0, (ClientData) NULL, TREE_CONF_INDENT | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-itemheight", "itemHeight", "ItemHeight", "0", Tk_Offset(TreeCtrl, itemHeightObj), Tk_Offset(TreeCtrl, itemHeight), 0, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, #if 0 {TK_OPTION_CUSTOM, "-itempadx", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeCtrl, itemPadXObj), Tk_Offset(TreeCtrl, itemPadX), 0, (ClientData) &PadAmountOption, 0}, {TK_OPTION_CUSTOM, "-itempady", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeCtrl, itemPadYObj), Tk_Offset(TreeCtrl, itemPadY), 0, (ClientData) &PadAmountOption, 0}, #endif {TK_OPTION_STRING, "-itemprefix", "itemPrefix", "ItemPrefix", "", -1, Tk_Offset(TreeCtrl, itemPrefix), 0, (ClientData) NULL, 0}, {TK_OPTION_PIXELS, "-itemwidth", "itemWidth", "ItemWidth", "", Tk_Offset(TreeCtrl, itemWidthObj), Tk_Offset(TreeCtrl, itemWidth), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-itemwidthequal", "itemWidthEqual", "ItemWidthEqual", "0", -1, Tk_Offset(TreeCtrl, itemWidthEqual), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-itemwidthmultiple", "itemWidthMultiple", "ItemWidthMultiple", "", Tk_Offset(TreeCtrl, itemWidMultObj), Tk_Offset(TreeCtrl, itemWidMult), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, {TK_OPTION_COLOR, "-linecolor", "lineColor", "LineColor", "#808080", -1, Tk_Offset(TreeCtrl, lineColor), 0, (ClientData) NULL, TREE_CONF_LINE | TREE_CONF_REDISPLAY}, {TK_OPTION_STRING_TABLE, "-linestyle", "lineStyle", "LineStyle", "dot", -1, Tk_Offset(TreeCtrl, lineStyle), 0, (ClientData) lineStyleST, TREE_CONF_LINE | TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-linethickness", "lineThickness", "LineThickness", "1", Tk_Offset(TreeCtrl, lineThicknessObj), Tk_Offset(TreeCtrl, lineThickness), 0, (ClientData) NULL, TREE_CONF_LINE | TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-minitemheight", "minItemHeight", "MinItemHeight", "0", Tk_Offset(TreeCtrl, minItemHeightObj), Tk_Offset(TreeCtrl, minItemHeight), 0, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical", -1, Tk_Offset(TreeCtrl, vertical), 0, (ClientData) orientStringTable, TREE_CONF_RELAYOUT}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "sunken", -1, Tk_Offset(TreeCtrl, relief), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-rowproxy", "rowProxy", "RowProxy", (char *) NULL, Tk_Offset(TreeCtrl, rowProxy.yObj), Tk_Offset(TreeCtrl, rowProxy.y), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_PROXY}, {TK_OPTION_STRING, "-scrollmargin", "scrollMargin", "ScrollMargin", "0", Tk_Offset(TreeCtrl, scrollMargin), -1, 0, (ClientData) NULL, 0}, {TK_OPTION_STRING, "-selectmode", "selectMode", "SelectMode", DEF_LISTBOX_SELECT_MODE, -1, Tk_Offset(TreeCtrl, selectMode), TK_OPTION_NULL_OK, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-showbuttons", "showButtons", "ShowButtons", "1", -1, Tk_Offset(TreeCtrl, showButtons), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showheader", "showHeader", "ShowHeader", "1", -1, Tk_Offset(TreeCtrl, showHeader), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showlines", "showLines", "ShowLines", "1", -1, Tk_Offset(TreeCtrl, showLines), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showrootlines", "showRootLines", "ShowRootLines", "1", -1, Tk_Offset(TreeCtrl, showRootLines), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showroot", "showRoot", "ShowRoot", "1", -1, Tk_Offset(TreeCtrl, showRoot), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showrootbutton", "showRootButton", "ShowRootButton", "0", -1, Tk_Offset(TreeCtrl, showRootButton), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", DEF_LISTBOX_TAKE_FOCUS, -1, Tk_Offset(TreeCtrl, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_CUSTOM, "-treecolumn", "treeColumn", "TreeColumn", (char *) NULL, -1, Tk_Offset(TreeCtrl, columnTree), TK_OPTION_NULL_OK, (ClientData) &columnCO_NOT_TAIL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-usetheme", "useTheme", "UseTheme", "0", -1, Tk_Offset(TreeCtrl, useTheme), 0, (ClientData) NULL, TREE_CONF_THEME | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-width", "width", "Width", "200", Tk_Offset(TreeCtrl, widthObj), Tk_Offset(TreeCtrl, width), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_STRING, "-wrap", "wrap", "Wrap", (char *) NULL, Tk_Offset(TreeCtrl, wrapObj), -1, TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_WRAP | TREE_CONF_RELAYOUT}, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", (char *) NULL, -1, Tk_Offset(TreeCtrl, xScrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-xscrolldelay", "xScrollDelay", "ScrollDelay", "50", Tk_Offset(TreeCtrl, xScrollDelay), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-xscrollincrement", "xScrollIncrement", "ScrollIncrement", "0", -1, Tk_Offset(TreeCtrl, xScrollIncrement), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", (char *) NULL, -1, Tk_Offset(TreeCtrl, yScrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-yscrolldelay", "yScrollDelay", "ScrollDelay", "50", Tk_Offset(TreeCtrl, yScrollDelay), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-yscrollincrement", "yScrollIncrement", "ScrollIncrement", "0", -1, Tk_Offset(TreeCtrl, yScrollIncrement), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, -1, -1, 0, (ClientData) NULL, 0} }; static Tk_OptionSpec debugSpecs[] = { {TK_OPTION_INT, "-displaydelay", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeCtrl, debug.displayDelay), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-data", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeCtrl, debug.data), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-display", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeCtrl, debug.display), 0, (ClientData) NULL, 0}, {TK_OPTION_COLOR, "-drawcolor", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeCtrl, debug.drawColor), TK_OPTION_NULL_OK, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-enable", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeCtrl, debug.enable), 0, (ClientData) NULL, 0}, {TK_OPTION_COLOR, "-erasecolor", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeCtrl, debug.eraseColor), TK_OPTION_NULL_OK, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-textlayout", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeCtrl, debug.textLayout), 0, (ClientData) NULL, 0}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, -1, -1, 0, (ClientData) NULL, 0} }; static int TreeWidgetCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); static int TreeConfigure(Tcl_Interp *interp, TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[], int createFlag); static void TreeEventProc(ClientData clientData, XEvent * eventPtr); static void TreeDestroy(char *memPtr); static void TreeCmdDeletedProc(ClientData clientData); static void TreeWorldChanged(ClientData instanceData); static void TreeComputeGeometry(TreeCtrl *tree); static int TreeStateCmd(TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); static int TreeSelectionCmd(Tcl_Interp *interp, TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); static int TreeXviewCmd(Tcl_Interp *interp, TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); static int TreeYviewCmd(Tcl_Interp *interp, TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); static int TreeDebugCmd(ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *CONST objv[]); static Tk_ClassProcs treectrlClass = { sizeof(Tk_ClassProcs), /* size */ TreeWorldChanged, /* worldChangedProc. */ NULL, /* createProc. */ NULL /* modalProc. */ }; /* *-------------------------------------------------------------- * * TreeObjCmd -- * * This procedure is invoked to process the [treectrl] Tcl * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree; Tk_Window tkwin; Tk_OptionTable optionTable; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?"); return TCL_ERROR; } tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), Tcl_GetStringFromObj(objv[1], NULL), (char *) NULL); if (tkwin == NULL) { return TCL_ERROR; } optionTable = Tk_CreateOptionTable(interp, optionSpecs); tree = (TreeCtrl *) ckalloc(sizeof(TreeCtrl)); memset(tree, '\0', sizeof(TreeCtrl)); tree->tkwin = tkwin; tree->display = Tk_Display(tkwin); tree->interp = interp; tree->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tree->tkwin), TreeWidgetCmd, (ClientData) tree, TreeCmdDeletedProc); tree->optionTable = optionTable; tree->relief = TK_RELIEF_SUNKEN; tree->prevWidth = Tk_Width(tkwin); tree->prevHeight = Tk_Height(tkwin); tree->updateIndex = 1; tree->stateNames[0] = "open"; tree->stateNames[1] = "selected"; tree->stateNames[2] = "enabled"; tree->stateNames[3] = "active"; tree->stateNames[4] = "focus"; Tcl_InitHashTable(&tree->selection, TCL_ONE_WORD_KEYS); /* Do this before Tree_InitColumns() which does Tk_InitOptions(), which * calls Tk_GetOption() which relies on the window class */ Tk_SetClass(tkwin, "TreeCtrl"); Tk_SetClassProcs(tkwin, &treectrlClass, (ClientData) tree); tree->debug.optionTable = Tk_CreateOptionTable(interp, debugSpecs); (void) Tk_InitOptions(interp, (char *) tree, tree->debug.optionTable, tkwin); Tcl_InitHashTable(&tree->itemHash, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&tree->itemSpansHash, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&tree->elementHash, TCL_STRING_KEYS); Tcl_InitHashTable(&tree->styleHash, TCL_STRING_KEYS); Tcl_InitHashTable(&tree->imageNameHash, TCL_STRING_KEYS); Tcl_InitHashTable(&tree->imageTokenHash, TCL_ONE_WORD_KEYS); TreeItemList_Init(tree, &tree->preserveItemList, 0); #ifdef ALLOC_HAX tree->allocData = AllocHax_Init(); #endif Tree_InitColumns(tree); TreeItem_Init(tree); TreeNotify_Init(tree); (void) TreeStyle_Init(tree); TreeMarquee_Init(tree); TreeDragImage_Init(tree); TreeDInfo_Init(tree); Tk_CreateEventHandler(tree->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask|ActivateMask, TreeEventProc, (ClientData) tree); /* Must do this on Unix because Tk_GCForColor() uses * Tk_WindowId(tree->tkwin) */ Tk_MakeWindowExist(tree->tkwin); /* Window must exist on Win32. */ TreeTheme_Init(tree); if (Tk_InitOptions(interp, (char *) tree, optionTable, tkwin) != TCL_OK) { Tk_DestroyWindow(tree->tkwin); WFREE(tree, TreeCtrl); return TCL_ERROR; } if (TreeConfigure(interp, tree, objc - 2, objv + 2, TRUE) != TCL_OK) { Tk_DestroyWindow(tree->tkwin); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tree->tkwin), -1)); return TCL_OK; } #define W2Cx(x) ((x) + tree->xOrigin) #define C2Wx(x) ((x) - tree->xOrigin) #define C2Ox(x) ((x) - Tree_ContentLeft(tree)) #define W2Cy(y) ((y) + tree->yOrigin) #define C2Wy(y) ((y) - tree->yOrigin) #define C2Oy(y) ((y) - Tree_ContentTop(tree)) /* *-------------------------------------------------------------- * * TreeWidgetCmd -- * * This procedure is invoked to process the Tcl command * that corresponds to a widget managed by this module. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeWidgetCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; int result = TCL_OK; static CONST84 char *commandName[] = { "activate", "bbox", "canvasx", "canvasy", "cget", #ifdef DEPRECATED "collapse", #endif "column", #ifdef DEPRECATED "compare", #endif "configure", "contentbox", "debug", "depth", "dragimage", "element", #ifdef DEPRECATED "expand", #endif "identify", "index", "item", "marquee", "notify", #ifdef DEPRECATED "numcolumns", "numitems", #endif "orphans", #ifdef DEPRECATED "range", #endif "scan", "see", "selection", "state", "style", #ifdef DEPRECATED "toggle", #endif "xview", "yview", (char *) NULL }; enum { COMMAND_ACTIVATE, COMMAND_BBOX, COMMAND_CANVASX, COMMAND_CANVASY, COMMAND_CGET, #ifdef DEPRECATED COMMAND_COLLAPSE, #endif COMMAND_COLUMN, #ifdef DEPRECATED COMMAND_COMPARE, #endif COMMAND_CONFIGURE, COMMAND_CONTENTBOX, COMMAND_DEBUG, COMMAND_DEPTH, COMMAND_DRAGIMAGE, COMMAND_ELEMENT, #ifdef DEPRECATED COMMAND_EXPAND, #endif COMMAND_IDENTIFY, COMMAND_INDEX, COMMAND_ITEM, COMMAND_MARQUEE, COMMAND_NOTIFY, #ifdef DEPRECATED COMMAND_NUMCOLUMNS, COMMAND_NUMITEMS, #endif COMMAND_ORPHANS, #ifdef DEPRECATED COMMAND_RANGE, #endif COMMAND_SCAN, COMMAND_SEE, COMMAND_SELECTION, COMMAND_STATE, COMMAND_STYLE, #ifdef DEPRECATED COMMAND_TOGGLE, #endif COMMAND_XVIEW, COMMAND_YVIEW }; Tcl_Obj *resultObjPtr; int index; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], commandName, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } Tcl_Preserve((ClientData) tree); Tree_PreserveItems(tree); switch (index) { case COMMAND_ACTIVATE: { TreeItem active, item; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "item"); goto error; } if (TreeItem_FromObj(tree, objv[2], &item, IFO_NOT_NULL) != TCL_OK) { goto error; } if (item != tree->activeItem) { int x, y, w, h; active = tree->activeItem; TreeItem_ChangeState(tree, active, STATE_ACTIVE, 0); tree->activeItem = item; TreeItem_ChangeState(tree, tree->activeItem, 0, STATE_ACTIVE); /* FIXME: is it onscreen? */ /* FIXME: what if only lock columns displayed? */ if (Tree_ItemBbox(tree, item, COLUMN_LOCK_NONE, &x, &y, &w, &h) >= 0) { Tk_SetCaretPos(tree->tkwin, x - tree->xOrigin, y - tree->yOrigin, h); } TreeNotify_ActiveItem(tree, active, item); } break; } /* .t bbox ?area? */ case COMMAND_BBOX: { static CONST84 char *areaName[] = { "content", "header", "left", "right", (char *) NULL }; int x1, y1, x2, y2; if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?area?"); goto error; } if (objc == 3) { int area[4] = { TREE_AREA_CONTENT, TREE_AREA_HEADER, TREE_AREA_LEFT, TREE_AREA_RIGHT }; if (Tcl_GetIndexFromObj(interp, objv[2], areaName, "area", 0, &index) != TCL_OK) { goto error; } if (!Tree_AreaBbox(tree, area[index], &x1, &y1, &x2, &y2)) break; } else { x1 = 0; y1 = 0; x2 = Tk_Width(tree->tkwin); y2 = Tk_Height(tree->tkwin); } FormatResult(interp, "%d %d %d %d", x1, y1, x2, y2); break; } case COMMAND_CANVASX: { int x; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "x"); goto error; } if (Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) goto error; Tcl_SetObjResult(interp, Tcl_NewIntObj(x + tree->xOrigin)); break; } case COMMAND_CANVASY: { int y; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "y"); goto error; } if (Tcl_GetIntFromObj(interp, objv[2], &y) != TCL_OK) goto error; Tcl_SetObjResult(interp, Tcl_NewIntObj(y + tree->yOrigin)); break; } case COMMAND_CGET: { if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); goto error; } resultObjPtr = Tk_GetOptionValue(interp, (char *) tree, tree->optionTable, objv[2], tree->tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, resultObjPtr); } break; } case COMMAND_CONFIGURE: { resultObjPtr = NULL; if (objc <= 3) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) tree, tree->optionTable, (objc == 2) ? (Tcl_Obj *) NULL : objv[2], tree->tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, resultObjPtr); } } else { result = TreeConfigure(interp, tree, objc - 2, objv + 2, FALSE); } break; } case COMMAND_CONTENTBOX: { int x1, y1, x2, y2; if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); goto error; } if (Tree_AreaBbox(tree, TREE_AREA_CONTENT, &x1, &y1, &x2, &y2)) { FormatResult(interp, "%d %d %d %d", x1, y1, x2, y2); } break; } #ifdef DEPRECATED /* T expand ?-recurse? I ... */ case COMMAND_COLLAPSE: case COMMAND_EXPAND: case COMMAND_TOGGLE: { char *s; int recurse = 0; int mode = 0; /* lint */ int i, j, count, len; TreeItemList items, item2s; TreeItem _item; ItemForEach iter; if (objc == 2) break; s = Tcl_GetStringFromObj(objv[2], &len); if (s[0] == '-') { if (strncmp(s, "-recurse", len)) { FormatResult(interp, "bad option \"%s\": must be -recurse", s); goto error; } if (objc == 3) break; recurse = 1; } switch (index) { case COMMAND_COLLAPSE: mode = 0; break; case COMMAND_EXPAND: mode = 1; break; case COMMAND_TOGGLE: mode = -1; break; } for (i = 2 + recurse; i < objc; i++) { if (TreeItemList_FromObj(tree, objv[i], &items, IFO_NOT_NULL) != TCL_OK) { goto error; } TreeItemList_Init(tree, &item2s, 0); ITEM_FOR_EACH(_item, &items, NULL, &iter) { TreeItemList_Append(&item2s, _item); if (!iter.all && recurse) { TreeItem_ListDescendants(tree, _item, &item2s); } } count = TreeItemList_Count(&item2s); for (j = 0; j < count; j++) { _item = TreeItemList_Nth(&item2s, j); TreeItem_OpenClose(tree, _item, mode); } TreeItemList_Free(&items); TreeItemList_Free(&item2s); } #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif break; } #endif /* DEPRECATED */ case COMMAND_COLUMN: { result = TreeColumnCmd(clientData, interp, objc, objv); break; } #ifdef DEPRECATED case COMMAND_COMPARE: { TreeItem item1, item2; static CONST84 char *opName[] = { "<", "<=", "==", ">=", ">", "!=", NULL }; int op, compare = 0, index1, index2; if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "item1 op item2"); goto error; } if (TreeItem_FromObj(tree, objv[2], &item1, IFO_NOT_NULL) != TCL_OK) goto error; if (Tcl_GetIndexFromObj(interp, objv[3], opName, "comparison operator", 0, &op) != TCL_OK) goto error; if (TreeItem_FromObj(tree, objv[4], &item2, IFO_NOT_NULL) != TCL_OK) goto error; if (TreeItem_RootAncestor(tree, item1) != TreeItem_RootAncestor(tree, item2)) { FormatResult(interp, "item %s%d and item %s%d don't share a common ancestor", tree->itemPrefix, TreeItem_GetID(tree, item1), tree->itemPrefix, TreeItem_GetID(tree, item2)); goto error; } TreeItem_ToIndex(tree, item1, &index1, NULL); TreeItem_ToIndex(tree, item2, &index2, NULL); switch (op) { case 0: compare = index1 < index2; break; case 1: compare = index1 <= index2; break; case 2: compare = index1 == index2; break; case 3: compare = index1 >= index2; break; case 4: compare = index1 > index2; break; case 5: compare = index1 != index2; break; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(compare)); break; } #endif /* DEPRECATED */ case COMMAND_DEBUG: { result = TreeDebugCmd(clientData, interp, objc, objv); break; } case COMMAND_DEPTH: { TreeItem item; int depth; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?item?"); goto error; } if (objc == 3) { if (TreeItem_FromObj(tree, objv[2], &item, IFO_NOT_NULL) != TCL_OK) goto error; depth = TreeItem_GetDepth(tree, item); if (TreeItem_RootAncestor(tree, item) == tree->root) depth++; Tcl_SetObjResult(interp, Tcl_NewIntObj(depth)); break; } Tree_UpdateItemIndex(tree); Tcl_SetObjResult(interp, Tcl_NewIntObj(tree->depth + 1)); break; } case COMMAND_DRAGIMAGE: { result = DragImageCmd(clientData, interp, objc, objv); break; } case COMMAND_ELEMENT: { result = TreeElementCmd(clientData, interp, objc, objv); break; } case COMMAND_IDENTIFY: { int x, y, width, height, depth; TreeColumn treeColumn; TreeItem item; char buf[64]; int hit; int lock; /* set id [$tree identify $x $y] "item I column C" : mouse is in column C of item I "item I column C elem E" : mouse is in element E in column C of item I "item I button" : mouse is in button-area of item I "item I line J" : mouse is near line coming from item J "header C ?left|right?" : mouse is in header column C "" : mouse is not in any item */ if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "x y"); goto error; } if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[2], &x) != TCL_OK) goto error; if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[3], &y) != TCL_OK) goto error; hit = Tree_HitTest(tree, x, y); /* Require point inside borders */ if (hit == TREE_AREA_NONE) break; if (hit == TREE_AREA_HEADER) { treeColumn = Tree_HeaderUnderPoint(tree, &x, &y, &width, &height, FALSE); if (treeColumn == tree->columnTail) { strcpy(buf, "header tail"); if (x < 4) sprintf(buf + strlen(buf), " left"); Tcl_SetResult(interp, buf, TCL_VOLATILE); break; } else if (treeColumn != NULL) { sprintf(buf, "header %s%d", tree->columnPrefix, TreeColumn_GetID(treeColumn)); if (x < 4) sprintf(buf + strlen(buf), " left"); else if (x >= width - 4) sprintf(buf + strlen(buf), " right"); Tcl_SetResult(interp, buf, TCL_VOLATILE); break; } } item = Tree_ItemUnderPoint(tree, &x, &y, FALSE); if (item == NULL) break; sprintf(buf, "item %s%d", tree->itemPrefix, TreeItem_GetID(tree, item)); /* TreeItem_ToObj() */ depth = TreeItem_GetDepth(tree, item); if (tree->showRoot || tree->showButtons || tree->showLines) depth++; if (tree->showRoot && tree->showButtons && tree->showRootButton) depth++; if (item == tree->root) depth = (tree->showButtons && tree->showRootButton) ? 1 : 0; lock = (hit == TREE_AREA_LEFT) ? COLUMN_LOCK_LEFT : (hit == TREE_AREA_RIGHT) ? COLUMN_LOCK_RIGHT : COLUMN_LOCK_NONE; /* Point is in a line or button */ if (tree->columnTreeVis && (TreeColumn_Lock(tree->columnTree) == lock) && (x >= tree->columnTreeLeft) && (x < tree->columnTreeLeft + TreeColumn_UseWidth(tree->columnTree)) && (x < tree->columnTreeLeft + depth * tree->useIndent)) { int column = (x - tree->columnTreeLeft) / tree->useIndent + 1; if (column == depth) { if (tree->showButtons && TreeItem_GetButton(tree, item)) sprintf(buf + strlen(buf), " button"); } else if (tree->showLines) { TreeItem sibling; do { item = TreeItem_GetParent(tree, item); } while (++column < depth); sibling = TreeItem_NextSiblingVisible(tree, item); if ((sibling != NULL) && ((TreeItem_GetParent(tree, sibling) != tree->root) || tree->showRootLines)) sprintf(buf + strlen(buf), " line %s%d", tree->itemPrefix, TreeItem_GetID(tree, item)); /* TreeItem_ToObj() */ } } else { TreeItem_Identify(tree, item, lock, x, y, buf); } Tcl_SetResult(interp, buf, TCL_VOLATILE); break; } #ifdef DEPRECATED case COMMAND_INDEX: { TreeItem item; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "item"); goto error; } if (TreeItem_FromObj(tree, objv[2], &item, 0) != TCL_OK) { goto error; } if (item != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item)); break; } #endif /* DEPRECATED */ case COMMAND_ITEM: { result = TreeItemCmd(clientData, interp, objc, objv); break; } case COMMAND_MARQUEE: { result = TreeMarqueeCmd(clientData, interp, objc, objv); break; } case COMMAND_NOTIFY: { result = TreeNotifyCmd(clientData, interp, objc, objv); break; } #ifdef DEPRECATED case COMMAND_NUMCOLUMNS: { if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); goto error; } Tcl_SetObjResult(interp, Tcl_NewIntObj(tree->columnCount)); break; } case COMMAND_NUMITEMS: { if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); goto error; } Tcl_SetObjResult(interp, Tcl_NewIntObj(tree->itemCount)); break; } #endif /* DEPRECATED */ case COMMAND_ORPHANS: { Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_Obj *listObj; TreeItem item; if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); goto error; } /* Pretty slow. Could keep a hash table of orphans */ listObj = Tcl_NewListObj(0, NULL); hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if ((item != tree->root) && (TreeItem_GetParent(tree, item) == NULL)) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); } hPtr = Tcl_NextHashEntry(&search); } Tcl_SetObjResult(interp, listObj); break; } #ifdef DEPRECATED case COMMAND_RANGE: { TreeItem item, itemFirst, itemLast; Tcl_Obj *listObj; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "first last"); goto error; } if (TreeItem_FromObj(tree, objv[2], &itemFirst, IFO_NOT_NULL) != TCL_OK) goto error; if (TreeItem_FromObj(tree, objv[3], &itemLast, IFO_NOT_NULL) != TCL_OK) goto error; if (TreeItem_FirstAndLast(tree, &itemFirst, &itemLast) == 0) goto error; listObj = Tcl_NewListObj(0, NULL); item = itemFirst; while (item != NULL) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); if (item == itemLast) break; item = TreeItem_Next(tree, item); } Tcl_SetObjResult(interp, listObj); break; } #endif /* DEPRECATED */ case COMMAND_SCAN: { static CONST84 char *optionName[] = { "dragto", "mark", (char *) NULL }; int x, y, gain = 10, xOrigin, yOrigin; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); goto error; } if (Tcl_GetIndexFromObj(interp, objv[2], optionName, "option", 2, &index) != TCL_OK) goto error; switch (index) { /* T scan dragto x y ?gain? */ case 0: if ((objc < 5) || (objc > 6)) { Tcl_WrongNumArgs(interp, 3, objv, "x y ?gain?"); goto error; } if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) goto error; if (objc == 6) { if (Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK) goto error; } xOrigin = tree->scanXOrigin - gain * (x - tree->scanX); yOrigin = tree->scanYOrigin - gain * (y - tree->scanY); Tree_SetOriginX(tree, xOrigin); Tree_SetOriginY(tree, yOrigin); break; /* T scan mark x y ?gain? */ case 1: if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "x y"); goto error; } if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) goto error; tree->scanX = x; tree->scanY = y; tree->scanXOrigin = tree->xOrigin; tree->scanYOrigin = tree->yOrigin; break; } break; } case COMMAND_SEE: { TreeItem item; int x, y, w, h; int visWidth = Tree_ContentWidth(tree); int visHeight = Tree_ContentHeight(tree); int xOrigin = tree->xOrigin; int yOrigin = tree->yOrigin; int minX = Tree_ContentLeft(tree); int minY = Tree_ContentTop(tree); int maxX = Tree_ContentRight(tree); int maxY = Tree_ContentBottom(tree); int index, offset; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "item"); goto error; } if (TreeItem_FromObj(tree, objv[2], &item, IFO_NOT_NULL) != TCL_OK) goto error; /* Canvas coords */ if (Tree_ItemBbox(tree, item, COLUMN_LOCK_NONE, &x, &y, &w, &h) < 0) break; if ((C2Wx(x) > maxX) || (C2Wx(x + w) <= minX) || (w <= visWidth)) { if ((C2Wx(x) < minX) || (w > visWidth)) { index = Increment_FindX(tree, x); offset = Increment_ToOffsetX(tree, index); xOrigin = C2Ox(offset); } else if (C2Wx(x + w) > maxX) { index = Increment_FindX(tree, x + w - visWidth); offset = Increment_ToOffsetX(tree, index); if (offset < x + w - visWidth) { index++; offset = Increment_ToOffsetX(tree, index); } xOrigin = C2Ox(offset); } } if ((C2Wy(y) > maxY) || (C2Wy(y + h) <= minY) || (h <= visHeight)) { if ((C2Wy(y) < minY) || (h > visHeight)) { index = Increment_FindY(tree, y); offset = Increment_ToOffsetY(tree, index); yOrigin = C2Oy(offset); } else if (C2Wy(y + h) > maxY) { index = Increment_FindY(tree, y + h - visHeight); offset = Increment_ToOffsetY(tree, index); if (offset < y + h - visHeight) { index++; offset = Increment_ToOffsetY(tree, index); } yOrigin = C2Oy(offset); } } Tree_SetOriginX(tree, xOrigin); Tree_SetOriginY(tree, yOrigin); break; } case COMMAND_SELECTION: { result = TreeSelectionCmd(interp, tree, objc, objv); break; } case COMMAND_STATE: { result = TreeStateCmd(tree, objc, objv); break; } case COMMAND_STYLE: { result = TreeStyleCmd(clientData, interp, objc, objv); break; } case COMMAND_XVIEW: { result = TreeXviewCmd(interp, tree, objc, objv); break; } case COMMAND_YVIEW: { result = TreeYviewCmd(interp, tree, objc, objv); break; } } Tree_ReleaseItems(tree); Tcl_Release((ClientData) tree); return result; error: Tree_ReleaseItems(tree); Tcl_Release((ClientData) tree); return TCL_ERROR; } /* *-------------------------------------------------------------- * * TreeConfigure -- * * This procedure is called to process an argv/argc list, plus * the Tk option database, in order to configure (or reconfigure) * a treectrl widget. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then the interp's result contains an error message. * * Side effects: * Configuration information, such as colors, border width, * etc. get set for tree; old resources get freed, * if there were any. * *-------------------------------------------------------------- */ static int TreeConfigure( Tcl_Interp *interp, /* Current interpreter. */ TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[], /* Argument values. */ int createFlag /* TRUE if the widget is being created. */ ) { int error; Tcl_Obj *errorResult = NULL; TreeCtrl saved; Tk_SavedOptions savedOptions; int oldShowRoot = tree->showRoot; int mask, maskFree = 0; XGCValues gcValues; unsigned long gcMask; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(interp, (char *) tree, tree->optionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* Wouldn't have to do this if Tk_InitOptions() would return * a mask of configured options like Tk_SetOptions() does. */ if (createFlag) { if (tree->backgroundImageString != NULL) mask |= TREE_CONF_BG_IMAGE; if (tree->buttonBitmap.obj != NULL) mask |= TREE_CONF_BUTBMP; if (tree->buttonImage.obj != NULL) mask |= TREE_CONF_BUTIMG; #ifdef DEPRECATED if (tree->defaultStyle.stylesObj != NULL) mask |= TREE_CONF_DEFSTYLE; #endif if (tree->wrapObj != NULL) mask |= TREE_CONF_WRAP; if (!ObjectIsEmpty(tree->itemWidthObj)) mask |= TREE_CONF_ITEMSIZE; if (!ObjectIsEmpty(tree->itemWidMultObj)) mask |= TREE_CONF_ITEMSIZE; } /* * Step 1: Save old values */ if (mask & TREE_CONF_BG_IMAGE) saved.backgroundImage = tree->backgroundImage; #ifdef DEPRECATED if (mask & TREE_CONF_DEFSTYLE) { saved.defaultStyle.styles = tree->defaultStyle.styles; saved.defaultStyle.numStyles = tree->defaultStyle.numStyles; } #endif if (mask & TREE_CONF_WRAP) { saved.wrapMode = tree->wrapMode; saved.wrapArg = tree->wrapArg; } /* * Step 2: Process new values */ if (mask & TREE_CONF_BG_IMAGE) { if (tree->backgroundImageString == NULL) { tree->backgroundImage = NULL; } else { Tk_Image image = Tree_GetImage(tree, tree->backgroundImageString); if (image == NULL) continue; tree->backgroundImage = image; maskFree |= TREE_CONF_BG_IMAGE; } } #ifdef DEPRECATED if (mask & TREE_CONF_DEFSTYLE) { if (tree->defaultStyle.stylesObj == NULL) { tree->defaultStyle.styles = NULL; tree->defaultStyle.numStyles = 0; } else { int i, listObjc; Tcl_Obj **listObjv; TreeStyle style; if ((Tcl_ListObjGetElements(interp, tree->defaultStyle.stylesObj, &listObjc, &listObjv) != TCL_OK)) continue; tree->defaultStyle.styles = (TreeStyle *) ckalloc(sizeof(TreeStyle) * listObjc); tree->defaultStyle.numStyles = listObjc; for (i = 0; i < listObjc; i++) { if (ObjectIsEmpty(listObjv[i])) { style = NULL; } else { if (TreeStyle_FromObj(tree, listObjv[i], &style) != TCL_OK) { ckfree((char *) tree->defaultStyle.styles); break; } } tree->defaultStyle.styles[i] = style; } if (i < listObjc) continue; maskFree |= TREE_CONF_DEFSTYLE; } } #endif /* DEPRECATED */ /* Parse -wrap string into wrapMode and wrapArg */ if (mask & TREE_CONF_WRAP) { int listObjc; Tcl_Obj **listObjv; if (tree->wrapObj == NULL) { tree->wrapMode = TREE_WRAP_NONE; tree->wrapArg = 0; } else { int len0, len1; char *s0, *s1, ch0, ch1; if ((Tcl_ListObjGetElements(interp, tree->wrapObj, &listObjc, &listObjv) != TCL_OK) || (listObjc > 2)) { badWrap: FormatResult(interp, "bad wrap \"%s\"", Tcl_GetString(tree->wrapObj)); continue; } if (listObjc == 1) { s0 = Tcl_GetStringFromObj(listObjv[0], &len0); ch0 = s0[0]; if ((ch0 == 'w') && !strncmp(s0, "window", len0)) { tree->wrapMode = TREE_WRAP_WINDOW; tree->wrapArg = 0; } else goto badWrap; } else { s1 = Tcl_GetStringFromObj(listObjv[1], &len1); ch1 = s1[0]; if ((ch1 == 'i') && !strncmp(s1, "items", len1)) { int n; if ((Tcl_GetIntFromObj(interp, listObjv[0], &n) != TCL_OK) || (n < 0)) { goto badWrap; } tree->wrapMode = TREE_WRAP_ITEMS; tree->wrapArg = n; } else if ((ch1 == 'p') && !strncmp(s1, "pixels", len1)) { int n; if (Tk_GetPixelsFromObj(interp, tree->tkwin, listObjv[0], &n) != TCL_OK) { goto badWrap; } tree->wrapMode = TREE_WRAP_PIXELS; tree->wrapArg = n; } else goto badWrap; } } } /* * Step 3: Free saved values */ if (mask & TREE_CONF_BG_IMAGE) { if (saved.backgroundImage != NULL) Tree_FreeImage(tree, saved.backgroundImage); } #ifdef DEPRECATED if (mask & TREE_CONF_DEFSTYLE) { if (saved.defaultStyle.styles != NULL) ckfree((char *) saved.defaultStyle.styles); } #endif Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* * Free new values. */ if (maskFree & TREE_CONF_BG_IMAGE) Tree_FreeImage(tree, tree->backgroundImage); #ifdef DEPRECATED if (maskFree & TREE_CONF_DEFSTYLE) ckfree((char *) tree->defaultStyle.styles); #endif /* * Restore old values. */ if (mask & TREE_CONF_BG_IMAGE) { tree->backgroundImage = saved.backgroundImage; } #ifdef DEPRECATED if (mask & TREE_CONF_DEFSTYLE) { tree->defaultStyle.styles = saved.defaultStyle.styles; tree->defaultStyle.numStyles = saved.defaultStyle.numStyles; } #endif if (mask & TREE_CONF_WRAP) { tree->wrapMode = saved.wrapMode; tree->wrapArg = saved.wrapArg; } Tcl_SetObjResult(interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } tree->itemPrefixLen = (int)strlen(tree->itemPrefix); tree->columnPrefixLen = (int)strlen(tree->columnPrefix); Tk_SetWindowBackground(tree->tkwin, Tk_3DBorderColor(tree->border)->pixel); if (createFlag) mask |= TREE_CONF_FONT | TREE_CONF_RELAYOUT; if (mask & (TREE_CONF_FONT | TREE_CONF_FG)) { /* * Should be blended into TreeWorldChanged. */ gcValues.font = Tk_FontId(tree->tkfont); gcValues.foreground = tree->fgColorPtr->pixel; gcValues.graphics_exposures = False; gcMask = GCForeground | GCFont | GCGraphicsExposures; if (tree->textGC != None) Tk_FreeGC(tree->display, tree->textGC); tree->textGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } if (tree->copyGC == None) { gcValues.function = GXcopy; gcValues.graphics_exposures = False; gcMask = GCFunction | GCGraphicsExposures; tree->copyGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } if (createFlag) mask |= TREE_CONF_BUTTON; if (mask & TREE_CONF_BUTTON) { if (tree->buttonGC != None) Tk_FreeGC(tree->display, tree->buttonGC); gcValues.foreground = tree->buttonColor->pixel; gcValues.line_width = tree->buttonThickness; gcMask = GCForeground | GCLineWidth; tree->buttonGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } if (createFlag) mask |= TREE_CONF_LINE; if (mask & TREE_CONF_LINE) { if (tree->lineGC != None) Tk_FreeGC(tree->display, tree->lineGC); gcValues.foreground = tree->lineColor->pixel; gcValues.line_width = tree->lineThickness; gcMask = GCForeground | GCLineWidth; tree->lineGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } if (mask & TREE_CONF_PROXY) { TreeColumnProxy_Undisplay(tree); TreeColumnProxy_Display(tree); TreeRowProxy_Undisplay(tree); TreeRowProxy_Display(tree); } tree->useIndent = MAX(tree->indent, ButtonMaxWidth(tree)); if (tree->highlightWidth < 0) tree->highlightWidth = 0; tree->inset = tree->highlightWidth + tree->borderWidth; if (oldShowRoot != tree->showRoot) { TreeItem_InvalidateHeight(tree, tree->root); tree->updateIndex = 1; } TreeStyle_TreeChanged(tree, mask); TreeColumn_TreeChanged(tree, mask); if (mask & TREE_CONF_RELAYOUT) { TreeComputeGeometry(tree); Tree_InvalidateColumnWidth(tree, NULL); Tree_InvalidateColumnHeight(tree, NULL); /* In case -usetheme changes */ Tree_RelayoutWindow(tree); } else if (mask & TREE_CONF_REDISPLAY) { Tree_RelayoutWindow(tree); } return TCL_OK; } /* *--------------------------------------------------------------------------- * * TreeWorldChanged -- * * This procedure is called when the world has changed in some * way and the widget needs to recompute all its graphics contexts * and determine its new geometry. * * Results: * None. * * Side effects: * Widget will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ static void TreeWorldChanged( ClientData instanceData /* Widget info. */ ) { TreeCtrl *tree = (TreeCtrl *) instanceData; XGCValues gcValues; unsigned long gcMask; gcValues.font = Tk_FontId(tree->tkfont); gcValues.foreground = tree->fgColorPtr->pixel; gcValues.graphics_exposures = False; gcMask = GCForeground | GCFont | GCGraphicsExposures; if (tree->textGC != None) Tk_FreeGC(tree->display, tree->textGC); tree->textGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); TreeStyle_TreeChanged(tree, TREE_CONF_FONT | TREE_CONF_RELAYOUT); TreeColumn_TreeChanged(tree, TREE_CONF_FONT | TREE_CONF_RELAYOUT); TreeComputeGeometry(tree); Tree_InvalidateColumnWidth(tree, NULL); Tree_RelayoutWindow(tree); } /* *-------------------------------------------------------------- * * TreeEventProc -- * * This procedure is invoked by the Tk dispatcher for various * events on the widget. * * Results: * None. * * Side effects: * When the window gets deleted, internal structures get * cleaned up. When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void TreeEventProc( ClientData clientData, /* Widget info. */ XEvent *eventPtr /* Event info. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; switch (eventPtr->type) { case Expose: { int x = eventPtr->xexpose.x; int y = eventPtr->xexpose.y; Tree_RedrawArea(tree, x, y, x + eventPtr->xexpose.width, y + eventPtr->xexpose.height); break; } case ConfigureNotify: { if ((tree->prevWidth != Tk_Width(tree->tkwin)) || (tree->prevHeight != Tk_Height(tree->tkwin))) { tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_RelayoutWindow(tree); tree->prevWidth = Tk_Width(tree->tkwin); tree->prevHeight = Tk_Height(tree->tkwin); } break; } case FocusIn: /* Handle focus as Tile does */ if ( eventPtr->xfocus.detail == NotifyInferior || eventPtr->xfocus.detail == NotifyAncestor || eventPtr->xfocus.detail == NotifyNonlinear) { Tree_FocusChanged(tree, 1); } break; case FocusOut: /* Handle focus as Tile does */ if ( eventPtr->xfocus.detail == NotifyInferior || eventPtr->xfocus.detail == NotifyAncestor || eventPtr->xfocus.detail == NotifyNonlinear) { Tree_FocusChanged(tree, 0); } break; case ActivateNotify: Tree_Activate(tree, 1); break; case DeactivateNotify: Tree_Activate(tree, 0); break; case DestroyNotify: if (!tree->deleted) { tree->deleted = 1; Tcl_DeleteCommandFromToken(tree->interp, tree->widgetCmd); Tcl_EventuallyFree((ClientData) tree, TreeDestroy); } break; } } /* *---------------------------------------------------------------------- * * TreeCmdDeletedProc -- * * This procedure is invoked when a widget command is deleted. If * the widget isn't already in the process of being destroyed, * this command destroys it. * * Results: * None. * * Side effects: * The widget is destroyed. * *---------------------------------------------------------------------- */ static void TreeCmdDeletedProc( ClientData clientData /* Widget info. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; if (!tree->deleted) { Tk_DestroyWindow(tree->tkwin); } } /* *---------------------------------------------------------------------- * * TreeDestroy -- * * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release * to clean up the internal structure of a widget at a safe time * (when no-one is using it anymore). * * Results: * None. * * Side effects: * Everything associated with the widget is freed up. * *---------------------------------------------------------------------- */ static void TreeDestroy( char *memPtr /* Widget info. */ ) { TreeCtrl *tree = (TreeCtrl *) memPtr; TreeItem item; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int i, count; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_FreeResources(tree, item); hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&tree->itemHash); Tcl_DeleteHashTable(&tree->itemSpansHash); count = TreeItemList_Count(&tree->preserveItemList); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&tree->preserveItemList, i); TreeItem_Release(tree, item); } TreeItemList_Free(&tree->preserveItemList); TreeStyle_Free(tree); TreeDragImage_Free(tree->dragImage); TreeMarquee_Free(tree->marquee); TreeDInfo_Free(tree); TreeTheme_Free(tree); if (tree->copyGC != None) Tk_FreeGC(tree->display, tree->copyGC); if (tree->textGC != None) Tk_FreeGC(tree->display, tree->textGC); if (tree->buttonGC != None) Tk_FreeGC(tree->display, tree->buttonGC); if (tree->lineGC != None) Tk_FreeGC(tree->display, tree->lineGC); Tree_FreeColumns(tree); QE_DeleteBindingTable(tree->bindingTable); for (i = STATE_USER - 1; i < 32; i++) if (tree->stateNames[i] != NULL) ckfree(tree->stateNames[i]); Tk_FreeConfigOptions((char *) tree, tree->debug.optionTable, tree->tkwin); Tk_FreeConfigOptions((char *) tree, tree->optionTable, tree->tkwin); hPtr = Tcl_FirstHashEntry(&tree->imageNameHash, &search); while (hPtr != NULL) { TreeImageRef *ref = (TreeImageRef *) Tcl_GetHashValue(hPtr); Tk_FreeImage(ref->image); ckfree((char *) ref); hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&tree->imageNameHash); Tcl_DeleteHashTable(&tree->imageTokenHash); Tcl_DeleteHashTable(&tree->selection); #ifdef DEPRECATED if (tree->defaultStyle.styles != NULL) ckfree((char *) tree->defaultStyle.styles); #endif #ifdef ALLOC_HAX AllocHax_Finalize(tree->allocData); #endif WFREE(tree, TreeCtrl); } /* *---------------------------------------------------------------------- * * Tree_UpdateScrollbarX -- * * This procedure is invoked whenever information has changed in * a widget in a way that would invalidate a scrollbar display. * * A event is generated. * * If there is an associated scrollbar, then this procedure updates * it by invoking a Tcl command. * * Results: * None. * * Side effects: * A Tcl command is invoked, and an additional command may be * invoked to process errors in the command. * *---------------------------------------------------------------------- */ void Tree_UpdateScrollbarX( TreeCtrl *tree /* Widget info. */ ) { Tcl_Interp *interp = tree->interp; int result; double fractions[2]; char buffer[TCL_DOUBLE_SPACE * 2]; char *xScrollCmd; Tree_GetScrollFractionsX(tree, fractions); TreeNotify_Scroll(tree, fractions, FALSE); if (tree->xScrollCmd == NULL) return; Tcl_Preserve((ClientData) interp); Tcl_Preserve((ClientData) tree); xScrollCmd = tree->xScrollCmd; Tcl_Preserve((ClientData) xScrollCmd); sprintf(buffer, "%g %g", fractions[0], fractions[1]); result = Tcl_VarEval(interp, xScrollCmd, " ", buffer, (char *) NULL); if (result != TCL_OK) Tcl_BackgroundError(interp); Tcl_ResetResult(interp); Tcl_Release((ClientData) xScrollCmd); Tcl_Release((ClientData) tree); Tcl_Release((ClientData) interp); } /* *---------------------------------------------------------------------- * * Tree_UpdateScrollbarY -- * * This procedure is invoked whenever information has changed in * a widget in a way that would invalidate a scrollbar display. * * A event is generated. * * If there is an associated scrollbar, then this procedure updates * it by invoking a Tcl command. * * Results: * None. * * Side effects: * A Tcl command is invoked, and an additional command may be * invoked to process errors in the command. * *---------------------------------------------------------------------- */ void Tree_UpdateScrollbarY( TreeCtrl *tree /* Widget info. */ ) { Tcl_Interp *interp = tree->interp; int result; double fractions[2]; char buffer[TCL_DOUBLE_SPACE * 2]; char *yScrollCmd; Tree_GetScrollFractionsY(tree, fractions); TreeNotify_Scroll(tree, fractions, TRUE); if (tree->yScrollCmd == NULL) return; Tcl_Preserve((ClientData) interp); Tcl_Preserve((ClientData) tree); yScrollCmd = tree->yScrollCmd; Tcl_Preserve((ClientData) yScrollCmd); sprintf(buffer, "%g %g", fractions[0], fractions[1]); result = Tcl_VarEval(interp, yScrollCmd, " ", buffer, (char *) NULL); if (result != TCL_OK) Tcl_BackgroundError(interp); Tcl_ResetResult(interp); Tcl_Release((ClientData) yScrollCmd); Tcl_Release((ClientData) tree); Tcl_Release((ClientData) interp); } /* *---------------------------------------------------------------------- * * TreeComputeGeometry -- * * This procedure is invoked to compute the requested size for the * window. * * Results: * None. * * Side effects: * Tk_GeometryRequest is called to register the desired dimensions * for the window. * *---------------------------------------------------------------------- */ static void TreeComputeGeometry( TreeCtrl *tree /* Widget info. */ ) { Tk_SetInternalBorder(tree->tkwin, tree->inset); Tk_GeometryRequest(tree->tkwin, tree->width + tree->inset * 2, tree->height + tree->inset * 2); } /* *---------------------------------------------------------------------- * * Tree_AddItem -- * * Add an item to the hash table of items. Also set the unique item * id and increment the number of items. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_AddItem( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item that was created. */ ) { Tcl_HashEntry *hPtr; int id, isNew; id = TreeItem_SetID(tree, item, tree->nextItemId++); hPtr = Tcl_CreateHashEntry(&tree->itemHash, (char *) id, &isNew); Tcl_SetHashValue(hPtr, item); tree->itemCount++; } /* *---------------------------------------------------------------------- * * Tree_RemoveItem -- * * Remove an item from the selection, if selected. * Remove an item from the hash table of items. * Decrement the number of items. * Reset the unique item id allocator if the last item is removed. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_RemoveItem( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item to remove. */ ) { Tcl_HashEntry *hPtr; if (TreeItem_GetSelected(tree, item)) Tree_RemoveFromSelection(tree, item); hPtr = Tcl_FindHashEntry(&tree->itemSpansHash, (char *) item); if (hPtr != NULL) Tcl_DeleteHashEntry(hPtr); hPtr = Tcl_FindHashEntry(&tree->itemHash, (char *) TreeItem_GetID(tree, item)); Tcl_DeleteHashEntry(hPtr); tree->itemCount--; if (tree->itemCount == 1) tree->nextItemId = TreeItem_GetID(tree, tree->root) + 1; } /* *---------------------------------------------------------------------- * * ImageChangedProc -- * * This procedure is invoked by the image code whenever the manager * for an image does something that affects the image's size or * how it is displayed. * * Results: * None. * * Side effects: * Arranges for the widget to get redisplayed. * *---------------------------------------------------------------------- */ static void ImageChangedProc( ClientData clientData, /* Widget info. */ int x, int y, /* Upper left pixel (within image) * that must be redisplayed. */ int width, int height, /* Dimensions of area to redisplay * (may be <= 0). */ int imageWidth, int imageHeight /* New dimensions of image. */ ) { /* I would like to know the image was deleted... */ TreeCtrl *tree = (TreeCtrl *) clientData; /* FIXME: any image elements need to have their size invalidated * and items relayout'd accordingly. */ /* FIXME: this is used for the background image, but whitespace * is not redrawn if the background image is modified. */ Tree_DInfoChanged(tree, DINFO_INVALIDATE | DINFO_OUT_OF_DATE); } /* *---------------------------------------------------------------------- * * Tree_GetImage -- * * Wrapper around Tk_GetImage(). If the requested image does not yet * exist it is created. Otherwise an existing instance is returned. * * The purpose of this procedure is to save memory. We may expect * the same image to be used hundreds of times (a folder image for * example) and want to avoid allocating an instance for every usage. * * For each call to this function, there must be a matching call * to Tree_FreeImage. * * Results: * Token for the image instance. If an error occurs the result is * NULL and a message is left in the interpreter's result. * * Side effects: * A new image instance may be created. * *---------------------------------------------------------------------- */ Tk_Image Tree_GetImage( TreeCtrl *tree, /* Widget info. */ char *imageName /* Name of an existing image. */ ) { Tcl_HashEntry *hPtr, *h2Ptr; TreeImageRef *ref; Tk_Image image; int isNew; hPtr = Tcl_CreateHashEntry(&tree->imageNameHash, imageName, &isNew); if (isNew) { image = Tk_GetImage(tree->interp, tree->tkwin, imageName, ImageChangedProc, (ClientData) tree); if (image == NULL) { Tcl_DeleteHashEntry(hPtr); return NULL; } ref = (TreeImageRef *) ckalloc(sizeof(TreeImageRef)); ref->count = 0; ref->image = image; ref->hPtr = hPtr; Tcl_SetHashValue(hPtr, ref); h2Ptr = Tcl_CreateHashEntry(&tree->imageTokenHash, (char *) image, &isNew); Tcl_SetHashValue(h2Ptr, ref); } ref = (TreeImageRef *) Tcl_GetHashValue(hPtr); ref->count++; return ref->image; } /* *---------------------------------------------------------------------- * * Tree_FreeImage -- * * Decrement the reference count on an image. * * Results: * If the reference count hits zero, frees the image instance and * hash table entries. * * Side effects: * Memory may be freed. * *---------------------------------------------------------------------- */ void Tree_FreeImage( TreeCtrl *tree, /* Widget info. */ Tk_Image image /* Image token. */ ) { Tcl_HashEntry *hPtr; TreeImageRef *ref; hPtr = Tcl_FindHashEntry(&tree->imageTokenHash, (char *) image); if (hPtr != NULL) { ref = (TreeImageRef *) Tcl_GetHashValue(hPtr); if (--ref->count == 0) { Tcl_DeleteHashEntry(ref->hPtr); /* imageNameHash */ Tcl_DeleteHashEntry(hPtr); Tk_FreeImage(ref->image); ckfree((char *) ref); } } } /* *---------------------------------------------------------------------- * * Tree_StateFromObj -- * * Parse a Tcl_Obj containing a state name (with optional modifers) * into a STATE_xxx flag, and modify an existing array of state * flags accordingly. * * If the object contains "foo", then the state "foo" is set on. * If the object contains "!foo", then the state "foo" is set off. * If the object contains "^foo", then the state "foo" is toggled. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_StateFromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* String rep of the state. */ int states[3], /* Initialized state flags, indexed by the * STATE_OP_xxx contants. A single flag * may be turned on or off in each value. */ int *indexPtr, /* Returned index of the STATE_xxx flag. * May be NULL. */ int flags /* SFO_xxx flags. */ ) { Tcl_Interp *interp = tree->interp; int i, op = STATE_OP_ON, op2, op3, length, state = 0; char ch0, *string; string = Tcl_GetStringFromObj(obj, &length); if (length == 0) goto unknown; ch0 = string[0]; if (ch0 == '!') { if (flags & SFO_NOT_OFF) { FormatResult(interp, "can't specify '!' for this command"); return TCL_ERROR; } op = STATE_OP_OFF; ++string; ch0 = string[0]; } else if (ch0 == '~') { if (flags & SFO_NOT_TOGGLE) { FormatResult(interp, "can't specify '~' for this command"); return TCL_ERROR; } op = STATE_OP_TOGGLE; ++string; ch0 = string[0]; } for (i = 0; i < 32; i++) { if (tree->stateNames[i] == NULL) continue; if ((ch0 == tree->stateNames[i][0]) && (strcmp(string, tree->stateNames[i]) == 0)) { if ((i < STATE_USER - 1) && (flags & SFO_NOT_STATIC)) { FormatResult(interp, "can't specify state \"%s\" for this command", tree->stateNames[i]); return TCL_ERROR; } state = 1L << i; break; } } if (state == 0) goto unknown; if (states != NULL) { if (op == STATE_OP_ON) { op2 = STATE_OP_OFF; op3 = STATE_OP_TOGGLE; } else if (op == STATE_OP_OFF) { op2 = STATE_OP_ON; op3 = STATE_OP_TOGGLE; } else { op2 = STATE_OP_ON; op3 = STATE_OP_OFF; } states[op2] &= ~state; states[op3] &= ~state; states[op] |= state; } if (indexPtr != NULL) (*indexPtr) = i; return TCL_OK; unknown: FormatResult(interp, "unknown state \"%s\"", string); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tree_StateFromListObj -- * * Call Tree_StateFromObj for a Tcl_Obj list object. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_StateFromListObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* List of states. */ int states[3], /* Uninitialized state flags, indexed by the * STATE_OP_xxx contants. A single flag * may be turned on or off in each value. */ int flags /* SFO_xxx flags. */ ) { Tcl_Interp *interp = tree->interp; int i, listObjc; Tcl_Obj **listObjv; states[0] = states[1] = states[2] = 0; if (Tcl_ListObjGetElements(interp, obj, &listObjc, &listObjv) != TCL_OK) return TCL_ERROR; for (i = 0; i < listObjc; i++) { if (Tree_StateFromObj(tree, listObjv[i], states, NULL, flags) != TCL_OK) return TCL_ERROR; } return TCL_OK; } /* *-------------------------------------------------------------- * * TreeStateCmd -- * * This procedure is invoked to process the [state] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeStateCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; static CONST84 char *commandName[] = { "define", "linkage", "names", "undefine", (char *) NULL }; enum { COMMAND_DEFINE, COMMAND_LINKAGE, COMMAND_NAMES, COMMAND_UNDEFINE }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandName, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_DEFINE: { char *string; int i, length, slot = -1; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "stateName"); return TCL_ERROR; } string = Tcl_GetStringFromObj(objv[3], &length); if (!length || (*string == '~') || (*string == '!')) { FormatResult(interp, "invalid state name \"%s\"", string); return TCL_ERROR; } for (i = 0; i < 32; i++) { if (tree->stateNames[i] == NULL) { if (slot == -1) slot = i; continue; } if (strcmp(tree->stateNames[i], string) == 0) { FormatResult(interp, "state \"%s\" already defined", string); return TCL_ERROR; } } if (slot == -1) { FormatResult(interp, "cannot define any more states"); return TCL_ERROR; } tree->stateNames[slot] = ckalloc(length + 1); strcpy(tree->stateNames[slot], string); break; } case COMMAND_LINKAGE: { int index; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "state"); return TCL_ERROR; } if (Tree_StateFromObj(tree, objv[3], NULL, &index, SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewStringObj( (index < STATE_USER - 1) ? "static" : "dynamic", -1)); break; } case COMMAND_NAMES: { Tcl_Obj *listObj; int i; if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } listObj = Tcl_NewListObj(0, NULL); for (i = STATE_USER - 1; i < 32; i++) { if (tree->stateNames[i] != NULL) Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(tree->stateNames[i], -1)); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_UNDEFINE: { int i, index; for (i = 3; i < objc; i++) { if (Tree_StateFromObj(tree, objv[i], NULL, &index, SFO_NOT_STATIC | SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; Tree_UndefineState(tree, 1L << index); PerStateInfo_Undefine(tree, &pstBitmap, &tree->buttonBitmap, 1L << index); PerStateInfo_Undefine(tree, &pstImage, &tree->buttonImage, 1L << index); ckfree(tree->stateNames[index]); tree->stateNames[index] = NULL; } break; } } return TCL_OK; } /* *-------------------------------------------------------------- * * Tree_AddToSelection -- * * Add an item to the hash table of selected items. Turn on the * STATE_SELECTED state for the item. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_AddToSelection( TreeCtrl *tree, /* Widget info */ TreeItem item /* Item to add to the selection. */ ) { Tcl_HashEntry *hPtr; int isNew; #ifdef SELECTION_VISIBLE if (!TreeItem_ReallyVisible(tree, item)) panic("Tree_AddToSelection: item %d not ReallyVisible", TreeItem_GetID(tree, item)); #endif if (TreeItem_GetSelected(tree, item)) panic("Tree_AddToSelection: item %d already selected", TreeItem_GetID(tree, item)); if (!TreeItem_GetEnabled(tree, item)) panic("Tree_AddToSelection: item %d not enabled", TreeItem_GetID(tree, item)); TreeItem_ChangeState(tree, item, 0, STATE_SELECTED); hPtr = Tcl_CreateHashEntry(&tree->selection, (char *) item, &isNew); if (!isNew) panic("Tree_AddToSelection: item %d already in selection hash table", TreeItem_GetID(tree, item)); tree->selectCount++; } /* *-------------------------------------------------------------- * * Tree_RemoveFromSelection -- * * Remove an item from the hash table of selected items. Turn off the * STATE_SELECTED state for the item. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_RemoveFromSelection( TreeCtrl *tree, /* Widget info */ TreeItem item /* Item to remove from the selection. */ ) { Tcl_HashEntry *hPtr; if (!TreeItem_GetSelected(tree, item)) panic("Tree_RemoveFromSelection: item %d isn't selected", TreeItem_GetID(tree, item)); TreeItem_ChangeState(tree, item, STATE_SELECTED, 0); hPtr = Tcl_FindHashEntry(&tree->selection, (char *) item); if (hPtr == NULL) panic("Tree_RemoveFromSelection: item %d not found in selection hash table", TreeItem_GetID(tree, item)); Tcl_DeleteHashEntry(hPtr); tree->selectCount--; } /* *-------------------------------------------------------------- * * TreeSelectionCmd -- * * This procedure is invoked to process the [selection] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeSelectionCmd( Tcl_Interp *interp, /* Current interpreter. */ TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { static CONST84 char *commandName[] = { "add", "anchor", "clear", "count", "get", "includes", "modify", NULL }; enum { COMMAND_ADD, COMMAND_ANCHOR, COMMAND_CLEAR, COMMAND_COUNT, COMMAND_GET, COMMAND_INCLUDES, COMMAND_MODIFY }; int index; TreeItemList itemsFirst, itemsLast; TreeItem item, itemFirst, itemLast; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandName, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_ADD: { int i, count; TreeItemList items; Tcl_HashEntry *hPtr; Tcl_HashSearch search; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "first ?last?"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[3], &itemsFirst, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; itemFirst = TreeItemList_Nth(&itemsFirst, 0); itemLast = NULL; if (objc == 5) { if (TreeItemList_FromObj(tree, objv[4], &itemsLast, IFO_NOT_NULL) != TCL_OK) { TreeItemList_Free(&itemsFirst); return TCL_ERROR; } itemLast = TreeItemList_Nth(&itemsLast, 0); } if ((itemFirst == ITEM_ALL) || (itemLast == ITEM_ALL)) { if (objc == 5) TreeItemList_Free(&itemsLast); TreeItemList_Init(tree, &items, tree->itemCount - tree->selectCount); /* Include orphans. */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); #ifdef SELECTION_VISIBLE if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item) && TreeItem_ReallyVisible(tree, item)) { #else if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item)) { #endif Tree_AddToSelection(tree, item); TreeItemList_Append(&items, item); } hPtr = Tcl_NextHashEntry(&search); } goto doneADD; } if (objc == 5) { TreeItemList_Free(&itemsFirst); TreeItemList_Free(&itemsLast); count = TreeItem_FirstAndLast(tree, &itemFirst, &itemLast); if (count == 0) return TCL_ERROR; TreeItemList_Init(tree, &items, count); while (1) { #ifdef SELECTION_VISIBLE if (!TreeItem_GetSelected(tree, itemFirst) && TreeItem_GetEnabled(tree, itemFirst) && TreeItem_ReallyVisible(tree, itemFirst)) { #else if (!TreeItem_GetSelected(tree, itemFirst) && TreeItem_GetEnabled(tree, itemFirst)) { #endif Tree_AddToSelection(tree, itemFirst); TreeItemList_Append(&items, itemFirst); } if (itemFirst == itemLast) break; itemFirst = TreeItem_Next(tree, itemFirst); } goto doneADD; } count = TreeItemList_Count(&itemsFirst); TreeItemList_Init(tree, &items, count); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&itemsFirst, i); #ifdef SELECTION_VISIBLE if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item) && TreeItem_ReallyVisible(tree, item)) { #else if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item)) { #endif Tree_AddToSelection(tree, item); TreeItemList_Append(&items, item); } } doneADD: if (TreeItemList_Count(&items)) { TreeNotify_Selection(tree, &items, NULL); } TreeItemList_Free(&items); TreeItemList_Free(&itemsFirst); break; } case COMMAND_ANCHOR: { if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "?item?"); return TCL_ERROR; } if (objc == 4) { if (TreeItem_FromObj(tree, objv[3], &item, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } tree->anchorItem = item; } Tcl_SetObjResult(interp, TreeItem_ToObj(tree, tree->anchorItem)); break; } case COMMAND_CLEAR: { int i, count; TreeItemList items; Tcl_HashEntry *hPtr; Tcl_HashSearch search; if (objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "?first? ?last?"); return TCL_ERROR; } itemFirst = itemLast = NULL; if (objc >= 4) { if (TreeItemList_FromObj(tree, objv[3], &itemsFirst, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; itemFirst = TreeItemList_Nth(&itemsFirst, 0); } if (objc == 5) { if (TreeItemList_FromObj(tree, objv[4], &itemsLast, IFO_NOT_NULL) != TCL_OK) { TreeItemList_Free(&itemsFirst); return TCL_ERROR; } itemLast = TreeItemList_Nth(&itemsLast, 0); } if (tree->selectCount < 1) { if (objc >= 4) TreeItemList_Free(&itemsFirst); if (objc == 5) TreeItemList_Free(&itemsLast); break; } if ((objc == 3) || (itemFirst == ITEM_ALL) || (itemLast == ITEM_ALL)) { if (objc >= 4) TreeItemList_Free(&itemsFirst); if (objc == 5) TreeItemList_Free(&itemsLast); TreeItemList_Init(tree, &items, tree->selectCount); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); TreeItemList_Append(&items, item); hPtr = Tcl_NextHashEntry(&search); } count = TreeItemList_Count(&items); for (i = 0; i < count; i++) Tree_RemoveFromSelection(tree, TreeItemList_Nth(&items, i)); goto doneCLEAR; } if (objc == 5) { TreeItemList_Free(&itemsFirst); TreeItemList_Free(&itemsLast); count = TreeItem_FirstAndLast(tree, &itemFirst, &itemLast); if (count == 0) return TCL_ERROR; TreeItemList_Init(tree, &items, count); while (1) { if (TreeItem_GetSelected(tree, itemFirst)) { Tree_RemoveFromSelection(tree, itemFirst); TreeItemList_Append(&items, itemFirst); } if (itemFirst == itemLast) break; itemFirst = TreeItem_Next(tree, itemFirst); } goto doneCLEAR; } count = TreeItemList_Count(&itemsFirst); TreeItemList_Init(tree, &items, count); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&itemsFirst, i); if (TreeItem_GetSelected(tree, item)) { Tree_RemoveFromSelection(tree, item); TreeItemList_Append(&items, item); } } TreeItemList_Free(&itemsFirst); doneCLEAR: if (TreeItemList_Count(&items)) { TreeNotify_Selection(tree, NULL, &items); } TreeItemList_Free(&items); break; } case COMMAND_COUNT: { if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(tree->selectCount)); break; } case COMMAND_GET: { TreeItem item; Tcl_Obj *listObj; Tcl_HashEntry *hPtr; Tcl_HashSearch search; #ifdef SELECTION_VISIBLE if (objc < 3 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "?first? ?last?"); return TCL_ERROR; } if (objc > 3) { int first, last; TreeItemList items; if (TclGetIntForIndex(interp, objv[3], (int)tree->selectCount - 1, &first) != TCL_OK) { return TCL_ERROR; } if (first < 0) first = 0; last = first; if (objc == 5) { if (TclGetIntForIndex(interp, objv[4], (int)tree->selectCount - 1, &last) != TCL_OK) { return TCL_ERROR; } } if (last >= tree->selectCount) last = tree->selectCount - 1; if (first > last) break; /* Build a list of selected items. */ TreeItemList_Init(tree, &items, tree->selectCount); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); TreeItemList_Append(&items, item); hPtr = Tcl_NextHashEntry(&search); } /* Sort it. */ TreeItemList_Sort(&items); if (first == last) { item = TreeItemList_Nth(&items, first); Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item)); } else { listObj = Tcl_NewListObj(0, NULL); for (index = first; index <= last; index++) { item = TreeItemList_Nth(&items, index); Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); } Tcl_SetObjResult(interp, listObj); } TreeItemList_Free(&items); break; } #else /* SELECTION_VISIBLE */ /* If any item may be selected, including orphans, then getting * a sorted list of selected items is impossible. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } #endif /* SELECTION_VISIBLE */ if (tree->selectCount < 1) break; listObj = Tcl_NewListObj(0, NULL); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); hPtr = Tcl_NextHashEntry(&search); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_INCLUDES: { if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "item"); return TCL_ERROR; } if (TreeItem_FromObj(tree, objv[3], &item, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewBooleanObj( TreeItem_GetSelected(tree, item))); break; } case COMMAND_MODIFY: { int i, j, k, objcS, objcD; Tcl_Obj **objvS, **objvD; Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeItem item; TreeItemList items; TreeItemList itemS, itemD, newS, newD; int allS = FALSE, allD = FALSE; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "select deselect"); return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[3], &objcS, &objvS) != TCL_OK) return TCL_ERROR; if (Tcl_ListObjGetElements(interp, objv[4], &objcD, &objvD) != TCL_OK) return TCL_ERROR; /* No change */ if (!objcS && !objcD) break; /* Some of these may get double-initialized. */ TreeItemList_Init(tree, &itemS, 0); TreeItemList_Init(tree, &itemD, 0); TreeItemList_Init(tree, &newS, 0); TreeItemList_Init(tree, &newD, 0); /* List of items to select */ for (i = 0; i < objcS; i++) { if (TreeItemList_FromObj(tree, objvS[i], &items, IFO_NOT_NULL) != TCL_OK) { TreeItemList_Free(&itemS); return TCL_ERROR; } /* Add unique items to itemS */ for (k = 0; k < TreeItemList_Count(&items); k++) { item = TreeItemList_Nth(&items, k); if (item == ITEM_ALL) { allS = TRUE; break; } for (j = 0; j < TreeItemList_Count(&itemS); j++) { if (TreeItemList_Nth(&itemS, j) == item) break; } if (j == TreeItemList_Count(&itemS)) { TreeItemList_Append(&itemS, item); } } TreeItemList_Free(&items); if (allS) break; } /* List of items to deselect */ for (i = 0; i < objcD; i++) { if (TreeItemList_FromObj(tree, objvD[i], &items, IFO_NOT_NULL) != TCL_OK) { TreeItemList_Free(&itemS); TreeItemList_Free(&itemD); return TCL_ERROR; } /* Add unique items to itemD */ for (k = 0; k < TreeItemList_Count(&items); k++) { item = TreeItemList_Nth(&items, k); if (item == ITEM_ALL) { allD = TRUE; break; } for (j = 0; j < TreeItemList_Count(&itemD); j++) { if (TreeItemList_Nth(&itemD, j) == item) break; } if (j == TreeItemList_Count(&itemD)) { TreeItemList_Append(&itemD, item); } } TreeItemList_Free(&items); if (allD) break; } /* Select all */ if (allS) { TreeItemList_Init(tree, &newS, tree->itemCount - tree->selectCount); #ifdef SELECTION_VISIBLE item = tree->root; if (!TreeItem_ReallyVisible(tree, item)) item = TreeItem_NextVisible(tree, item); while (item != NULL) { if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item)) { TreeItemList_Append(&newS, item); } item = TreeItem_NextVisible(tree, item); } #else /* Include detached items */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item)) { TreeItemList_Append(&newS, item); } hPtr = Tcl_NextHashEntry(&search); } #endif /* Ignore the deselect list. */ goto modifyDONE; } /* Select some */ if (objcS > 0) { TreeItemList_Init(tree, &newS, objcS); for (i = 0; i < TreeItemList_Count(&itemS); i++) { item = TreeItemList_Nth(&itemS, i); if (TreeItem_GetSelected(tree, item)) continue; if (!TreeItem_GetEnabled(tree, item)) continue; #ifdef SELECTION_VISIBLE if (!TreeItem_ReallyVisible(tree, item)) continue; #endif TreeItemList_Append(&newS, item); } } /* Deselect all */ if (allD) { TreeItemList_Init(tree, &newD, tree->selectCount); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); /* Don't deselect an item in the select list */ for (j = 0; j < TreeItemList_Count(&itemS); j++) { if (item == TreeItemList_Nth(&itemS, j)) break; } if (j == TreeItemList_Count(&itemS)) { TreeItemList_Append(&newD, item); } hPtr = Tcl_NextHashEntry(&search); } } /* Deselect some */ if ((objcD > 0) && !allD) { TreeItemList_Init(tree, &newD, objcD); for (i = 0; i < TreeItemList_Count(&itemD); i++) { item = TreeItemList_Nth(&itemD, i); if (!TreeItem_GetSelected(tree, item)) continue; /* Don't deselect an item in the select list */ for (j = 0; j < TreeItemList_Count(&itemS); j++) { if (item == TreeItemList_Nth(&itemS, j)) break; } if (j == TreeItemList_Count(&itemS)) { TreeItemList_Append(&newD, item); } } } modifyDONE: for (i = 0; i < TreeItemList_Count(&newS); i++) Tree_AddToSelection(tree, TreeItemList_Nth(&newS, i)); for (i = 0; i < TreeItemList_Count(&newD); i++) Tree_RemoveFromSelection(tree, TreeItemList_Nth(&newD, i)); if (TreeItemList_Count(&newS) || TreeItemList_Count(&newD)) { TreeNotify_Selection(tree, &newS, &newD); } TreeItemList_Free(&newS); TreeItemList_Free(&itemS); TreeItemList_Free(&newD); TreeItemList_Free(&itemD); break; } } return TCL_OK; } /* *-------------------------------------------------------------- * * A_XviewCmd -- * * This procedure is invoked to process the "xview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * NOTE: This procedure is called when the -xscrollincrement option * is specified. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int A_XviewCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; if (objc == 2) { double fractions[2]; char buf[TCL_DOUBLE_SPACE * 2]; Tree_GetScrollFractionsX(tree, fractions); sprintf(buf, "%g %g", fractions[0], fractions[1]); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else { int count, index = 0, indexMax, offset, type; double fraction; int visWidth = Tree_ContentWidth(tree); int totWidth = Tree_TotalWidth(tree); int xIncr = tree->xScrollIncrement; if (visWidth < 0) visWidth = 0; if (totWidth <= visWidth) return TCL_OK; if (visWidth > 1) { /* Find incrementLeft when scrolled to extreme right */ indexMax = Increment_FindX(tree, totWidth - visWidth); offset = Increment_ToOffsetX(tree, indexMax); if (offset < totWidth - visWidth) { indexMax++; offset = Increment_ToOffsetX(tree, indexMax); } /* Add some fake content to right */ if (offset + visWidth > totWidth) totWidth = offset + visWidth; } else { indexMax = Increment_FindX(tree, totWidth); visWidth = 1; } type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: return TCL_ERROR; case TK_SCROLL_MOVETO: offset = (int) (fraction * totWidth + 0.5); index = Increment_FindX(tree, offset); break; case TK_SCROLL_PAGES: offset = Tree_ContentLeft(tree) + tree->xOrigin; offset += (int) (count * visWidth * 0.9); index = Increment_FindX(tree, offset); if ((count > 0) && (index == Increment_FindX(tree, Tree_ContentLeft(tree) + tree->xOrigin))) index++; break; case TK_SCROLL_UNITS: offset = Tree_ContentLeft(tree) + tree->xOrigin; index = offset / xIncr; index += count; break; } /* Don't scroll too far left */ if (index < 0) index = 0; /* Don't scroll too far right */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetX(tree, index); if (offset - Tree_ContentLeft(tree) != tree->xOrigin) { tree->xOrigin = offset - Tree_ContentLeft(tree); Tree_EventuallyRedraw(tree); } } return TCL_OK; } /* *-------------------------------------------------------------- * * A_YviewCmd -- * * This procedure is invoked to process the "yview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * NOTE: This procedure is called when the -yscrollincrement option * is specified. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int A_YviewCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; if (objc == 2) { double fractions[2]; char buf[TCL_DOUBLE_SPACE * 2]; Tree_GetScrollFractionsY(tree, fractions); sprintf(buf, "%g %g", fractions[0], fractions[1]); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else { int count, index = 0, indexMax, offset, type; double fraction; int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); int yIncr = tree->yScrollIncrement; if (visHeight < 0) visHeight = 0; if (totHeight <= visHeight) return TCL_OK; if (visHeight > 1) { /* Find incrementTop when scrolled to bottom */ indexMax = Increment_FindY(tree, totHeight - visHeight); offset = Increment_ToOffsetY(tree, indexMax); if (offset < totHeight - visHeight) { indexMax++; offset = Increment_ToOffsetY(tree, indexMax); } /* Add some fake content to bottom */ if (offset + visHeight > totHeight) totHeight = offset + visHeight; } else { indexMax = Increment_FindY(tree, totHeight); visHeight = 1; } type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: return TCL_ERROR; case TK_SCROLL_MOVETO: offset = (int) (fraction * totHeight + 0.5); index = Increment_FindY(tree, offset); break; case TK_SCROLL_PAGES: offset = Tree_ContentTop(tree) + tree->yOrigin; offset += (int) (count * visHeight * 0.9); index = Increment_FindY(tree, offset); if ((count > 0) && (index == Increment_FindY(tree, Tree_ContentTop(tree) + tree->yOrigin))) index++; break; case TK_SCROLL_UNITS: offset = Tree_ContentTop(tree) + tree->yOrigin; index = offset / yIncr; index += count; break; } /* Don't scroll too far left */ if (index < 0) index = 0; /* Don't scroll too far right */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetY(tree, index); if (offset - Tree_ContentTop(tree) != tree->yOrigin) { tree->yOrigin = offset - Tree_ContentTop(tree); Tree_EventuallyRedraw(tree); } } return TCL_OK; } /* *-------------------------------------------------------------- * * TreeXviewCmd -- * * This procedure is invoked to process the "xview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeXviewCmd( Tcl_Interp *interp, /* Current interpreter. */ TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { if (tree->xScrollIncrement <= 0) return B_XviewCmd(tree, objc, objv); return A_XviewCmd(tree, objc, objv); } /* *-------------------------------------------------------------- * * TreeYviewCmd -- * * This procedure is invoked to process the "yview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeYviewCmd( Tcl_Interp *interp, /* Current interpreter. */ TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { if (tree->yScrollIncrement <= 0) return B_YviewCmd(tree, objc, objv); return A_YviewCmd(tree, objc, objv); } void Tree_Debug( TreeCtrl *tree /* Widget info. */ ) { if (TreeItem_Debug(tree, tree->root) != TCL_OK) { dbwin("Tree_Debug: %s\n", Tcl_GetStringResult(tree->interp)); Tcl_BackgroundError(tree->interp); } } /* *-------------------------------------------------------------- * * TreeDebugCmd -- * * This procedure is invoked to process the [debug] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeDebugCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandNames[] = { "alloc", "cget", "configure", "dinfo", "expose", "scroll", (char *) NULL }; enum { COMMAND_ALLOC, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DINFO, COMMAND_EXPOSE, COMMAND_SCROLL }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T debug alloc */ case COMMAND_ALLOC: { #ifdef ALLOC_HAX #ifdef TREECTRL_DEBUG AllocHax_Stats(interp, tree->allocData); #else FormatResult(interp, "TREECTRL_DEBUG is not defined"); #endif #else FormatResult(interp, "ALLOC_HAX is not defined"); #endif break; } /* T debug cget option */ case COMMAND_CGET: { Tcl_Obj *resultObjPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(interp, (char *) tree, tree->debug.optionTable, objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T debug configure ?option? ?value? ?option value ...? */ case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr; Tk_SavedOptions savedOptions; int mask, result; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?option? ?value?"); return TCL_ERROR; } if (objc <= 4) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) tree, tree->debug.optionTable, (objc == 3) ? (Tcl_Obj *) NULL : objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } result = Tk_SetOptions(interp, (char *) tree, tree->debug.optionTable, objc - 3, objv + 3, tree->tkwin, &savedOptions, &mask); if (result != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } Tk_FreeSavedOptions(&savedOptions); if (tree->debug.eraseColor != NULL) { tree->debug.gcErase = Tk_GCForColor(tree->debug.eraseColor, Tk_WindowId(tree->tkwin)); } if (tree->debug.drawColor != NULL) { tree->debug.gcDraw = Tk_GCForColor(tree->debug.drawColor, Tk_WindowId(tree->tkwin)); } break; } case COMMAND_DINFO: { extern void DumpDInfo(TreeCtrl *tree, int index); static CONST84 char *optionNames[] = { "ditem", "onscreen", "range", (char *) NULL }; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], optionNames, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } DumpDInfo(tree, index); break; } /* T debug expose x1 y1 x2 y2 */ case COMMAND_EXPOSE: { int x1, y1, x2, y2; if (objc != 7) { Tcl_WrongNumArgs(interp, 3, objv, "x1 y1 x2 y2"); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[3], &x1) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y1) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[5], &x2) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[6], &y2) != TCL_OK) return TCL_ERROR; Tree_RedrawArea(tree, MIN(x1, x2), MIN(y1, y2), MAX(x1, x2), MAX(y1, y2)); break; } case COMMAND_SCROLL: { int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); int yIncr = tree->yScrollIncrement; if (yIncr <= 0) yIncr = tree->itemHeight; if (yIncr <= 0) yIncr = 1; FormatResult(interp, "visHeight %d totHeight %d visHeight %% yIncr %d totHeight %% yIncr %d", visHeight, totHeight, visHeight % yIncr, totHeight % yIncr ); break; } } return TCL_OK; } /* *-------------------------------------------------------------- * * Tree_PreserveItems -- * * Increment tree->preserveItemRefCnt. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_PreserveItems( TreeCtrl *tree ) { tree->preserveItemRefCnt++; } /* *-------------------------------------------------------------- * * Tree_ReleaseItems -- * * Decrement tree->preserveItemRefCnt. If it reaches zero, * release the storage of items marked as deleted. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_ReleaseItems( TreeCtrl *tree ) { int i, count; TreeItem item; if (tree->preserveItemRefCnt == 0) panic("mismatched calls to Tree_PreserveItems/Tree_ReleaseItems"); if (--tree->preserveItemRefCnt > 0) return; count = TreeItemList_Count(&tree->preserveItemList); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&tree->preserveItemList, i); TreeItem_Release(tree, item); } TreeItemList_Free(&tree->preserveItemList); } /* *-------------------------------------------------------------- * * TextLayoutCmd -- * * This procedure is invoked to process the [textlayout] Tcl * command. The command is used by the library scripts to place * the text-edit Entry or Text widget. * * Results: * A standard Tcl result. * * Side effects: * None. * *-------------------------------------------------------------- */ /* textlayout $font $text -width pixels -wrap word|char -justify left|center|right -ignoretabs boolean -ignorenewlines boolean */ int TextLayoutCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tk_Font tkfont; Tk_Window tkwin = Tk_MainWindow(interp); char *text; int flags = 0; Tk_Justify justify = TK_JUSTIFY_LEFT; Tk_TextLayout layout; int width = 0, height; int result = TCL_OK; int i; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "font text ?options ...?"); return TCL_ERROR; } tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[1]); if (tkfont == NULL) return TCL_ERROR; text = Tcl_GetString(objv[2]); for (i = 3; i < objc; i += 2) { static CONST84 char *optionNames[] = { "-ignoretabs", "-ignorenewlines", "-justify", "-width", (char *) NULL }; enum { OPT_IGNORETABS, OPT_IGNORENEWLINES, OPT_JUSTIFY, OPT_WIDTH }; int index; if (Tcl_GetIndexFromObj(interp, objv[i], optionNames, "option", 0, &index) != TCL_OK) { result = TCL_ERROR; goto done; } if (i + 1 == objc) { FormatResult(interp, "missing value for \"%s\" option", optionNames[index]); goto done; } switch (index) { case OPT_IGNORENEWLINES: { int v; if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &v) != TCL_OK) { result = TCL_ERROR; goto done; } if (v) flags |= TK_IGNORE_NEWLINES; else flags &= ~TK_IGNORE_NEWLINES; break; } case OPT_IGNORETABS: { int v; if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &v) != TCL_OK) { result = TCL_ERROR; goto done; } if (v) flags |= TK_IGNORE_TABS; else flags &= ~TK_IGNORE_TABS; break; } case OPT_JUSTIFY: { if (Tk_GetJustifyFromObj(interp, objv[i + 1], &justify) != TCL_OK) { result = TCL_ERROR; goto done; } break; } case OPT_WIDTH: { if (Tk_GetPixelsFromObj(interp, tkwin, objv[i + 1], &width) != TCL_OK) { result = TCL_ERROR; goto done; } break; } } } layout = Tk_ComputeTextLayout(tkfont, text, -1, width, justify, flags, &width, &height); FormatResult(interp, "%d %d", width, height); Tk_FreeTextLayout(layout); done: Tk_FreeFont(tkfont); return result; } /* *-------------------------------------------------------------- * * ImageTintCmd -- * * This procedure is invoked to process the [imagetint] Tcl * command. The command may be used to apply a highlight to an * existing photo image. It is used by the demos to produce a * selected version of an image. * * Results: * A standard Tcl result. * * Side effects: * A photo image is modified. * *-------------------------------------------------------------- */ int ImageTintCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { char *imageName; Tk_PhotoHandle photoH; Tk_PhotoImageBlock photoBlock; XColor *xColor; unsigned char *pixelPtr, *photoPix; int x, y, alpha, imgW, imgH, pitch; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "imageName color alpha"); return TCL_ERROR; } imageName = Tcl_GetStringFromObj(objv[1], NULL); photoH = Tk_FindPhoto(interp, imageName); if (photoH == NULL) { Tcl_AppendResult(interp, "image \"", imageName, "\" doesn't exist or is not a photo image", (char *) NULL); return TCL_ERROR; } xColor = Tk_AllocColorFromObj(interp, Tk_MainWindow(interp), objv[2]); if (xColor == NULL) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[3], &alpha) != TCL_OK) return TCL_ERROR; if (alpha < 0) alpha = 0; if (alpha > 255) alpha = 255; Tk_PhotoGetImage(photoH, &photoBlock); photoPix = photoBlock.pixelPtr; imgW = photoBlock.width; imgH = photoBlock.height; pitch = photoBlock.pitch; pixelPtr = (unsigned char *) Tcl_Alloc(imgW * 4); photoBlock.pixelPtr = pixelPtr; photoBlock.width = imgW; photoBlock.height = 1; photoBlock.pitch = imgW * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (x = 0; x < imgW; x++) { pixelPtr[x*4 + 0] = UCHAR(((double) xColor->red / USHRT_MAX) * 255); pixelPtr[x*4 + 1] = UCHAR(((double) xColor->green / USHRT_MAX) * 255); pixelPtr[x*4 + 2] = UCHAR(((double) xColor->blue / USHRT_MAX) * 255); } for (y = 0; y < imgH; y++) { for (x = 0; x < imgW; x++) { if (photoPix[x * 4 + 3]) { pixelPtr[x * 4 + 3] = alpha; } else { pixelPtr[x * 4 + 3] = 0; } } TK_PHOTOPUTBLOCK(interp, photoH, &photoBlock, 0, y, imgW, 1, TK_PHOTO_COMPOSITE_OVERLAY); photoPix += pitch; } Tcl_Free((char *) photoBlock.pixelPtr); return TCL_OK; } /* *-------------------------------------------------------------- * * LoupeCmd -- * * This procedure is invoked to process the [loupe] Tcl * command. The command is used to perform a screen grab on the * root window and place a magnified version of the screen grab * into an existing photo image. The command is used to check those * dotted lines and make sure they line up properly. * * Results: * A standard Tcl result. * * Side effects: * A photo image is modified. * *-------------------------------------------------------------- */ int LoupeCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tk_Window tkwin = Tk_MainWindow(interp); Display *display = Tk_Display(tkwin); int screenNum = Tk_ScreenNumber(tkwin); int displayW = DisplayWidth(display, screenNum); int displayH = DisplayHeight(display, screenNum); char *imageName; Tk_PhotoHandle photoH; Tk_PhotoImageBlock photoBlock; unsigned char *pixelPtr; int x, y, w, h, zoom; int grabX, grabY, grabW, grabH; int minx = 0, miny = 0; #ifdef WIN32 int xx, yy; HWND hwnd; HDC hdc; #elif defined(MAC_TCL) || defined(MAC_OSX_TK) #else Visual *visual = Tk_Visual(tkwin); Window rootWindow = RootWindow(display, screenNum); XImage *ximage; XColor *xcolors; unsigned long red_shift, green_shift, blue_shift; int i, ncolors; int separated = 0; #endif /* * x && y are points on screen to snap from * w && h are size of image to grab (default to image size) * zoom is the integer zoom factor to grab */ if ((objc != 4) && (objc != 6) && (objc != 7)) { Tcl_WrongNumArgs(interp, 1, objv, "imageName x y ?w h? ?zoom?"); return TCL_ERROR; } imageName = Tcl_GetStringFromObj(objv[1], NULL); photoH = Tk_FindPhoto(interp, imageName); if (photoH == NULL) { Tcl_AppendResult(interp, "image \"", imageName, "\" doesn't exist or is not a photo image", (char *) NULL); return TCL_ERROR; } if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { return TCL_ERROR; } if (objc >= 6) { if ((Tcl_GetIntFromObj(interp, objv[4], &w) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[5], &h) != TCL_OK)) { return TCL_ERROR; } } else { /* * Get dimensions from image */ Tk_PhotoGetSize(photoH, &w, &h); } if (objc == 7) { if (Tcl_GetIntFromObj(interp, objv[6], &zoom) != TCL_OK) { return TCL_ERROR; } } else { zoom = 1; } #ifdef WIN32 /* * Windows multiple monitors can have negative coords */ #ifndef SM_XVIRTUALSCREEN #define SM_XVIRTUALSCREEN 76 #define SM_YVIRTUALSCREEN 77 #define SM_CXVIRTUALSCREEN 78 #define SM_CYVIRTUALSCREEN 79 #endif minx = GetSystemMetrics(SM_XVIRTUALSCREEN); miny = GetSystemMetrics(SM_YVIRTUALSCREEN); displayW = GetSystemMetrics(SM_CXVIRTUALSCREEN); displayH = GetSystemMetrics(SM_CYVIRTUALSCREEN); #elif defined(MAC_TCL) || defined(MAC_OSX_TK) /* * OS X multiple monitors can have negative coords * FIX: must be implemented * Probably with CGDisplayPixelsWide & CGDisplayPixelsHigh, * may need to iterate existing displays */ #else /* * Does X11 allow for negative screen coords? */ #endif grabX = x - (w / zoom / 2); grabY = y - (h / zoom / 2); grabW = w / zoom; grabH = h / zoom; if (grabW > displayW) grabW = displayW; if (grabH > displayH) grabH = displayH; if (grabX < minx) grabX = minx; if (grabY < miny) grabY = miny; if (grabX + grabW > displayW) grabX = displayW - grabW; if (grabY + grabH > displayH) grabY = displayH - grabH; if ((grabW <= 0) || (grabH <= 0)) { return TCL_OK; } #ifdef WIN32 hwnd = GetDesktopWindow(); hdc = GetWindowDC(hwnd); /* XImage -> Tk_Image */ pixelPtr = (unsigned char *) Tcl_Alloc(grabW * grabH * 4); memset(pixelPtr, 0, (grabW * grabH * 4)); photoBlock.pixelPtr = pixelPtr; photoBlock.width = grabW; photoBlock.height = grabH; photoBlock.pitch = grabW * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; /* * We could do a BitBlt for bulk copying, but then we'd have to * do screen size consistency checks and possibly pixel conversion. */ for (yy = 0; yy < grabH; yy++) { COLORREF pixel; unsigned long stepDest = yy * photoBlock.pitch; for (xx = 0; xx < grabW; xx++) { pixel = GetPixel(hdc, grabX + xx, grabY + yy); if (pixel == CLR_INVALID) { /* * Skip just this pixel, as others will be valid depending on * what corner we are in. */ continue; } pixelPtr[stepDest + xx * 4 + 0] = GetRValue(pixel); pixelPtr[stepDest + xx * 4 + 1] = GetGValue(pixel); pixelPtr[stepDest + xx * 4 + 2] = GetBValue(pixel); pixelPtr[stepDest + xx * 4 + 3] = 255; } } ReleaseDC(hwnd, hdc); #elif defined(MAC_TCL) || defined(MAC_OSX_TK) /* * Adapted from John Anon's ScreenController demo code. */ { int xx, yy; unsigned char *screenBytes; int bPerPixel, byPerRow, byPerPixel; // Gets all the screen info: CGDisplayHideCursor(kCGDirectMainDisplay); bPerPixel = CGDisplayBitsPerPixel(kCGDirectMainDisplay); byPerRow = CGDisplayBytesPerRow(kCGDirectMainDisplay); byPerPixel = bPerPixel / 8; screenBytes = (unsigned char *)CGDisplayBaseAddress(kCGDirectMainDisplay); pixelPtr = (unsigned char *) Tcl_Alloc(grabW * grabH * 4); memset(pixelPtr, 0, (grabW * grabH * 4)); photoBlock.pixelPtr = pixelPtr; photoBlock.width = grabW; photoBlock.height = grabH; photoBlock.pitch = grabW * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (yy = 0; yy < grabH; yy++) { unsigned long newPixel = 0; unsigned long stepSrc = (grabY + yy) * byPerRow; unsigned long stepDest = yy * photoBlock.pitch; for (xx = 0; xx < grabW; xx++) { if (bPerPixel == 16) { unsigned short thisPixel; thisPixel = *((unsigned short*)(screenBytes + stepSrc + ((grabX + xx) * byPerPixel))); #ifdef WORDS_BIGENDIAN /* Transform from 0xARGB (1555) to 0xR0G0B0A0 (4444) */ newPixel = (((thisPixel & 0x8000) >> 15) * 0xF8) | /* A */ ((thisPixel & 0x7C00) << 17) | /* R */ ((thisPixel & 0x03E0) << 14) | /* G */ ((thisPixel & 0x001F) << 11); /* B */ #else /* Transform from 0xARGB (1555) to 0xB0G0R0A0 (4444) */ newPixel = (((thisPixel & 0x8000) >> 15) * 0xF8) | /* A */ ((thisPixel & 0x7C00) << 11) | /* R */ ((thisPixel & 0x03E0) << 14) | /* G */ ((thisPixel & 0x001F) << 17); /* B */ #endif } else if (bPerPixel == 32) { unsigned long thisPixel; thisPixel = *((unsigned long*)(screenBytes + stepSrc + ((grabX + xx) * byPerPixel))); #ifdef WORDS_BIGENDIAN /* Transformation is from 0xAARRGGBB to 0xRRGGBBAA */ newPixel = ((thisPixel & 0xFF000000) >> 24) | ((thisPixel & 0x00FFFFFF) << 8); #else /* Transformation is from 0xAARRGGBB to 0xBBGGRRAA */ newPixel = (thisPixel & 0xFF00FF00) | ((thisPixel & 0x00FF0000) >> 16) | ((thisPixel & 0x000000FF) << 16); #endif } *((unsigned int *)(pixelPtr + stepDest + xx * 4)) = newPixel; } } CGDisplayShowCursor(kCGDirectMainDisplay); } #else ximage = XGetImage(display, rootWindow, grabX, grabY, grabW, grabH, AllPlanes, ZPixmap); if (ximage == NULL) { FormatResult(interp, "XGetImage() failed"); return TCL_ERROR; } /* See TkPostscriptImage */ ncolors = visual->map_entries; xcolors = (XColor *) ckalloc(sizeof(XColor) * ncolors); if ((visual->class == DirectColor) || (visual->class == TrueColor)) { separated = 1; red_shift = green_shift = blue_shift = 0; while ((0x0001 & (ximage->red_mask >> red_shift)) == 0) red_shift++; while ((0x0001 & (ximage->green_mask >> green_shift)) == 0) green_shift++; while ((0x0001 & (ximage->blue_mask >> blue_shift)) == 0) blue_shift++; for (i = 0; i < ncolors; i++) { xcolors[i].pixel = ((i << red_shift) & ximage->red_mask) | ((i << green_shift) & ximage->green_mask) | ((i << blue_shift) & ximage->blue_mask); } } else { for (i = 0; i < ncolors; i++) xcolors[i].pixel = i; } XQueryColors(display, Tk_Colormap(tkwin), xcolors, ncolors); /* XImage -> Tk_Image */ pixelPtr = (unsigned char *) Tcl_Alloc(ximage->width * ximage->height * 4); photoBlock.pixelPtr = pixelPtr; photoBlock.width = ximage->width; photoBlock.height = ximage->height; photoBlock.pitch = ximage->width * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (y = 0; y < ximage->height; y++) { for (x = 0; x < ximage->width; x++) { int r, g, b; unsigned long pixel; pixel = XGetPixel(ximage, x, y); if (separated) { r = (pixel & ximage->red_mask) >> red_shift; g = (pixel & ximage->green_mask) >> green_shift; b = (pixel & ximage->blue_mask) >> blue_shift; r = ((double) xcolors[r].red / USHRT_MAX) * 255; g = ((double) xcolors[g].green / USHRT_MAX) * 255; b = ((double) xcolors[b].blue / USHRT_MAX) * 255; } else { r = ((double) xcolors[pixel].red / USHRT_MAX) * 255; g = ((double) xcolors[pixel].green / USHRT_MAX) * 255; b = ((double) xcolors[pixel].blue / USHRT_MAX) * 255; } pixelPtr[y * photoBlock.pitch + x * 4 + 0] = r; pixelPtr[y * photoBlock.pitch + x * 4 + 1] = g; pixelPtr[y * photoBlock.pitch + x * 4 + 2] = b; pixelPtr[y * photoBlock.pitch + x * 4 + 3] = 255; } } #endif TK_PHOTOPUTZOOMEDBLOCK(interp, photoH, &photoBlock, 0, 0, w, h, zoom, zoom, 1, 1, TK_PHOTO_COMPOSITE_SET); Tcl_Free((char *) pixelPtr); #if !defined(WIN32) && !defined(MAC_TCL) && !defined(MAC_OSX_TK) ckfree((char *) xcolors); XDestroyImage(ximage); #endif return TCL_OK; } /* *-------------------------------------------------------------- * * RecomputeWidgets -- * * This procedure is called when the system theme changes on platforms * that support theming. The worldChangedProc of all treectrl widgets * is called to relayout and redisplay the widgets. * * Taken from tkFont.c. * * Results: * None. * * Side effects: * All treectrl widgets will be redisplayed at idle time. * *-------------------------------------------------------------- */ static void RecomputeWidgets( TkWindow *winPtr /* Window info. */ ) { Tk_ClassWorldChangedProc *proc; /* Clomp! Stomp! All over the internals */ proc = Tk_GetClassProc(winPtr->classProcsPtr, worldChangedProc); if (proc == TreeWorldChanged) { TreeTheme_ThemeChanged((TreeCtrl *) winPtr->instanceData); TreeWorldChanged(winPtr->instanceData); } for (winPtr = winPtr->childList; winPtr != NULL; winPtr = winPtr->nextPtr) { RecomputeWidgets(winPtr); } } /* *-------------------------------------------------------------- * * Tree_TheWorldHasChanged -- * * This procedure is called when the system theme changes on platforms * that support theming. The worldChangedProc of all treectrl widgets * is called to relayout and redisplay the widgets. * * Results: * None. * * Side effects: * All treectrl widgets will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_TheWorldHasChanged( Tcl_Interp *interp /* Current interpreter. */ ) { /* Could send a <> event to every window like Tile does. */ /* Could keep a list of treectrl widgets. */ TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp); RecomputeWidgets(winPtr); } /* * In order to find treectrl.tcl during initialization, the following script * is invoked. */ static char initScript[] = "if {![llength [info proc ::TreeCtrl::Init]]} {\n\ namespace eval ::TreeCtrl {}\n\ proc ::TreeCtrl::Init {} {\n\ global treectrl_library\n\ tcl_findLibrary treectrl 2.2.1 2.2.1 treectrl.tcl TREECTRL_LIBRARY treectrl_library\n\ }\n\ }\n\ ::TreeCtrl::Init"; /* *-------------------------------------------------------------- * * Treectrl_Init -- * * This procedure initializes the TreeCtrl package and related * commands. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. New Tcl commands are created. * *-------------------------------------------------------------- */ DLLEXPORT int Treectrl_Init( Tcl_Interp *interp /* Interpreter the package is loading into. */ ) { #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, "8.4", 0) == NULL) { return TCL_ERROR; } #endif #ifdef USE_TK_STUBS if (Tk_InitStubs(interp, "8.4", 0) == NULL) { return TCL_ERROR; } #endif PerStateCO_Init(optionSpecs, "-buttonbitmap", &pstBitmap, TreeStateFromObj); PerStateCO_Init(optionSpecs, "-buttonimage", &pstImage, TreeStateFromObj); if (TreeElement_Init(interp) != TCL_OK) { return TCL_ERROR; } /* We don't care if this fails */ (void) TreeTheme_InitInterp(interp); if (TreeColumn_InitInterp(interp) != TCL_OK) return TCL_ERROR; /* Hack for editing a text Element */ Tcl_CreateObjCommand(interp, "textlayout", TextLayoutCmd, NULL, NULL); /* Hack for colorizing a image (like Win98 explorer) */ Tcl_CreateObjCommand(interp, "imagetint", ImageTintCmd, NULL, NULL); /* Screen magnifier to check those dotted lines */ Tcl_CreateObjCommand(interp, "loupe", LoupeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "treectrl", TreeObjCmd, NULL, NULL); if (Tcl_PkgProvide(interp, "treectrl", "2.2.1") != TCL_OK) { return TCL_ERROR; } return Tcl_EvalEx(interp, initScript, -1, TCL_EVAL_GLOBAL); } /* *-------------------------------------------------------------- * * Treectrl_SafeInit -- * * This procedure initializes the TreeCtrl package and related * commands. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. New Tcl commands are created. * *-------------------------------------------------------------- */ DLLEXPORT int Treectrl_SafeInit( Tcl_Interp *interp /* Interpreter the package is loading into. */ ) { return Treectrl_Init(interp); } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeUtils.c0000644000175000017500000045432111044115431025121 0ustar domibeldomibel/* * tkTreeUtils.c -- * * This module implements misc routines for treectrl widgets. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: tkTreeUtils.c,v 1.3 2008-07-30 16:47:21 barre Exp $ */ #include "tkTreeCtrl.h" #include "tclInt.h" /* TCL_ALIGN */ #ifdef WIN32 #include "tkWinInt.h" #endif /* OffsetRgn() on Mac */ #if defined(MAC_OSX_TK) #include #include "tkMacOSXInt.h" static PixPatHandle gPenPat = NULL; #endif /* * Forward declarations for procedures defined later in this file: */ static int PadAmountOptionSet _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags)); static Tcl_Obj *PadAmountOptionGet _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset)); static void PadAmountOptionRestore _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr)); static void PadAmountOptionFree _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *internalPtr)); /* * The following Tk_ObjCustomOption structure can be used as clientData entry * of a Tk_OptionSpec record with a TK_OPTION_CUSTOM type in the form * "(ClientData) &PadAmountOption"; the option will then parse list with * one or two screen distances. */ Tk_ObjCustomOption PadAmountOption = { "pad amount", PadAmountOptionSet, PadAmountOptionGet, PadAmountOptionRestore, PadAmountOptionFree }; /* *---------------------------------------------------------------------- * * FormatResult -- * * Set the interpreter's result to a formatted string. * * Results: * None. * * Side effects: * Interpreter's result is modified. * *---------------------------------------------------------------------- */ void FormatResult( Tcl_Interp *interp, /* Current interpreter. */ char *fmt, ... /* Format string and varargs. */ ) { va_list ap; char buf[256]; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); Tcl_SetResult(interp, buf, TCL_VOLATILE); } /* *---------------------------------------------------------------------- * * DStringAppendf -- * * Format a string and append it to a Tcl_DString. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void DStringAppendf( Tcl_DString *dString, /* Initialized dynamic string. */ char *fmt, ... /* Format string and varargs. */ ) { va_list ap; char buf[256]; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); Tcl_DStringAppend(dString, buf, -1); } /* *---------------------------------------------------------------------- * * Ellipsis -- * * Determine the number of bytes from the string that will fit * in the given horizontal span. If the entire string does not * fit then determine the largest number of bytes of a substring * with an ellipsis "..." appended that will fit. * * Results: * When the return value is positive the caller should add the * ellipsis to the string (unless the entire string fits). * When the return value is negative the caller should not add * the ellipsis because only a few characters fit. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Ellipsis( Tk_Font tkfont, /* The font used to display the string. */ char *string, /* UTF-8 string, need not be NULL-terminated. */ int numBytes, /* Number of bytes to consider. */ int *maxPixels, /* In: maximum line length allowed. * Out: length of string that fits (with * ellipsis added if needed). */ char *ellipsis, /* NULL-terminated "..." */ int force /* TRUE if ellipsis should always be added * even if the whole string fits in * maxPixels. */ ) { char staticStr[256], *tmpStr = staticStr; int pixels, pixelsTest, bytesThatFit, bytesTest; int ellipsisNumBytes = (int)strlen(ellipsis); bytesThatFit = Tk_MeasureChars(tkfont, string, numBytes, *maxPixels, 0, &pixels); /* The whole string fits. No ellipsis needed (unless forced) */ if ((bytesThatFit == numBytes) && !force) { (*maxPixels) = pixels; return numBytes; } if (bytesThatFit <= 1) { (*maxPixels) = pixels; return -bytesThatFit; } /* Strip off one character at a time, adding ellipsis, until it fits */ if (force) bytesTest = bytesThatFit; else bytesTest = (int)(Tcl_UtfPrev(string + bytesThatFit, string) - string); if (bytesTest + ellipsisNumBytes > sizeof(staticStr)) tmpStr = ckalloc(bytesTest + ellipsisNumBytes); memcpy(tmpStr, string, bytesTest); while (bytesTest > 0) { memcpy(tmpStr + bytesTest, ellipsis, ellipsisNumBytes); numBytes = Tk_MeasureChars(tkfont, tmpStr, bytesTest + ellipsisNumBytes, *maxPixels, 0, &pixelsTest); if (numBytes == bytesTest + ellipsisNumBytes) { (*maxPixels) = pixelsTest; if (tmpStr != staticStr) ckfree(tmpStr); return bytesTest; } bytesTest = (int)(Tcl_UtfPrev(string + bytesTest, string) - string); } /* No single char + ellipsis fits. Return number of chars that fit */ /* Negative tells caller to not add ellipsis */ (*maxPixels) = pixels; if (tmpStr != staticStr) ckfree(tmpStr); return -bytesThatFit; } /* *---------------------------------------------------------------------- * * HDotLine -- * * Draws a horizontal 1-pixel-tall dotted line. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void HDotLine( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ GC gc, /* Graphics context. */ int x1, int y1, int x2 /* Left, top and right coordinates. */ ) { #ifdef WIN32 TkWinDCState state; HDC dc; HPEN pen, oldPen; int nw; int wx = x1 + tree->drawableXOrigin; int wy = y1 + tree->drawableYOrigin; dc = TkWinGetDrawableDC(tree->display, drawable, &state); SetROP2(dc, R2_COPYPEN); pen = CreatePen(PS_SOLID, 1, gc->foreground); oldPen = SelectObject(dc, pen); nw = !(wx & 1) == !(wy & 1); for (x1 += !nw; x1 < x2; x1 += 2) { MoveToEx(dc, x1, y1, NULL); LineTo(dc, x1 + 1, y1); } SelectObject(dc, oldPen); DeleteObject(pen); TkWinReleaseDrawableDC(drawable, dc, &state); #else int nw; int wx = x1 + tree->drawableXOrigin; int wy = y1 + tree->drawableYOrigin; nw = !(wx & 1) == !(wy & 1); for (x1 += !nw; x1 < x2; x1 += 2) { XDrawPoint(tree->display, drawable, gc, x1, y1); } #endif } /* *---------------------------------------------------------------------- * * VDotLine -- * * Draws a vertical 1-pixel-wide dotted line. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void VDotLine( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ GC gc, /* Graphics context. */ int x1, int y1, int y2) /* Left, top, and bottom coordinates. */ { #ifdef WIN32 TkWinDCState state; HDC dc; HPEN pen, oldPen; int nw; int wx = x1 + tree->drawableXOrigin; int wy = y1 + tree->drawableYOrigin; dc = TkWinGetDrawableDC(tree->display, drawable, &state); SetROP2(dc, R2_COPYPEN); pen = CreatePen(PS_SOLID, 1, gc->foreground); oldPen = SelectObject(dc, pen); nw = !(wx & 1) == !(wy & 1); for (y1 += !nw; y1 < y2; y1 += 2) { MoveToEx(dc, x1, y1, NULL); LineTo(dc, x1 + 1, y1); } SelectObject(dc, oldPen); DeleteObject(pen); TkWinReleaseDrawableDC(drawable, dc, &state); #else int nw; int wx = x1 + tree->drawableXOrigin; int wy = y1 + tree->drawableYOrigin; nw = !(wx & 1) == !(wy & 1); for (y1 += !nw; y1 < y2; y1 += 2) { XDrawPoint(tree->display, drawable, gc, x1, y1); } #endif } /* *---------------------------------------------------------------------- * * DrawActiveOutline -- * * Draws 0 or more sides of a rectangle, dot-on dot-off, XOR style. * This is used by rectangle Elements to indicate the "active" * item. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void DrawActiveOutline( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ int x, int y, /* Left and top coordinates. */ int width, int height, /* Size of rectangle. */ int open /* Bitmask of edges not to draw: * 0x01: left * 0x02: top * 0x04: right * 0x08: bottom */ ) { #ifdef WIN32 int wx = x + tree->drawableXOrigin; int wy = y + tree->drawableYOrigin; int w = !(open & 0x01); int n = !(open & 0x02); int e = !(open & 0x04); int s = !(open & 0x08); int nw, ne, sw, se; int i; TkWinDCState state; HDC dc; /* Dots on even pixels only */ nw = !(wx & 1) == !(wy & 1); ne = !((wx + width - 1) & 1) == !(wy & 1); sw = !(wx & 1) == !((wy + height - 1) & 1); se = !((wx + width - 1) & 1) == !((wy + height - 1) & 1); dc = TkWinGetDrawableDC(tree->display, drawable, &state); SetROP2(dc, R2_NOT); if (w) /* left */ { for (i = !nw; i < height; i += 2) { MoveToEx(dc, x, y + i, NULL); LineTo(dc, x + 1, y + i); } } if (n) /* top */ { for (i = nw ? w * 2 : 1; i < width; i += 2) { MoveToEx(dc, x + i, y, NULL); LineTo(dc, x + i + 1, y); } } if (e) /* right */ { for (i = ne ? n * 2 : 1; i < height; i += 2) { MoveToEx(dc, x + width - 1, y + i, NULL); LineTo(dc, x + width, y + i); } } if (s) /* bottom */ { for (i = sw ? w * 2 : 1; i < width - (se && e); i += 2) { MoveToEx(dc, x + i, y + height - 1, NULL); LineTo(dc, x + i + 1, y + height - 1); } } TkWinReleaseDrawableDC(drawable, dc, &state); #else /* WIN32 */ int wx = x + tree->drawableXOrigin; int wy = y + tree->drawableYOrigin; int w = !(open & 0x01); int n = !(open & 0x02); int e = !(open & 0x04); int s = !(open & 0x08); int nw, ne, sw, se; int i; XGCValues gcValues; unsigned long gcMask; GC gc; /* Dots on even pixels only */ nw = !(wx & 1) == !(wy & 1); ne = !((wx + width - 1) & 1) == !(wy & 1); sw = !(wx & 1) == !((wy + height - 1) & 1); se = !((wx + width - 1) & 1) == !((wy + height - 1) & 1); #if defined(MAC_TCL) || defined(MAC_OSX_TK) gcValues.function = GXxor; #else gcValues.function = GXinvert; #endif gcMask = GCFunction; gc = Tk_GetGC(tree->tkwin, gcMask, &gcValues); if (w) /* left */ { for (i = !nw; i < height; i += 2) { XDrawPoint(tree->display, drawable, gc, x, y + i); } } if (n) /* top */ { for (i = nw ? w * 2 : 1; i < width; i += 2) { XDrawPoint(tree->display, drawable, gc, x + i, y); } } if (e) /* right */ { for (i = ne ? n * 2 : 1; i < height; i += 2) { XDrawPoint(tree->display, drawable, gc, x + width - 1, y + i); } } if (s) /* bottom */ { for (i = sw ? w * 2 : 1; i < width - (se && e); i += 2) { XDrawPoint(tree->display, drawable, gc, x + i, y + height - 1); } } Tk_FreeGC(tree->display, gc); #endif } /* * The following structure is used when drawing a number of dotted XOR * rectangles. */ struct DotStatePriv { TreeCtrl *tree; Drawable drawable; #ifdef WIN32 HDC dc; TkWinDCState dcState; HRGN rgn; #elif defined(MAC_OSX_TK) CGrafPtr saveWorld; GDHandle saveDevice; #else GC gc; TkRegion rgn; #endif }; /* *---------------------------------------------------------------------- * * DotRect_Setup -- * * Prepare a drawable for drawing a series of dotted XOR rectangles. * * Results: * State info is returned to be used by the other DotRect_xxx() * procedures. * * Side effects: * On Win32 and OSX the device context/graphics port is altered * in preparation for drawing. On X11 a new graphics context is * created. * *---------------------------------------------------------------------- */ void DotRect_Setup( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ DotState *p /* Where to save state info. */ ) { struct DotStatePriv *dotState = (struct DotStatePriv *) p; #ifdef WIN32 #elif defined(MAC_OSX_TK) GWorldPtr destPort; #else XGCValues gcValues; unsigned long mask; XRectangle xrect; #endif if (sizeof(*dotState) > sizeof(*p)) panic("DotRect_Setup: DotState hack is too small"); dotState->tree = tree; dotState->drawable = drawable; #ifdef WIN32 dotState->dc = TkWinGetDrawableDC(tree->display, drawable, &dotState->dcState); /* XOR drawing */ SetROP2(dotState->dc, R2_NOT); /* Keep drawing inside the contentbox */ dotState->rgn = CreateRectRgn( Tree_ContentLeft(tree), Tree_ContentTop(tree), Tree_ContentRight(tree), Tree_ContentBottom(tree)); SelectClipRgn(dotState->dc, dotState->rgn); #elif defined(MAC_OSX_TK) tree->display->request++; destPort = TkMacOSXGetDrawablePort(drawable); GetGWorld(&dotState->saveWorld, &dotState->saveDevice); SetGWorld(destPort, NULL); TkMacOSXSetUpClippingRgn(drawable); PenNormal(); PenMode(patXor); ShowPen(); /* FIXME: clipping region */ #else gcValues.line_style = LineOnOffDash; gcValues.line_width = 1; gcValues.dash_offset = 0; gcValues.dashes = 1; #if defined(MAC_TCL) gcValues.function = GXxor; #else gcValues.function = GXinvert; #endif mask = GCLineWidth | GCLineStyle | GCDashList | GCDashOffset | GCFunction; dotState->gc = Tk_GetGC(tree->tkwin, mask, &gcValues); /* Keep drawing inside the contentbox */ dotState->rgn = TkCreateRegion(); xrect.x = Tree_ContentLeft(tree); xrect.y = Tree_ContentTop(tree); xrect.width = Tree_ContentRight(tree) - xrect.x; xrect.height = Tree_ContentBottom(tree) - xrect.y; TkUnionRectWithRegion(&xrect, dotState->rgn, dotState->rgn); TkSetRegion(tree->display, dotState->gc, dotState->rgn); #endif } /* *---------------------------------------------------------------------- * * DotRect_Draw -- * * Draw a dotted XOR rectangle. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void DotRect_Draw( DotState *p, /* Info returned by DotRect_Setup(). */ int x, int y, /* Left and top coordinates. */ int width, int height /* Size of rectangle. */ ) { struct DotStatePriv *dotState = (struct DotStatePriv *) p; #ifdef WIN32 #if 1 RECT rect; rect.left = x; rect.right = x + width; rect.top = y; rect.bottom = y + height; DrawFocusRect(dotState->dc, &rect); #else HDC dc = dotState->dc; int i; int wx = x + dotState->tree->drawableXOrigin; int wy = y + dotState->tree->drawableYOrigin; int nw, ne, sw, se; /* Dots on even pixels only */ nw = !(wx & 1) == !(wy & 1); ne = !((wx + width - 1) & 1) == !(wy & 1); sw = !(wx & 1) == !((wy + height - 1) & 1); se = !((wx + width - 1) & 1) == !((wy + height - 1) & 1); for (i = !nw; i < height; i += 2) { MoveToEx(dc, x, y + i, NULL); LineTo(dc, x + 1, y + i); } for (i = nw ? 2 : 1; i < width; i += 2) { MoveToEx(dc, x + i, y, NULL); LineTo(dc, x + i + 1, y); } for (i = ne ? 2 : 1; i < height; i += 2) { MoveToEx(dc, x + width - 1, y + i, NULL); LineTo(dc, x + width, y + i); } for (i = sw ? 2 : 1; i < width - se; i += 2) { MoveToEx(dc, x + i, y + height - 1, NULL); LineTo(dc, x + i + 1, y + height - 1); } #endif #elif defined(MAC_OSX_TK) MacDrawable *macWin = (MacDrawable *) dotState->drawable; int i; int wx = x + dotState->tree->drawableXOrigin; int wy = y + dotState->tree->drawableYOrigin; int nw, ne, sw, se; /* Dots on even pixels only */ nw = !(wx & 1) == !(wy & 1); ne = !((wx + width - 1) & 1) == !(wy & 1); sw = !(wx & 1) == !((wy + height - 1) & 1); se = !((wx + width - 1) & 1) == !((wy + height - 1) & 1); x += macWin->xOff; y += macWin->yOff; for (i = !nw; i < height; i += 2) { MoveTo(x, y + i); LineTo(x, y + i); } for (i = nw ? 2 : 1; i < width; i += 2) { MoveTo(x + i, y); LineTo(x + i, y); } for (i = ne ? 2 : 1; i < height; i += 2) { MoveTo(x + width, y + i); LineTo(x + width, y + i); } for (i = sw ? 2 : 1; i < width - se; i += 2) { MoveTo(x + i, y + height - 1); LineTo(x + i, y + height - 1); } #else /* MAC_OSX_TK */ XDrawRectangle(dotState->tree->display, dotState->drawable, dotState->gc, x, y, width - 1, height - 1); #endif } /* *---------------------------------------------------------------------- * * DotRect_Restore -- * * Restore the drawing environment. * * Results: * None. * * Side effects: * On Win32 and OSX the device context/graphics port is restored. * On X11 a new graphics context is freed. * *---------------------------------------------------------------------- */ void DotRect_Restore( DotState *p /* Info returned by DotRect_Setup(). */ ) { struct DotStatePriv *dotState = (struct DotStatePriv *) p; #ifdef WIN32 SelectClipRgn(dotState->dc, NULL); DeleteObject(dotState->rgn); TkWinReleaseDrawableDC(dotState->drawable, dotState->dc, &dotState->dcState); #elif defined(MAC_OSX_TK) HidePen(); /* FIXME: clipping region */ SetGWorld(dotState->saveWorld, dotState->saveDevice); #else XSetClipMask(dotState->tree->display, dotState->gc, None); TkDestroyRegion(dotState->rgn); Tk_FreeGC(dotState->tree->display, dotState->gc); #endif } #ifdef MAC_OSX_TK /* *---------------------------------------------------------------------- * * DrawXORLine -- * * Draw a 1-pixel thick XOR line (not dotted). This is used * to draw the vertical column proxy when resizing columns. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void DrawXORLine( Display *display, /* Display. */ Drawable drawable, /* Where to draw. */ int x1, int y1, /* Left, top. */ int x2, int y2 /* Bottom, right. */ ) { MacDrawable *macWin = (MacDrawable *) drawable; CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; destPort = TkMacOSXGetDrawablePort(drawable); display->request++; GetGWorld(&saveWorld, &saveDevice); SetGWorld(destPort, NULL); TkMacOSXSetUpClippingRgn(drawable); #if 1 PenNormal(); #else TkMacOSXSetUpGraphicsPort(gc, destPort); #endif PenMode(patXor); ShowPen(); MoveTo(macWin->xOff + x1, macWin->yOff + y1); LineTo(macWin->xOff + x2, macWin->yOff + y2); HidePen(); SetGWorld(saveWorld, saveDevice); } #endif /* MAC_OSX_TK */ /* *---------------------------------------------------------------------- * * Tk_FillRegion -- * * Paint a region with the foreground color of a graphics context. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tk_FillRegion( Display *display, /* Display. */ Drawable drawable, /* Where to draw. */ GC gc, /* Foreground color. */ TkRegion rgn /* Region to paint. */ ) { #ifdef WIN32 HDC dc; TkWinDCState dcState; HBRUSH brush; dc = TkWinGetDrawableDC(display, drawable, &dcState); SetROP2(dc, R2_COPYPEN); brush = CreateSolidBrush(gc->foreground); FillRgn(dc, (HRGN) rgn, brush); DeleteObject(brush); TkWinReleaseDrawableDC(drawable, dc, &dcState); #elif defined(MAC_OSX_TK) MacDrawable *macWin = (MacDrawable *) drawable; CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; RGBColor macColor; destPort = TkMacOSXGetDrawablePort(drawable); if (gPenPat == NULL) gPenPat = NewPixPat(); if (TkSetMacColor(gc->foreground, &macColor) == true) MakeRGBPat(gPenPat, &macColor); display->request++; GetGWorld(&saveWorld, &saveDevice); SetGWorld(destPort, NULL); TkMacOSXSetUpClippingRgn(drawable); TkMacOSXSetUpGraphicsPort(gc, destPort); OffsetRgn((RgnHandle) rgn, macWin->xOff, macWin->yOff); ShowPen(); /* seemed to work without this */ FillCRgn((RgnHandle) rgn, gPenPat); HidePen(); /* seemed to work without this */ OffsetRgn((RgnHandle) rgn, -macWin->xOff, -macWin->yOff); SetGWorld(saveWorld, saveDevice); #else XRectangle box; TkClipBox(rgn, &box); TkSetRegion(display, gc, rgn); XFillRectangle(display, drawable, gc, box.x, box.y, box.width, box.height); XSetClipMask(display, gc, None); #endif } /* *---------------------------------------------------------------------- * * Tk_OffsetRegion -- * * Offset a region. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tk_OffsetRegion( TkRegion region, /* Region to modify. */ int xOffset, int yOffset /* Horizontal and vertical offsets. */ ) { #ifdef WIN32 OffsetRgn((HRGN) region, xOffset, yOffset); #elif defined(MAC_TCL) || defined(MAC_OSX_TK) OffsetRgn((RgnHandle) region, (short) xOffset, (short) yOffset); #else XOffsetRegion((Region) region, xOffset, yOffset); #endif } /* *---------------------------------------------------------------------- * * Tree_ScrollWindow -- * * Wrapper around TkScrollWindow() to fix an apparent bug with the * Mac/OSX versions. * * Results: * None. * * Side effects: * Stuff is scrolled in a drawable. * *---------------------------------------------------------------------- */ int Tree_ScrollWindow( TreeCtrl *tree, /* Widget info. */ GC gc, /* Arg to TkScrollWindow(). */ int x, int y, /* Arg to TkScrollWindow(). */ int width, int height, /* Arg to TkScrollWindow(). */ int dx, int dy, /* Arg to TkScrollWindow(). */ TkRegion damageRgn /* Arg to TkScrollWindow(). */ ) { #ifdef WIN32xxx /* It would be best to call ScrollWindowEx with SW_SCROLLCHILDREN so * that windows in window elements scroll smoothly with a minimum of * redrawing. */ HWND hwnd = TkWinGetHWND(Tk_WindowId(tree->tkwin)); HWND hwndChild; RECT scrollRect, childRect; struct { int x; int y; TkWindow *winPtr; } winInfo[128], *winInfoPtr; TkWindow *winPtr = (TkWindow *) tree->tkwin; int winCount = 0; int result; winInfoPtr = winInfo; for (winPtr = winPtr->childList; winPtr != NULL; winPtr = winPtr->nextPtr) { if (winPtr->window != None) { hwndChild = TkWinGetHWND(winPtr->window); GetWindowRect(hwndChild, &childRect); winInfoPtr->x = childRect.left; winInfoPtr->y = childRect.top; winInfoPtr->winPtr = winPtr; winInfoPtr++; winCount++; } } scrollRect.left = x; scrollRect.top = y; scrollRect.right = x + width; scrollRect.bottom = y + height; result = (ScrollWindowEx(hwnd, dx, dy, &scrollRect, NULL, (HRGN) damageRgn, NULL, SW_SCROLLCHILDREN) == NULLREGION) ? 0 : 1; winInfoPtr = winInfo; while (winCount--) { winPtr = winInfoPtr->winPtr; hwndChild = TkWinGetHWND(winPtr->window); GetWindowRect(hwndChild, &childRect); if (childRect.left != winInfoPtr->x || childRect.top != winInfoPtr->y) { dbwin("moved window %s %d,%d\n", winPtr->pathName, childRect.left - winInfoPtr->x, childRect.top - winInfoPtr->y); winPtr->changes.x += childRect.left - winInfoPtr->x; winPtr->changes.y += childRect.top - winInfoPtr->y; /* TkDoConfigureNotify(winPtr); */ } winInfoPtr++; } #else /* WIN32 */ int result = TkScrollWindow(tree->tkwin, gc, x, y, width, height, dx, dy, damageRgn); #endif /* WIN32 */ #if defined(MAC_TCL) || defined(MAC_OSX_TK) { MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tree->tkwin); /* BUG IN TK? */ OffsetRgn((RgnHandle) damageRgn, -macWin->xOff, -macWin->yOff); } #endif return result; } /* *---------------------------------------------------------------------- * * UnsetClipMask -- * * Wrapper around XSetClipMask(). On Win32 Tk_DrawChars() does * not clear the clipping region. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void UnsetClipMask( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ GC gc /* Graphics context to modify. */ ) { XSetClipMask(tree->display, gc, None); #ifdef WIN32 /* Tk_DrawChars does not clear the clip region */ if (drawable == Tk_WindowId(tree->tkwin)) { HDC dc; TkWinDCState dcState; dc = TkWinGetDrawableDC(tree->display, drawable, &dcState); SelectClipRgn(dc, NULL); TkWinReleaseDrawableDC(drawable, dc, &dcState); } #endif } /* *---------------------------------------------------------------------- * * Tree_DrawBitmapWithGC -- * * Draw part of a bitmap. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_DrawBitmapWithGC( TreeCtrl *tree, /* Widget info. */ Pixmap bitmap, /* Bitmap to draw. */ Drawable drawable, /* Where to draw. */ GC gc, /* Graphics context. */ int src_x, int src_y, /* Left and top of part of bitmap to copy. */ int width, int height, /* Width and height of part of bitmap to * copy. */ int dest_x, int dest_y /* Left and top coordinates to copy part of * the bitmap to. */ ) { #ifdef WIN32 TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; #endif XSetClipOrigin(tree->display, gc, dest_x, dest_y); #ifdef WIN32 /* * It seems as though the device context is not set up properly * when drawing a transparent bitmap into a window. Normally Tk draws * into an offscreen pixmap which gets a temporary device context. * This fixes a bug with -doublebuffer none in the demo "Bitmaps". */ if (drawable == Tk_WindowId(tree->tkwin)) { if ((clipPtr != NULL) && (clipPtr->type == TKP_CLIP_PIXMAP) && (clipPtr->value.pixmap == bitmap)) { HDC dc; TkWinDCState dcState; dc = TkWinGetDrawableDC(tree->display, drawable, &dcState); SetTextColor(dc, RGB(0,0,0)); SetBkColor(dc, RGB(255,255,255)); TkWinReleaseDrawableDC(drawable, dc, &dcState); } } #endif XCopyPlane(tree->display, bitmap, drawable, gc, src_x, src_y, (unsigned int) width, (unsigned int) height, dest_x, dest_y, 1); XSetClipOrigin(tree->display, gc, 0, 0); } /* *---------------------------------------------------------------------- * * Tree_DrawBitmap -- * * Draw part of a bitmap. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_DrawBitmap( TreeCtrl *tree, /* Widget info. */ Pixmap bitmap, /* Bitmap to draw. */ Drawable drawable, /* Where to draw. */ XColor *fg, XColor *bg, /* Foreground and background colors. * May be NULL. */ int src_x, int src_y, /* Left and top of part of bitmap to copy. */ int width, int height, /* Width and height of part of bitmap to * copy. */ int dest_x, int dest_y /* Left and top coordinates to copy part of * the bitmap to. */ ) { XGCValues gcValues; GC gc; unsigned long mask = 0; if (fg != NULL) { gcValues.foreground = fg->pixel; mask |= GCForeground; } if (bg != NULL) { gcValues.background = bg->pixel; mask |= GCBackground; } else { gcValues.clip_mask = bitmap; mask |= GCClipMask; } gcValues.graphics_exposures = False; mask |= GCGraphicsExposures; gc = Tk_GetGC(tree->tkwin, mask, &gcValues); Tree_DrawBitmapWithGC(tree, bitmap, drawable, gc, src_x, src_y, width, height, dest_x, dest_y); Tk_FreeGC(tree->display, gc); } /* * TIP #116 altered Tk_PhotoPutBlock API to add interp arg. * We need to remove that for compiling with 8.4. */ #if (TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION < 5) #define TK_PHOTOPUTBLOCK(interp, hdl, blk, x, y, w, h, cr) \ Tk_PhotoPutBlock(hdl, blk, x, y, w, h, cr) #define TK_PHOTOPUTZOOMEDBLOCK(interp, hdl, blk, x, y, w, h, \ zx, zy, sx, sy, cr) \ Tk_PhotoPutZoomedBlock(hdl, blk, x, y, w, h, \ zx, zy, sx, sy, cr) #else #define TK_PHOTOPUTBLOCK Tk_PhotoPutBlock #define TK_PHOTOPUTZOOMEDBLOCK Tk_PhotoPutZoomedBlock #endif /* *---------------------------------------------------------------------- * * XImage2Photo -- * * Copy pixels from an XImage to a Tk photo image. * * Results: * None. * * Side effects: * The given photo image is blanked and all the pixels from the * XImage are put into the photo image. * *---------------------------------------------------------------------- */ #if defined(WIN32) || defined(MAC_TCL) || defined(MAC_OSX_TK) void XImage2Photo( Tcl_Interp *interp, /* Current interpreter. */ Tk_PhotoHandle photoH, /* Existing photo image. */ XImage *ximage, /* XImage to copy pixels from. */ int alpha /* Desired transparency of photo image.*/ ) { Tk_PhotoImageBlock photoBlock; unsigned char *pixelPtr; int x, y, w = ximage->width, h = ximage->height; #if defined(MAC_TCL) || defined(MAC_OSX_TK) unsigned long red_shift, green_shift, blue_shift; #endif Tk_PhotoBlank(photoH); /* See TkPoscriptImage */ #if defined(MAC_TCL) || defined(MAC_OSX_TK) red_shift = green_shift = blue_shift = 0; while ((0x0001 & (ximage->red_mask >> red_shift)) == 0) red_shift++; while ((0x0001 & (ximage->green_mask >> green_shift)) == 0) green_shift++; while ((0x0001 & (ximage->blue_mask >> blue_shift)) == 0) blue_shift++; #endif pixelPtr = (unsigned char *) Tcl_Alloc(ximage->width * ximage->height * 4); photoBlock.pixelPtr = pixelPtr; photoBlock.width = ximage->width; photoBlock.height = ximage->height; photoBlock.pitch = ximage->width * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (y = 0; y < ximage->height; y++) { for (x = 0; x < ximage->width; x++) { int r, g, b; unsigned long pixel; /* FIXME: I think this blows up on classic Mac??? */ pixel = XGetPixel(ximage, x, y); #ifdef WIN32 r = GetRValue(pixel); g = GetGValue(pixel); b = GetBValue(pixel); #endif #if defined(MAC_TCL) || defined(MAC_OSX_TK) r = (pixel & ximage->red_mask) >> red_shift; g = (pixel & ximage->green_mask) >> green_shift; b = (pixel & ximage->blue_mask) >> blue_shift; #endif pixelPtr[y * photoBlock.pitch + x * 4 + 0] = r; pixelPtr[y * photoBlock.pitch + x * 4 + 1] = g; pixelPtr[y * photoBlock.pitch + x * 4 + 2] = b; pixelPtr[y * photoBlock.pitch + x * 4 + 3] = alpha; } } TK_PHOTOPUTBLOCK(interp, photoH, &photoBlock, 0, 0, w, h, TK_PHOTO_COMPOSITE_SET); Tcl_Free((char *) pixelPtr); } #else /* not X11 */ void XImage2Photo( Tcl_Interp *interp, /* Current interpreter. */ Tk_PhotoHandle photoH, /* Existing photo image. */ XImage *ximage, /* XImage to copy pixels from. */ int alpha /* Desired transparency of photo image.*/ ) { Tk_Window tkwin = Tk_MainWindow(interp); Display *display = Tk_Display(tkwin); Visual *visual = Tk_Visual(tkwin); Tk_PhotoImageBlock photoBlock; unsigned char *pixelPtr; int x, y, w = ximage->width, h = ximage->height; int i, ncolors; XColor *xcolors; unsigned long red_shift, green_shift, blue_shift; int separated = 0; Tk_PhotoBlank(photoH); /* See TkPoscriptImage */ ncolors = visual->map_entries; xcolors = (XColor *) ckalloc(sizeof(XColor) * ncolors); if ((visual->class == DirectColor) || (visual->class == TrueColor)) { separated = 1; red_shift = green_shift = blue_shift = 0; /* ximage->red_mask etc are zero */ while ((0x0001 & (visual->red_mask >> red_shift)) == 0) red_shift++; while ((0x0001 & (visual->green_mask >> green_shift)) == 0) green_shift++; while ((0x0001 & (visual->blue_mask >> blue_shift)) == 0) blue_shift++; for (i = 0; i < ncolors; i++) { xcolors[i].pixel = ((i << red_shift) & visual->red_mask) | ((i << green_shift) & visual->green_mask) | ((i << blue_shift) & visual->blue_mask); } } else { red_shift = green_shift = blue_shift = 0; for (i = 0; i < ncolors; i++) xcolors[i].pixel = i; } XQueryColors(display, Tk_Colormap(tkwin), xcolors, ncolors); pixelPtr = (unsigned char *) Tcl_Alloc(ximage->width * ximage->height * 4); photoBlock.pixelPtr = pixelPtr; photoBlock.width = ximage->width; photoBlock.height = ximage->height; photoBlock.pitch = ximage->width * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (y = 0; y < ximage->height; y++) { for (x = 0; x < ximage->width; x++) { int r, g, b; unsigned long pixel; pixel = XGetPixel(ximage, x, y); if (separated) { r = (pixel & visual->red_mask) >> red_shift; g = (pixel & visual->green_mask) >> green_shift; b = (pixel & visual->blue_mask) >> blue_shift; r = ((double) xcolors[r].red / USHRT_MAX) * 255; g = ((double) xcolors[g].green / USHRT_MAX) * 255; b = ((double) xcolors[b].blue / USHRT_MAX) * 255; } else { r = ((double) xcolors[pixel].red / USHRT_MAX) * 255; g = ((double) xcolors[pixel].green / USHRT_MAX) * 255; b = ((double) xcolors[pixel].blue / USHRT_MAX) * 255; } pixelPtr[y * photoBlock.pitch + x * 4 + 0] = r; pixelPtr[y * photoBlock.pitch + x * 4 + 1] = g; pixelPtr[y * photoBlock.pitch + x * 4 + 2] = b; pixelPtr[y * photoBlock.pitch + x * 4 + 3] = alpha; } } TK_PHOTOPUTBLOCK(interp, photoH, &photoBlock, 0, 0, w, h, TK_PHOTO_COMPOSITE_SET); Tcl_Free((char *) pixelPtr); ckfree((char *) xcolors); } #endif /* X11 */ /* * Replacement for Tk_TextLayout stuff. Allows the caller to break lines * on character boundaries (as well as word boundaries). Allows the caller * to specify the maximum number of lines to display. Will add ellipsis "..." * to the end of text that is too long to fit (when max lines specified). */ typedef struct LayoutChunk { CONST char *start; /* Pointer to simple string to be displayed. * * This is a pointer into the TkTextLayout's * * string. */ int numBytes; /* The number of bytes in this chunk. */ int numChars; /* The number of characters in this chunk. */ int numDisplayChars; /* The number of characters to display when * * this chunk is displayed. Can be less than * * numChars if extra space characters were * * absorbed by the end of the chunk. This * * will be < 0 if this is a chunk that is * * holding a tab or newline. */ int x, y; /* The origin of the first character in this * * chunk with respect to the upper-left hand * * corner of the TextLayout. */ int totalWidth; /* Width in pixels of this chunk. Used * * when hit testing the invisible spaces at * * the end of a chunk. */ int displayWidth; /* Width in pixels of the displayable * * characters in this chunk. Can be less than * * width if extra space characters were * * absorbed by the end of the chunk. */ int ellipsis; /* TRUE if adding "..." */ } LayoutChunk; typedef struct LayoutInfo { Tk_Font tkfont; /* The font used when laying out the text. */ CONST char *string; /* The string that was layed out. */ int numLines; /* Number of lines */ int width; /* The maximum width of all lines in the * * text layout. */ int height; int numChunks; /* Number of chunks actually used in * * following array. */ int totalWidth; #define TEXTLAYOUT_ALLOCHAX #ifdef TEXTLAYOUT_ALLOCHAX int maxChunks; struct LayoutInfo *nextFree; #endif LayoutChunk chunks[1]; /* Array of chunks. The actual size will * * be maxChunks. THIS FIELD MUST BE THE LAST * * IN THE STRUCTURE. */ } LayoutInfo; #ifdef TEXTLAYOUT_ALLOCHAX TCL_DECLARE_MUTEX(textLayoutMutex) /* FIXME: memory leak, list is never freed. */ static LayoutInfo *freeLayoutInfo = NULL; #endif #ifdef TEXTLAYOUT_ALLOCHAX static LayoutChunk *NewChunk(LayoutInfo **layoutPtrPtr, #else static LayoutChunk *NewChunk(LayoutInfo **layoutPtrPtr, int *maxPtr, #endif CONST char *start, int numBytes, int curX, int newX, int y) { LayoutInfo *layoutPtr; LayoutChunk *chunkPtr; #ifdef TEXTLAYOUT_ALLOCHAX int numChars; #else int maxChunks, numChars; #endif size_t s; layoutPtr = *layoutPtrPtr; #ifdef TEXTLAYOUT_ALLOCHAX if (layoutPtr->numChunks == layoutPtr->maxChunks) { layoutPtr->maxChunks *= 2; s = sizeof(LayoutInfo) + ((layoutPtr->maxChunks - 1) * sizeof(LayoutChunk)); layoutPtr = (LayoutInfo *) ckrealloc((char *) layoutPtr, (unsigned int)s); *layoutPtrPtr = layoutPtr; } #else maxChunks = *maxPtr; if (layoutPtr->numChunks == maxChunks) { maxChunks *= 2; s = sizeof(LayoutInfo) + ((maxChunks - 1) * sizeof(LayoutChunk)); layoutPtr = (LayoutInfo *) ckrealloc((char *) layoutPtr, s); *layoutPtrPtr = layoutPtr; *maxPtr = maxChunks; } #endif numChars = Tcl_NumUtfChars(start, numBytes); chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks]; chunkPtr->start = start; chunkPtr->numBytes = numBytes; chunkPtr->numChars = numChars; chunkPtr->numDisplayChars = numChars; chunkPtr->x = curX; chunkPtr->y = y; chunkPtr->totalWidth = newX - curX; chunkPtr->displayWidth = newX - curX; chunkPtr->ellipsis = FALSE; layoutPtr->numChunks++; return chunkPtr; } TextLayout TextLayout_Compute( Tk_Font tkfont, /* Font that will be used to display text. */ CONST char *string, /* String whose dimensions are to be ** computed. */ int numChars, /* Number of characters to consider from ** string, or < 0 for strlen(). */ int wrapLength, /* Longest permissible line length, in ** pixels. <= 0 means no automatic wrapping: ** just let lines get as long as needed. */ Tk_Justify justify, /* How to justify lines. */ int maxLines, int flags /* Flag bits OR-ed together. ** TK_IGNORE_TABS means that tab characters ** should not be expanded. TK_IGNORE_NEWLINES ** means that newline characters should not ** cause a line break. */ ) { CONST char *start, *end, *special; int n, y, bytesThisChunk, maxChunks; int baseline, height, curX, newX, maxWidth; LayoutInfo *layoutPtr; LayoutChunk *chunkPtr; Tk_FontMetrics fm; Tcl_DString lineBuffer; int *lineLengths; int curLine; int tabWidth = 20; /* FIXME */ Tcl_DStringInit(&lineBuffer); Tk_GetFontMetrics(tkfont, &fm); height = fm.ascent + fm.descent; if (numChars < 0) numChars = Tcl_NumUtfChars(string, -1); if (wrapLength == 0) wrapLength = -1; #ifdef TEXTLAYOUT_ALLOCHAX Tcl_MutexLock(&textLayoutMutex); if (freeLayoutInfo != NULL) { layoutPtr = freeLayoutInfo; freeLayoutInfo = layoutPtr->nextFree; } else { maxChunks = 1; layoutPtr = (LayoutInfo *) ckalloc(sizeof(LayoutInfo) + (maxChunks - 1) * sizeof(LayoutChunk)); layoutPtr->maxChunks = maxChunks; } Tcl_MutexUnlock(&textLayoutMutex); #else maxChunks = 1; layoutPtr = (LayoutInfo *) ckalloc(sizeof(LayoutInfo) + (maxChunks - 1) * sizeof(LayoutChunk)); #endif layoutPtr->tkfont = tkfont; layoutPtr->string = string; layoutPtr->numChunks = 0; layoutPtr->numLines = 0; baseline = fm.ascent; maxWidth = 0; curX = 0; end = Tcl_UtfAtIndex(string, numChars); special = string; flags &= TK_WHOLE_WORDS | TK_IGNORE_TABS | TK_IGNORE_NEWLINES; flags |= TK_AT_LEAST_ONE; for (start = string; start < end;) { if (start >= special) { for (special = start; special < end; special++) { if (!(flags & TK_IGNORE_NEWLINES)) { if ((*special == '\n') || (*special == '\r')) break; } if (!(flags & TK_IGNORE_TABS)) { if (*special == '\t') break; } } } chunkPtr = NULL; if (start < special) { bytesThisChunk = Tk_MeasureChars(tkfont, start, (int)(special - start), (int)(wrapLength - curX), flags, &newX); newX += curX; flags &= ~TK_AT_LEAST_ONE; if (bytesThisChunk > 0) { #ifdef TEXTLAYOUT_ALLOCHAX chunkPtr = NewChunk(&layoutPtr, start, #else chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, #endif bytesThisChunk, curX, newX, baseline); start += bytesThisChunk; curX = newX; } } if ((start == special) && (special < end)) { chunkPtr = NULL; if (*special == '\t') { newX = curX + tabWidth; newX -= newX % tabWidth; #ifdef TEXTLAYOUT_ALLOCHAX NewChunk(&layoutPtr, start, 1, curX, newX, #else NewChunk(&layoutPtr, &maxChunks, start, 1, curX, newX, #endif baseline)->numDisplayChars = -1; start++; if ((start < end) && ((wrapLength <= 0) || (newX <= wrapLength))) { curX = newX; flags &= ~TK_AT_LEAST_ONE; continue; } } else { #ifdef TEXTLAYOUT_ALLOCHAX NewChunk(&layoutPtr, start, 1, curX, curX, #else NewChunk(&layoutPtr, &maxChunks, start, 1, curX, curX, #endif baseline)->numDisplayChars = -1; start++; goto wrapLine; } } while ((start < end) && isspace(UCHAR(*start))) { if (!(flags & TK_IGNORE_NEWLINES)) { if ((*start == '\n') || (*start == '\r')) break; } if (!(flags & TK_IGNORE_TABS)) { if (*start == '\t') break; } start++; } if (chunkPtr != NULL) { CONST char *end; end = chunkPtr->start + chunkPtr->numBytes; bytesThisChunk = (int)(start - end); if (bytesThisChunk > 0) { bytesThisChunk = Tk_MeasureChars(tkfont, end, bytesThisChunk, -1, 0, &chunkPtr->totalWidth); chunkPtr->numBytes += bytesThisChunk; chunkPtr->numChars += Tcl_NumUtfChars(end, bytesThisChunk); chunkPtr->totalWidth += curX; } } wrapLine: flags |= TK_AT_LEAST_ONE; if (curX > maxWidth) maxWidth = curX; Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX)); curX = 0; baseline += height; layoutPtr->numLines++; if ((maxLines > 0) && (layoutPtr->numLines >= maxLines)) break; } if (start >= end) if ((layoutPtr->numChunks > 0) && !(flags & TK_IGNORE_NEWLINES)) { if (layoutPtr->chunks[layoutPtr->numChunks - 1].start[0] == '\n') { chunkPtr = #ifdef TEXTLAYOUT_ALLOCHAX NewChunk(&layoutPtr, start, 0, curX, curX, #else NewChunk(&layoutPtr, &maxChunks, start, 0, curX, curX, #endif baseline); chunkPtr->numDisplayChars = -1; Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX)); baseline += height; } } #if 1 /* Fiddle with chunks on the last line to add ellipsis if there is some * text remaining */ if ((start < end) && (layoutPtr->numChunks > 0)) { char *ellipsis = "..."; int ellipsisLen = (int)strlen(ellipsis); char staticStr[256], *buf = staticStr; chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks - 1]; if (wrapLength > 0) { y = chunkPtr->y; for (n = layoutPtr->numChunks - 1; n >= 0; n--) { chunkPtr = &layoutPtr->chunks[n]; /* Only consider the last line */ if (chunkPtr->y != y) break; if (chunkPtr->start[0] == '\n') continue; newX = chunkPtr->totalWidth - 1; if (chunkPtr->x + chunkPtr->totalWidth < wrapLength) newX = wrapLength - chunkPtr->x; bytesThisChunk = Ellipsis(tkfont, (char *) chunkPtr->start, chunkPtr->numBytes, &newX, ellipsis, TRUE); if (bytesThisChunk > 0) { chunkPtr->numBytes = bytesThisChunk; chunkPtr->numChars = Tcl_NumUtfChars(chunkPtr->start, bytesThisChunk); chunkPtr->numDisplayChars = chunkPtr->numChars; chunkPtr->ellipsis = TRUE; chunkPtr->displayWidth = newX; chunkPtr->totalWidth = newX; lineLengths = (int *) Tcl_DStringValue(&lineBuffer); lineLengths[layoutPtr->numLines - 1] = chunkPtr->x + newX; if (chunkPtr->x + newX > maxWidth) maxWidth = chunkPtr->x + newX; break; } } } else { if (chunkPtr->start[0] == '\n') { if (layoutPtr->numChunks == 1) goto finish; if (layoutPtr->chunks[layoutPtr->numChunks - 2].y != chunkPtr->y) goto finish; chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks - 2]; } if (chunkPtr->numBytes + ellipsisLen > sizeof(staticStr)) buf = ckalloc(chunkPtr->numBytes + ellipsisLen); memcpy(buf, chunkPtr->start, chunkPtr->numBytes); memcpy(buf + chunkPtr->numBytes, ellipsis, ellipsisLen); Tk_MeasureChars(tkfont, buf, chunkPtr->numBytes + ellipsisLen, -1, 0, &chunkPtr->displayWidth); chunkPtr->totalWidth = chunkPtr->displayWidth; chunkPtr->ellipsis = TRUE; lineLengths = (int *) Tcl_DStringValue(&lineBuffer); lineLengths[layoutPtr->numLines - 1] = chunkPtr->x + chunkPtr->displayWidth; if (chunkPtr->x + chunkPtr->displayWidth > maxWidth) maxWidth = chunkPtr->x + chunkPtr->displayWidth; if (buf != staticStr) ckfree(buf); } } finish: #endif layoutPtr->width = maxWidth; layoutPtr->height = baseline - fm.ascent; layoutPtr->totalWidth = 0; if (layoutPtr->numChunks == 0) { layoutPtr->height = height; layoutPtr->numChunks = 1; layoutPtr->chunks[0].start = string; layoutPtr->chunks[0].numBytes = 0; layoutPtr->chunks[0].numChars = 0; layoutPtr->chunks[0].numDisplayChars = -1; layoutPtr->chunks[0].x = 0; layoutPtr->chunks[0].y = fm.ascent; layoutPtr->chunks[0].totalWidth = 0; layoutPtr->chunks[0].displayWidth = 0; } else { curLine = 0; chunkPtr = layoutPtr->chunks; y = chunkPtr->y; lineLengths = (int *) Tcl_DStringValue(&lineBuffer); for (n = 0; n < layoutPtr->numChunks; n++) { int extra; if (chunkPtr->y != y) { curLine++; y = chunkPtr->y; } extra = maxWidth - lineLengths[curLine]; if (justify == TK_JUSTIFY_CENTER) { chunkPtr->x += extra / 2; } else if (justify == TK_JUSTIFY_RIGHT) { chunkPtr->x += extra; } if (chunkPtr->x + chunkPtr->totalWidth > layoutPtr->totalWidth) layoutPtr->totalWidth = chunkPtr->x + chunkPtr->totalWidth; chunkPtr++; } /* dbwin("totalWidth %d displayWidth %d\n", layoutPtr->totalWidth, maxWidth); */ Tcl_DStringFree(&lineBuffer); } /* We don't want single-line text layouts for text elements, but it happens for column titles */ /* if (layoutPtr->numLines == 1) dbwin("WARNING: single-line TextLayout created\n"); */ return (TextLayout) layoutPtr; } void TextLayout_Free(TextLayout textLayout) { LayoutInfo *layoutPtr = (LayoutInfo *) textLayout; #ifdef TEXTLAYOUT_ALLOCHAX Tcl_MutexLock(&textLayoutMutex); layoutPtr->nextFree = freeLayoutInfo; freeLayoutInfo = layoutPtr; Tcl_MutexUnlock(&textLayoutMutex); #else ckfree((char *) layoutPtr); #endif } void TextLayout_Size(TextLayout textLayout, int *widthPtr, int *heightPtr) { LayoutInfo *layoutPtr = (LayoutInfo *) textLayout; if (widthPtr != NULL) (*widthPtr) = layoutPtr->width; if (heightPtr != NULL) (*heightPtr) = layoutPtr->height; } int TextLayout_TotalWidth(TextLayout textLayout) { LayoutInfo *layoutPtr = (LayoutInfo *) textLayout; return layoutPtr->totalWidth; } void TextLayout_Draw( Display *display, /* Display on which to draw. */ Drawable drawable, /* Window or pixmap in which to draw. */ GC gc, /* Graphics context to use for drawing text. */ TextLayout layout, /* Layout information, from a previous call * * to Tk_ComputeTextLayout(). */ int x, int y, /* Upper-left hand corner of rectangle in * * which to draw (pixels). */ int firstChar, /* The index of the first character to draw * * from the given text item. 0 specfies the * * beginning. */ int lastChar, /* The index just after the last character * * to draw from the given text item. A number * * < 0 means to draw all characters. */ int underline /* Character index to underline, or < 0 for * no underline. */ ) { LayoutInfo *layoutPtr = (LayoutInfo *) layout; int i, numDisplayChars, drawX; CONST char *firstByte; CONST char *lastByte; LayoutChunk *chunkPtr; if (lastChar < 0) lastChar = 100000000; chunkPtr = layoutPtr->chunks; for (i = 0; i < layoutPtr->numChunks; i++) { numDisplayChars = chunkPtr->numDisplayChars; if ((numDisplayChars > 0) && (firstChar < numDisplayChars)) { if (firstChar <= 0) { drawX = 0; firstChar = 0; firstByte = chunkPtr->start; } else { firstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar); Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start, (int)(firstByte - chunkPtr->start), -1, 0, &drawX); } if (lastChar < numDisplayChars) numDisplayChars = lastChar; lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars); #if 1 if (chunkPtr->ellipsis) { char staticStr[256], *buf = staticStr; char *ellipsis = "..."; int ellipsisLen = (int)strlen(ellipsis); if ((lastByte - firstByte) + ellipsisLen > sizeof(staticStr)) buf = ckalloc((int)(lastByte - firstByte) + ellipsisLen); memcpy(buf, firstByte, (lastByte - firstByte)); memcpy(buf + (lastByte - firstByte), ellipsis, ellipsisLen); Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, buf, (int)(lastByte - firstByte) + ellipsisLen, x + chunkPtr->x + drawX, y + chunkPtr->y); if (buf != staticStr) ckfree(buf); } else #endif Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, firstByte, (int)(lastByte - firstByte), x + chunkPtr->x + drawX, y + chunkPtr->y); #if 1 if (underline >= firstChar && underline < numDisplayChars) { CONST char *fstBytePtr = Tcl_UtfAtIndex(chunkPtr->start, underline); CONST char *sndBytePtr = Tcl_UtfNext(fstBytePtr); Tk_UnderlineChars(display, drawable, gc, layoutPtr->tkfont, firstByte, x + chunkPtr->x + drawX, y + chunkPtr->y, (int)(fstBytePtr - chunkPtr->start), (int)(sndBytePtr - chunkPtr->start)); } #endif } firstChar -= chunkPtr->numChars; lastChar -= chunkPtr->numChars; #if 1 underline -= chunkPtr->numChars; #endif if (lastChar <= 0) break; chunkPtr++; } } /* *---------------------------------------------------------------------- * * TreeCtrl_GetPadAmountFromObj -- * * Parse a pad amount configuration option. * A pad amount (typically the value of an option -XXXpadx or * -XXXpady, where XXX may be a possibly empty string) can * be either a single pixel width, or a list of two pixel widths. * If a single pixel width, the amount specified is used for * padding on both sides. If two amounts are specified, then * they specify the left/right or top/bottom padding. * * Results: * Standard Tcl Result. * * Side effects: * Sets internal representation of the object. In case of an error * the result of the interpreter is modified. * *---------------------------------------------------------------------- */ int TreeCtrl_GetPadAmountFromObj(interp, tkwin, padObj, topLeftPtr, bottomRightPtr) Tcl_Interp *interp; /* Interpreter for error reporting, or NULL, * if no error message is wanted. */ Tk_Window tkwin; /* A window. Needed by Tk_GetPixels() */ Tcl_Obj *padObj; /* Object containing a pad amount. */ int *topLeftPtr; /* Pointer to the location, where to store the first component of the padding. */ int *bottomRightPtr; /* Pointer to the location, where to store the second component of the padding. */ { int padc; /* Number of element objects in padv. */ Tcl_Obj **padv; /* Pointer to the element objects of the * parsed pad amount value. */ int topLeft, bottomRight; if (Tcl_ListObjGetElements(interp, padObj, &padc, &padv) != TCL_OK) { return TCL_ERROR; } /* * The value specifies a non empty string. * Check that this string is indeed a valid pad amount. */ if (padc < 1 || padc > 2) { if (interp != NULL) { error: Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad pad amount \"", Tcl_GetString(padObj), "\": must be a list of ", "1 or 2 positive screen distances", (char *) NULL); } return TCL_ERROR; } if ((Tk_GetPixelsFromObj(interp, tkwin, padv[0], &topLeft) != TCL_OK) || (topLeft < 0)) { goto error; } if (padc == 2) { if ((Tk_GetPixelsFromObj(interp, tkwin, padv[1], &bottomRight) != TCL_OK) || (bottomRight < 0)) { goto error; } } else { bottomRight = topLeft; } (*topLeftPtr) = topLeft; (*bottomRightPtr) = bottomRight; return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeCtrl_NewPadAmountObj -- * * Create a Tcl object with an internal representation, that * corresponds to a pad amount, i.e. an integer Tcl_Obj or a * list Tcl_Obj with 2 elements. * * Results: * The created object. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeCtrl_NewPadAmountObj(padAmounts) int *padAmounts; /* Internal form of a pad amount. */ { Tcl_Obj *newObj; /* * If both values are the same, create a list with one value, * otherwise create a two element list with the top/left value * first followed by the bottom/right value. */ if (padAmounts[PAD_TOP_LEFT] == padAmounts[PAD_BOTTOM_RIGHT]) { newObj = Tcl_NewIntObj(padAmounts[PAD_TOP_LEFT]); } else { newObj = Tcl_NewObj(); Tcl_ListObjAppendElement((Tcl_Interp *) NULL, newObj, Tcl_NewIntObj(padAmounts[PAD_TOP_LEFT])); Tcl_ListObjAppendElement((Tcl_Interp *) NULL, newObj, Tcl_NewIntObj(padAmounts[PAD_BOTTOM_RIGHT])); } return newObj; } /* *---------------------------------------------------------------------- * * PadAmountOptionSet -- * PadAmountOptionGet -- * PadAmountOptionRestore -- * PadAmountOptionFree -- * * Handlers for object-based pad amount configuration options. * A pad amount (typically the value of an option -XXXpadx or * -XXXpady, where XXX may be a possibly empty string) can * be either a single pixel width, or a list of two pixel widths. * If a single pixel width, the amount specified is used for * padding on both sides. If two amounts are specified, then * they specify the left/right or top/bottom padding. * * Results: * See user documentation for expected results from these functions. * PadAmountOptionSet Standard Tcl Result. * PadAmountOptionGet Tcl_Obj * containing a valid internal * representation of the pad amount. * PadAmountOptionRestore None. * PadAmountOptionFree None. * * Side effects: * Depends on the function. * PadAmountOptionSet Sets option value to new setting, * allocating a new integer array. * PadAmountOptionGet Creates a new Tcl_Obj. * PadAmountOptionRestore Resets option value to original value. * PadAmountOptionFree Free storage for internal rep. * *---------------------------------------------------------------------- */ static int PadAmountOptionSet(clientData, interp, tkwin, valuePtr, recordPtr, internalOffset, saveInternalPtr, flags) ClientData clientData; /* unused. */ Tcl_Interp *interp; /* Interpreter for error reporting, or NULL, * if no error message is wanted. */ Tk_Window tkwin; /* A window. Needed by Tk_GetPixels() */ Tcl_Obj **valuePtr; /* The argument to "-padx", "-pady", "-ipadx", * or "-ipady". The thing to be parsed. */ char *recordPtr; /* Pointer to start of widget record. */ int internalOffset; /* Offset of internal representation or * -1, if no internal repr is wanted. */ char *saveInternalPtr; /* Pointer to the place, where the saved * internal form (of type "int *") resides. */ int flags; /* Flags as specified in Tk_OptionSpec. */ { int topLeft, bottomRight; /* The two components of the padding. */ int *new; /* Pointer to the allocated array of integers * containing the parsed pad amounts. */ int **internalPtr; /* Pointer to the place, where the internal * form (of type "int *") resides. */ /* * Check that the given object indeed specifies a valid pad amount. */ if (TreeCtrl_GetPadAmountFromObj(interp, tkwin, *valuePtr, &topLeft, &bottomRight) != TCL_OK) { return TCL_ERROR; } /* * Store a pointer to an allocated array of the two padding values * into the widget record at the specified offset. */ if (internalOffset >= 0) { internalPtr = (int **) (recordPtr + internalOffset); *(int **) saveInternalPtr = *internalPtr; new = (int *) ckalloc(2 * sizeof(int)); new[PAD_TOP_LEFT] = topLeft; new[PAD_BOTTOM_RIGHT] = bottomRight; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * PadAmountOptionGet(clientData, tkwin, recordPtr, internalOffset) ClientData clientData; /* unused. */ Tk_Window tkwin; /* A window; unused. */ char *recordPtr; /* Pointer to start of widget record. */ int internalOffset; /* Offset of internal representation. */ { int *padAmounts = *(int **)(recordPtr + internalOffset); return TreeCtrl_NewPadAmountObj(padAmounts); } static void PadAmountOptionRestore(clientData, tkwin, internalPtr, saveInternalPtr) ClientData clientData; /* unused. */ Tk_Window tkwin; /* A window; unused. */ char *internalPtr; /* Pointer to the place, where the internal * form (of type "int *") resides. */ char *saveInternalPtr; /* Pointer to the place, where the saved * internal form (of type "int *") resides. */ { *(int **) internalPtr = *(int **) saveInternalPtr; } static void PadAmountOptionFree(clientData, tkwin, internalPtr) ClientData clientData; /* unused. */ Tk_Window tkwin; /* A window; unused */ char *internalPtr; /* Pointer to the place, where the internal * form (of type "int *") resides. */ { if (*(int **)internalPtr != NULL) { ckfree((char *) *(int **)internalPtr); } } /* *---------------------------------------------------------------------- * * ObjectIsEmpty -- * * This procedure tests whether the string value of an object is * empty. * * Results: * The return value is 1 if the string value of objPtr has length * zero, and 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int ObjectIsEmpty( Tcl_Obj *obj /* Object to test. May be NULL. */ ) { int length; if (obj == NULL) return 1; if (obj->bytes != NULL) return (obj->length == 0); Tcl_GetStringFromObj(obj, &length); return (length == 0); } #define PERSTATE_ROUNDUP 5 /* *---------------------------------------------------------------------- * * PerStateInfo_Free -- * * Frees memory and resources associated with a single per-state * option. pInfo is set to an empty state ready to be used again. * * Results: * None. * * Side effects: * Memory is deallocated. Colors, etc are freed. * *---------------------------------------------------------------------- */ void PerStateInfo_Free( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo /* Per-state info to free. */ ) { PerStateData *pData = pInfo->data; int i; if (pInfo->data == NULL) return; #ifdef TREECTRL_DEBUG if (pInfo->type != typePtr) panic("PerStateInfo_Free type mismatch: got %s expected %s", pInfo->type ? pInfo->type->name : "NULL", typePtr->name); #endif for (i = 0; i < pInfo->count; i++) { (*typePtr->freeProc)(tree, pData); pData = (PerStateData *) (((char *) pData) + typePtr->size); } #ifdef ALLOC_HAX AllocHax_CFree(tree->allocData, typePtr->name, (char *) pInfo->data, typePtr->size, pInfo->count, PERSTATE_ROUNDUP); #else WIPEFREE(pInfo->data, typePtr->size * pInfo->count); #endif pInfo->data = NULL; pInfo->count = 0; } /* *---------------------------------------------------------------------- * * PerStateInfo_FromObj -- * * Parse a Tcl_Obj to an array of PerStateData. The current data * is freed (if any). If the Tcl_Obj is NULL then pInfo is left in * an empty state ready to be used again. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated/deallocated. * *---------------------------------------------------------------------- */ int PerStateInfo_FromObj( TreeCtrl *tree, /* Widget info. */ StateFromObjProc proc, /* Procedure used to turn a Tcl_Obj into * a state bit-flag. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo /* Per-state info to return. pInfo->obj * must be NULL or point to a valid Tcl_Obj. */ ) { int i, j; int objc, objc2; Tcl_Obj **objv, **objv2; PerStateData *pData; #ifdef TREECTRL_DEBUG pInfo->type = typePtr; #endif PerStateInfo_Free(tree, typePtr, pInfo); if (pInfo->obj == NULL) return TCL_OK; if (Tcl_ListObjGetElements(tree->interp, pInfo->obj, &objc, &objv) != TCL_OK) return TCL_ERROR; if (objc == 0) return TCL_OK; if (objc == 1) { #ifdef ALLOC_HAX pData = (PerStateData *) AllocHax_CAlloc(tree->allocData, typePtr->name, typePtr->size, 1, PERSTATE_ROUNDUP); #else pData = (PerStateData *) ckalloc(typePtr->size); #endif pData->stateOff = pData->stateOn = 0; /* all states */ if ((*typePtr->fromObjProc)(tree, objv[0], pData) != TCL_OK) { #ifdef ALLOC_HAX AllocHax_CFree(tree->allocData, typePtr->name, (char *) pData, typePtr->size, 1, PERSTATE_ROUNDUP); #else WIPEFREE(pData, typePtr->size); #endif return TCL_ERROR; } pInfo->data = pData; pInfo->count = 1; return TCL_OK; } if (objc & 1) { FormatResult(tree->interp, "list must have even number of elements"); return TCL_ERROR; } #ifdef ALLOC_HAX pData = (PerStateData *) AllocHax_CAlloc(tree->allocData, typePtr->name, typePtr->size, objc / 2, PERSTATE_ROUNDUP); #else pData = (PerStateData *) ckalloc(typePtr->size * (objc / 2)); #endif pInfo->data = pData; for (i = 0; i < objc; i += 2) { if ((*typePtr->fromObjProc)(tree, objv[i], pData) != TCL_OK) { goto freeIt; } pInfo->count++; if (Tcl_ListObjGetElements(tree->interp, objv[i + 1], &objc2, &objv2) != TCL_OK) { goto freeIt; } pData->stateOff = pData->stateOn = 0; /* all states */ for (j = 0; j < objc2; j++) { if (proc(tree, objv2[j], &pData->stateOff, &pData->stateOn) != TCL_OK) { goto freeIt; } } pData = (PerStateData *) (((char *) pData) + typePtr->size); } return TCL_OK; freeIt: pData = pInfo->data; for (i = 0; i < pInfo->count; i++) { (*typePtr->freeProc)(tree, pData); pData = (PerStateData *) (((char *) pData) + typePtr->size); } #ifdef ALLOC_HAX AllocHax_CFree(tree->allocData, typePtr->name, (char *) pInfo->data, typePtr->size, objc / 2, PERSTATE_ROUNDUP); #else WIPEFREE(pInfo->data, typePtr->size * (objc / 2)); #endif pInfo->data = NULL; pInfo->count = 0; return TCL_ERROR; } /* *---------------------------------------------------------------------- * * PerStateInfo_ForState -- * * Return the best-matching PerStateData for a given state. * * Results: * The return value is a pointer to the best-matching PerStateData. * *match is set to a MATCH_xxx constant. NULL is returned if * no appropriate PerStateData was found. * * Side effects: * None. * *---------------------------------------------------------------------- */ PerStateData * PerStateInfo_ForState( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo, /* Per-state info to search. */ int state, /* State bit-flags to compare. */ int *match /* Returned MATCH_xxx constant. */ ) { PerStateData *pData = pInfo->data; int stateOff = ~state, stateOn = state; int i; #ifdef TREECTRL_DEBUG if ((pInfo->data != NULL) && (pInfo->type != typePtr)) { panic("PerStateInfo_ForState type mismatch: got %s expected %s", pInfo->type ? pInfo->type->name : "NULL", typePtr->name); } #endif for (i = 0; i < pInfo->count; i++) { /* Any state */ if ((pData->stateOff == 0) && (pData->stateOn == 0)) { if (match) (*match) = MATCH_ANY; return pData; } /* Exact match */ if ((pData->stateOff == stateOff) && (pData->stateOn == stateOn)) { if (match) (*match) = MATCH_EXACT; return pData; } /* Partial match */ if (((pData->stateOff & stateOff) == pData->stateOff) && ((pData->stateOn & stateOn) == pData->stateOn)) { if (match) (*match) = MATCH_PARTIAL; return pData; } pData = (PerStateData *) (((char *) pData) + typePtr->size); } if (match) (*match) = MATCH_NONE; return NULL; } /* *---------------------------------------------------------------------- * * PerStateInfo_ObjForState -- * * Return a Tcl_Obj from the list object that was parsed by * PerStateInfo_FromObj(). pInfo is searched for the best-matching * PerStateData for the given state and the object used to * create that PerStateData is returned. * * Results: * *match is set to a MATCH_xxx constant. NULL is returned if * no appropriate PerStateData was found. The object should not * be modified by the caller. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * PerStateInfo_ObjForState( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo, /* Per-state info to search. */ int state, /* State bit-flags to compare. */ int *match /* Returned MATCH_xxx constant. */ ) { PerStateData *pData; Tcl_Obj *obj; int i; #ifdef TREECTRL_DEBUG if ((pInfo->data != NULL) && (pInfo->type != typePtr)) panic("PerStateInfo_ObjForState type mismatch: got %s expected %s", pInfo->type ? pInfo->type->name : "NULL", typePtr->name); #endif pData = PerStateInfo_ForState(tree, typePtr, pInfo, state, match); if (pData != NULL) { i = (int)((char *) pData - (char *) pInfo->data) / (int)typePtr->size; Tcl_ListObjIndex(tree->interp, pInfo->obj, i * 2, &obj); return obj; } return NULL; } /* *---------------------------------------------------------------------- * * PerStateInfo_Undefine -- * * Called when a user-defined state flag is undefined. The state * flag is cleared from every PerStateData using that flag. The * list object that was parsed by PerStateInfo_FromObj() is modified * by removing any reference to the undefined state. * * Results: * The return value is a boolean indicating whether or not pInfo * was modified. * * Side effects: * The list object pointed to by pInfo->obj may be recreated. * *---------------------------------------------------------------------- */ Tcl_Obj * DuplicateListObj( Tcl_Obj *objPtr ) { int objc; Tcl_Obj **objv; int result; /* * Comment from TclLsetFlat: * ... A plain Tcl_DuplicateObj * will just increase the intrep's refCount without upping the sublists' * refCount, so that their true shared status cannot be determined from * their refCount. */ result = Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv); return Tcl_NewListObj(objc, objv); } int PerStateInfo_Undefine( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo, /* Per-state info to modify. */ int state /* State bit-flag that was undefined. */ ) { PerStateData *pData = pInfo->data; int i, j, numStates, stateOff, stateOn; Tcl_Obj *configObj = pInfo->obj, *listObj, *stateObj; int modified = 0; #ifdef TREECTRL_DEBUG if ((pInfo->data != NULL) && (pInfo->type != typePtr)) panic("PerStateInfo_Undefine type mismatch: got %s expected %s", pInfo->type ? pInfo->type->name : "NULL", typePtr->name); #endif for (i = 0; i < pInfo->count; i++) { if ((pData->stateOff | pData->stateOn) & state) { pData->stateOff &= ~state; pData->stateOn &= ~state; if (Tcl_IsShared(configObj)) { configObj = DuplicateListObj(configObj); Tcl_DecrRefCount(pInfo->obj); Tcl_IncrRefCount(configObj); pInfo->obj = configObj; } Tcl_ListObjIndex(tree->interp, configObj, i * 2 + 1, &listObj); if (Tcl_IsShared(listObj)) { listObj = DuplicateListObj(listObj); Tcl_ListObjReplace(tree->interp, configObj, i * 2 + 1, 1, 1, &listObj); } Tcl_ListObjLength(tree->interp, listObj, &numStates); for (j = 0; j < numStates; ) { Tcl_ListObjIndex(tree->interp, listObj, j, &stateObj); stateOff = stateOn = 0; TreeStateFromObj(tree, stateObj, &stateOff, &stateOn); if ((stateOff | stateOn) & state) { Tcl_ListObjReplace(tree->interp, listObj, j, 1, 0, NULL); numStates--; } else j++; } /* Given {bitmap {state1 state2 state3}}, we just invalidated * the string rep of the sublist {state1 state2 state3}, but not * the parent list. */ Tcl_InvalidateStringRep(configObj); modified = 1; } pData = (PerStateData *) (((char *) pData) + typePtr->size); } return modified; } /*****/ void PerStateGC_Free(TreeCtrl *tree, struct PerStateGC **pGCPtr) { struct PerStateGC *pGC = (*pGCPtr), *next; while (pGC != NULL) { next = pGC->next; Tk_FreeGC(tree->display, pGC->gc); WFREE(pGC, struct PerStateGC); pGC = next; } (*pGCPtr) = NULL; } GC PerStateGC_Get(TreeCtrl *tree, struct PerStateGC **pGCPtr, unsigned long mask, XGCValues *gcValues) { struct PerStateGC *pGC; if ((mask | (GCFont | GCForeground | GCBackground | GCGraphicsExposures)) != (GCFont | GCForeground | GCBackground | GCGraphicsExposures)) panic("PerStateGC_Get: unsupported mask"); for (pGC = (*pGCPtr); pGC != NULL; pGC = pGC->next) { if (mask != pGC->mask) continue; if ((mask & GCFont) && (pGC->gcValues.font != gcValues->font)) continue; if ((mask & GCForeground) && (pGC->gcValues.foreground != gcValues->foreground)) continue; if ((mask & GCBackground) && (pGC->gcValues.background != gcValues->background)) continue; if ((mask & GCGraphicsExposures) && (pGC->gcValues.graphics_exposures != gcValues->graphics_exposures)) continue; return pGC->gc; } pGC = (struct PerStateGC *) ckalloc(sizeof(*pGC)); pGC->gcValues = (*gcValues); pGC->mask = mask; pGC->gc = Tk_GetGC(tree->tkwin, mask, gcValues); pGC->next = (*pGCPtr); (*pGCPtr) = pGC; return pGC->gc; } /*****/ typedef struct PerStateDataBitmap PerStateDataBitmap; struct PerStateDataBitmap { PerStateData header; Pixmap bitmap; }; static int PSDBitmapFromObj(TreeCtrl *tree, Tcl_Obj *obj, PerStateDataBitmap *pBitmap) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pBitmap->bitmap = None; } else { pBitmap->bitmap = Tk_AllocBitmapFromObj(tree->interp, tree->tkwin, obj); if (pBitmap->bitmap == None) return TCL_ERROR; } return TCL_OK; } static void PSDBitmapFree(TreeCtrl *tree, PerStateDataBitmap *pBitmap) { if (pBitmap->bitmap != None) Tk_FreeBitmap(tree->display, pBitmap->bitmap); } PerStateType pstBitmap = { "pstBitmap", sizeof(PerStateDataBitmap), (PerStateType_FromObjProc) PSDBitmapFromObj, (PerStateType_FreeProc) PSDBitmapFree }; Pixmap PerStateBitmap_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataBitmap *pData; pData = (PerStateDataBitmap *) PerStateInfo_ForState(tree, &pstBitmap, pInfo, state, match); if (pData != NULL) return pData->bitmap; return None; } void PerStateBitmap_MaxSize( TreeCtrl *tree, PerStateInfo *pInfo, int *widthPtr, int *heightPtr) { PerStateDataBitmap *pData = (PerStateDataBitmap *) pInfo->data; int i, width, height, w, h; width = height = 0; for (i = 0; i < pInfo->count; i++, ++pData) { if (pData->bitmap == None) continue; Tk_SizeOfBitmap(tree->display, pData->bitmap, &w, &h); width = MAX(width, w); height = MAX(height, h); } (*widthPtr) = width; (*heightPtr) = height; } /*****/ typedef struct PerStateDataBoolean PerStateDataBoolean; struct PerStateDataBoolean { PerStateData header; int value; }; static int PSDBooleanFromObj(TreeCtrl *tree, Tcl_Obj *obj, PerStateDataBoolean *pBoolean) { if (ObjectIsEmpty(obj)) { pBoolean->value = -1; } else { if (Tcl_GetBooleanFromObj(tree->interp, obj, &pBoolean->value) != TCL_OK) return TCL_ERROR; } return TCL_OK; } static void PSDBooleanFree(TreeCtrl *tree, PerStateDataBoolean *pBoolean) { } PerStateType pstBoolean = { "pstBoolean", sizeof(PerStateDataBoolean), (PerStateType_FromObjProc) PSDBooleanFromObj, (PerStateType_FreeProc) PSDBooleanFree }; int PerStateBoolean_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataBoolean *pData; pData = (PerStateDataBoolean *) PerStateInfo_ForState(tree, &pstBoolean, pInfo, state, match); if (pData != NULL) return pData->value; return -1; } /*****/ typedef struct PerStateDataBorder PerStateDataBorder; struct PerStateDataBorder { PerStateData header; Tk_3DBorder border; }; static int PSDBorderFromObj(TreeCtrl *tree, Tcl_Obj *obj, PerStateDataBorder *pBorder) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pBorder->border = NULL; } else { pBorder->border = Tk_Alloc3DBorderFromObj(tree->interp, tree->tkwin, obj); if (pBorder->border == NULL) return TCL_ERROR; } return TCL_OK; } static void PSDBorderFree(TreeCtrl *tree, PerStateDataBorder *pBorder) { if (pBorder->border != NULL) Tk_Free3DBorder(pBorder->border); } PerStateType pstBorder = { "pstBorder", sizeof(PerStateDataBorder), (PerStateType_FromObjProc) PSDBorderFromObj, (PerStateType_FreeProc) PSDBorderFree }; Tk_3DBorder PerStateBorder_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataBorder *pData; pData = (PerStateDataBorder *) PerStateInfo_ForState(tree, &pstBorder, pInfo, state, match); if (pData != NULL) return pData->border; return NULL; } /*****/ typedef struct PerStateDataColor PerStateDataColor; struct PerStateDataColor { PerStateData header; XColor *color; }; static int PSDColorFromObj(TreeCtrl *tree, Tcl_Obj *obj, PerStateDataColor *pColor) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pColor->color = NULL; } else { pColor->color = Tk_AllocColorFromObj(tree->interp, tree->tkwin, obj); if (pColor->color == NULL) return TCL_ERROR; } return TCL_OK; } static void PSDColorFree(TreeCtrl *tree, PerStateDataColor *pColor) { if (pColor->color != NULL) Tk_FreeColor(pColor->color); } PerStateType pstColor = { "pstColor", sizeof(PerStateDataColor), (PerStateType_FromObjProc) PSDColorFromObj, (PerStateType_FreeProc) PSDColorFree }; XColor *PerStateColor_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataColor *pData; pData = (PerStateDataColor *) PerStateInfo_ForState(tree, &pstColor, pInfo, state, match); if (pData != NULL) return pData->color; return NULL; } /*****/ typedef struct PerStateDataFont PerStateDataFont; struct PerStateDataFont { PerStateData header; Tk_Font tkfont; }; static int PSDFontFromObj(TreeCtrl *tree, Tcl_Obj *obj, PerStateDataFont *pFont) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pFont->tkfont = NULL; } else { pFont->tkfont = Tk_AllocFontFromObj(tree->interp, tree->tkwin, obj); if (pFont->tkfont == NULL) return TCL_ERROR; } return TCL_OK; } static void PSDFontFree(TreeCtrl *tree, PerStateDataFont *pFont) { if (pFont->tkfont != NULL) Tk_FreeFont(pFont->tkfont); } PerStateType pstFont = { "pstFont", sizeof(PerStateDataFont), (PerStateType_FromObjProc) PSDFontFromObj, (PerStateType_FreeProc) PSDFontFree }; Tk_Font PerStateFont_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataFont *pData; pData = (PerStateDataFont *) PerStateInfo_ForState(tree, &pstFont, pInfo, state, match); if (pData != NULL) return pData->tkfont; return NULL; } /*****/ typedef struct PerStateDataImage PerStateDataImage; struct PerStateDataImage { PerStateData header; Tk_Image image; char *string; }; static int PSDImageFromObj(TreeCtrl *tree, Tcl_Obj *obj, PerStateDataImage *pImage) { int length; char *string; if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pImage->image = NULL; pImage->string = NULL; } else { string = Tcl_GetStringFromObj(obj, &length); pImage->image = Tree_GetImage(tree, string); if (pImage->image == NULL) return TCL_ERROR; pImage->string = ckalloc(length + 1); strcpy(pImage->string, string); } return TCL_OK; } static void PSDImageFree(TreeCtrl *tree, PerStateDataImage *pImage) { if (pImage->string != NULL) ckfree(pImage->string); if (pImage->image != NULL) Tree_FreeImage(tree, pImage->image); } PerStateType pstImage = { "pstImage", sizeof(PerStateDataImage), (PerStateType_FromObjProc) PSDImageFromObj, (PerStateType_FreeProc) PSDImageFree }; Tk_Image PerStateImage_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataImage *pData; pData = (PerStateDataImage *) PerStateInfo_ForState(tree, &pstImage, pInfo, state, match); if (pData != NULL) return pData->image; return NULL; } void PerStateImage_MaxSize( TreeCtrl *tree, PerStateInfo *pInfo, int *widthPtr, int *heightPtr) { PerStateDataImage *pData = (PerStateDataImage *) pInfo->data; int i, width, height, w, h; width = height = 0; for (i = 0; i < pInfo->count; i++, ++pData) { if (pData->image == None) continue; Tk_SizeOfImage(pData->image, &w, &h); width = MAX(width, w); height = MAX(height, h); } (*widthPtr) = width; (*heightPtr) = height; } /*****/ typedef struct PerStateDataRelief PerStateDataRelief; struct PerStateDataRelief { PerStateData header; int relief; }; static int PSDReliefFromObj(TreeCtrl *tree, Tcl_Obj *obj, PerStateDataRelief *pRelief) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pRelief->relief = TK_RELIEF_NULL; } else { if (Tk_GetReliefFromObj(tree->interp, obj, &pRelief->relief) != TCL_OK) return TCL_ERROR; } return TCL_OK; } static void PSDReliefFree(TreeCtrl *tree, PerStateDataRelief *pRelief) { } PerStateType pstRelief = { "pstRelief", sizeof(PerStateDataRelief), (PerStateType_FromObjProc) PSDReliefFromObj, (PerStateType_FreeProc) PSDReliefFree }; int PerStateRelief_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataRelief *pData; pData = (PerStateDataRelief *) PerStateInfo_ForState(tree, &pstRelief, pInfo, state, match); if (pData != NULL) return pData->relief; return TK_RELIEF_NULL; } /*****/ void PSTSave( PerStateInfo *pInfo, PerStateInfo *pSave) { #ifdef TREECTRL_DEBUG pSave->type = pInfo->type; /* could be NULL */ #endif pSave->data = pInfo->data; pSave->count = pInfo->count; pInfo->data = NULL; pInfo->count = 0; } void PSTRestore( TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, PerStateInfo *pSave) { PerStateInfo_Free(tree, typePtr, pInfo); pInfo->data = pSave->data; pInfo->count = pSave->count; } #ifdef ALLOC_HAX /* * The following AllocHax_xxx calls implement a mini memory allocator that * allocates blocks of same-sized chunks, and holds on to those chunks when * they are freed so they can be reused quickly. If you don't want to use it * just comment out #define ALLOC_HAX in tkTreeCtrl.h. */ typedef struct AllocElem AllocElem; typedef struct AllocBlock AllocBlock; typedef struct AllocList AllocList; typedef struct AllocData AllocData; #ifdef TREECTRL_DEBUG #define ALLOC_STATS #endif #ifdef ALLOC_STATS typedef struct AllocStats AllocStats; #endif /* * One of the following structures exists for each client piece of memory. * These structures are allocated in arrays (blocks). */ struct AllocElem { AllocElem *next; #ifdef TREECTRL_DEBUG int free; int size; #endif char body[1]; /* First byte of client's space. Actual * size of this field will be larger than * one. */ }; struct AllocBlock { int count; /* Size of .elem[] */ AllocBlock *next; /* Next block with same-sized elems. */ AllocElem elem[1]; /* Actual size will be larger than one. */ }; /* * One of the following structures maintains an array of blocks of AllocElems * of the same size. */ struct AllocList { int size; /* Size of every AllocElem.body[] */ AllocElem *head; /* Top of stack of unused pieces of memory. */ AllocBlock *blocks; /* Linked list of allocated blocks. The blocks * may contain a different number of elements. */ int blockSize; /* The number of AllocElems per block to allocate. * Starts at 16 and gets doubled up to 1024. */ AllocList *next; /* Points to an AllocList with a different .size */ }; /* * A pointer to one of the following structures is stored in each TreeCtrl. */ struct AllocData { AllocList *freeLists; /* Linked list. */ #ifdef ALLOC_STATS AllocStats *stats; /* For memory-usage reporting. */ #endif }; #ifdef ALLOC_STATS struct AllocStats { Tk_Uid id; /* Name for reporting results. */ unsigned count; /* Number of allocations. */ unsigned size; /* Total allocated bytes. */ AllocStats *next; /* Linked list. */ }; #endif /* * The following macro computes the offset of the "body" field within * AllocElem. It is used to get back to the header pointer from the * body pointer that's used by clients. */ #define BODY_OFFSET \ ((unsigned long) (&((AllocElem *) 0)->body)) #ifdef ALLOC_STATS static AllocStats * AllocStats_Get( ClientData _data, Tk_Uid id ) { AllocData *data = (AllocData *) _data; AllocStats *stats = data->stats; while (stats != NULL) { if (stats->id == id) break; stats = stats->next; } if (stats == NULL) { stats = (AllocStats *) ckalloc(sizeof(AllocStats)); stats->id = id; stats->count = 0; stats->size = 0; stats->next = data->stats; data->stats = stats; } return stats; } void AllocHax_Stats( Tcl_Interp *interp, ClientData _data ) { AllocData *data = (AllocData *) _data; AllocStats *stats = data->stats; Tcl_DString dString; Tcl_DStringInit(&dString); while (stats != NULL) { DStringAppendf(&dString, "%-20s: %8d : %8d B %5d KB\n", stats->id, stats->count, stats->size, (stats->size + 1023) / 1024); stats = stats->next; } Tcl_DStringResult(interp, &dString); } #endif /* ALLOC_STATS */ /* *---------------------------------------------------------------------- * * AllocHax_Alloc -- * * Return storage for a piece of data of the given size. * * Results: * The return value is a pointer to memory for the caller's * use. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ char * AllocHax_Alloc( ClientData _data, /* Token returned by AllocHax_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ int size /* Number of bytes needed. */ ) { AllocData *data = (AllocData *) _data; AllocList *freeLists = data->freeLists; AllocList *freeList = freeLists; AllocBlock *block; AllocElem *elem, *result; #ifdef ALLOC_STATS AllocStats *stats = AllocStats_Get(_data, id); #endif int i; #ifdef ALLOC_STATS stats->count++; stats->size += size; #endif while ((freeList != NULL) && (freeList->size != size)) freeList = freeList->next; if (freeList == NULL) { freeList = (AllocList *) ckalloc(sizeof(AllocList)); freeList->size = size; freeList->head = NULL; freeList->next = freeLists; freeList->blocks = NULL; freeList->blockSize = 16; freeLists = freeList; ((AllocData *) data)->freeLists = freeLists; } if (freeList->head == NULL) { unsigned elemSize = TCL_ALIGN(BODY_OFFSET + size); block = (AllocBlock *) ckalloc(Tk_Offset(AllocBlock, elem) + elemSize * freeList->blockSize); block->count = freeList->blockSize; block->next = freeList->blocks; /* dbwin("AllocHax_Alloc alloc %d of size %d\n", freeList->blockSize, size); */ freeList->blocks = block; if (freeList->blockSize < 1024) freeList->blockSize *= 2; freeList->head = block->elem; elem = freeList->head; for (i = 1; i < block->count - 1; i++) { #ifdef TREECTRL_DEBUG elem->free = 1; elem->size = size; #endif elem->next = (AllocElem *) (((char *) freeList->head) + elemSize * i); elem = elem->next; } elem->next = NULL; #ifdef TREECTRL_DEBUG elem->free = 1; elem->size = size; #endif } result = freeList->head; freeList->head = result->next; #ifdef TREECTRL_DEBUG if (!result->free) panic("AllocHax_Alloc: element not marked free"); result->free = 0; #endif return result->body; } /* *---------------------------------------------------------------------- * * AllocHax_Realloc -- * * Realloc. * * Results: * The return value is a pointer to memory for the caller's * use. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ char * AllocHax_Realloc( ClientData data, /* Token returned by AllocHax_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ char *ptr, int size1, /* Number of bytes in ptr. */ int size2 /* Number of bytes needed. */ ) { char *ptr2; ptr2 = AllocHax_Alloc(data, id, size2); memcpy(ptr2, ptr, MIN(size1, size2)); AllocHax_Free(data, id, ptr, size1); return ptr2; } /* *---------------------------------------------------------------------- * * AllocHax_Free -- * * Mark a piece of memory as free for reuse. * * Results: * The piece of memory is added to a list of free pieces of the * same size. * * Side effects: * None. * *---------------------------------------------------------------------- */ void AllocHax_Free( ClientData _data, /* Token returned by AllocHax_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ char *ptr, /* Memory to mark for reuse. Must have * been allocated by AllocHax_Alloc(). */ int size /* Number of bytes. Must match the size * passed to AllocHax_CAlloc(). */ ) { AllocData *data = (AllocData *) _data; AllocList *freeLists = data->freeLists; AllocList *freeList = freeLists; AllocElem *elem; #ifdef ALLOC_STATS AllocStats *stats = AllocStats_Get(_data, id); #endif #ifdef ALLOC_STATS stats->count--; stats->size -= size; #endif /* * Comment from Tcl_DbCkfree: * The following cast is *very* tricky. Must convert the pointer * to an integer before doing arithmetic on it, because otherwise * the arithmetic will be done differently (and incorrectly) on * word-addressed machines such as Crays (will subtract only bytes, * even though BODY_OFFSET is in words on these machines). */ elem = (AllocElem *) (((unsigned long) ptr) - BODY_OFFSET); #ifdef TREECTRL_DEBUG if (elem->free) panic("AllocHax_Free: element already marked free"); if (elem->size != size) panic("AllocHax_Free: element size %d != size %d", elem->size, size); #endif while (freeList != NULL && freeList->size != size) freeList = freeList->next; if (freeList == NULL) panic("AllocHax_Free: can't find free list for size %d", size); WIPE(elem->body, size); elem->next = freeList->head; #ifdef TREECTRL_DEBUG elem->free = 1; #endif freeList->head = elem; } /* *---------------------------------------------------------------------- * * AllocHax_CAlloc -- * * Return storage for an array of pieces of memory. * * Results: * Pointer to the available memory. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ char * AllocHax_CAlloc( ClientData data, /* Token returned by AllocHax_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ int size, /* Number of bytes needed for each piece * of memory. */ int count, /* Number of pieces of memory needed. */ int roundUp /* Positive number used to reduce the number * of lists of memory pieces of different * size. */ ) { int n = (count / roundUp) * roundUp + ((count % roundUp) ? roundUp : 0); #ifdef ALLOC_STATS AllocStats *stats = AllocStats_Get(data, id); #endif #ifdef ALLOC_STATS stats->count += count - 1; #endif return AllocHax_Alloc(data, id, size * n); } /* *---------------------------------------------------------------------- * * AllocHax_CFree -- * * Mark a piece of memory as free for reuse. * * Results: * The piece of memory is added to a list of free pieces of the * same size. * * Side effects: * None. * *---------------------------------------------------------------------- */ void AllocHax_CFree( ClientData data, /* Token returned by AllocHax_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ char *ptr, /* Memory to mark for reuse. Must have * been allocated by AllocHax_CAlloc(). */ int size, /* Same arg to AllocHax_CAlloc(). */ int count, /* Same arg to AllocHax_CAlloc(). */ int roundUp /* Same arg to AllocHax_CAlloc(). */ ) { int n = (count / roundUp) * roundUp + ((count % roundUp) ? roundUp : 0); #ifdef ALLOC_STATS AllocStats *stats = AllocStats_Get(data, id); #endif AllocHax_Free(data, id, ptr, size * n); #ifdef ALLOC_STATS stats->count -= count - 1; #endif } /* *---------------------------------------------------------------------- * * AllocHax_Init -- * * Allocate and initialize a new memory-manager record. * * Results: * Pointer to memory-manager record. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ ClientData AllocHax_Init(void) { AllocData *data = (AllocData *) ckalloc(sizeof(AllocData)); data->freeLists = NULL; #ifdef ALLOC_STATS data->stats = NULL; #endif return data; } /* *---------------------------------------------------------------------- * * AllocHax_Finalize -- * * Free all the memory associated with a memory-manager record. * * Results: * Pointer to memory-manager record. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void AllocHax_Finalize( ClientData _data /* Pointer to AllocData created by * AllocHax_Init(). */ ) { AllocData *data = (AllocData *) _data; AllocList *freeList = data->freeLists; #ifdef ALLOC_STATS AllocStats *stats = data->stats; #endif while (freeList != NULL) { AllocList *nextList = freeList->next; AllocBlock *block = freeList->blocks; while (block != NULL) { AllocBlock *nextBlock = block->next; ckfree((char *) block); block = nextBlock; } ckfree((char *) freeList); freeList = nextList; } #ifdef ALLOC_STATS while (stats != NULL) { AllocStats *next = stats->next; ckfree((char *) stats); stats = next; } #endif ckfree((char *) data); } #endif /* ALLOC_HAX */ /* *---------------------------------------------------------------------- * * TreePtrList_Init -- * * Initializes an pointer list, discarding any previous contents * of the pointer list (TreePtrList_Free should have been called already * if the pointer list was previously in use). * * Results: * None. * * Side effects: * The pointer list is initialized to be empty. * *---------------------------------------------------------------------- */ void TreePtrList_Init( TreeCtrl *tree, /* Widget info. */ TreePtrList *tplPtr, /* Structure describing pointer list. */ int count /* Number of pointers the list should hold. * 0 for default. */ ) { tplPtr->tree = tree; tplPtr->pointers = tplPtr->pointerSpace; tplPtr->count = 0; tplPtr->space = TIL_STATIC_SPACE; if (count + 1 > TIL_STATIC_SPACE) { tplPtr->space = count + 1; tplPtr->pointers = (ClientData *) ckalloc(tplPtr->space * sizeof(ClientData)); } tplPtr->pointers[0] = NULL; } /* *---------------------------------------------------------------------- * * TreePtrList_Grow -- * * Increase the available space in an pointer list. * * Results: * The pointers[] array is resized if needed. * * Side effects: * Memory gets reallocated if needed. * *---------------------------------------------------------------------- */ void TreePtrList_Grow( TreePtrList *tplPtr, /* Structure describing pointer list. */ int count /* Number of pointers the list should hold. */ ) { if (tplPtr->space >= count + 1) return; while (tplPtr->space < count + 1) tplPtr->space *= 2; if (tplPtr->pointers == tplPtr->pointerSpace) { ClientData *pointers; pointers = (ClientData *) ckalloc(tplPtr->space * sizeof(ClientData)); memcpy(pointers, tplPtr->pointers, (tplPtr->count + 1) * sizeof(ClientData)); tplPtr->pointers = pointers; } else { tplPtr->pointers = (ClientData *) ckrealloc((char *) tplPtr->pointers, tplPtr->space * sizeof(ClientData)); } } /* *---------------------------------------------------------------------- * * TreePtrList_Append -- * * Append an pointer to an pointer list. * * Results: * The return value is a pointer to the list of pointers. * * Side effects: * Memory gets reallocated if needed. * *---------------------------------------------------------------------- */ ClientData * TreePtrList_Append( TreePtrList *tplPtr, /* Structure describing pointer list. */ ClientData pointer /* Item to append. */ ) { TreePtrList_Grow(tplPtr, tplPtr->count + 1); tplPtr->pointers[tplPtr->count] = pointer; tplPtr->count++; tplPtr->pointers[tplPtr->count] = NULL; return tplPtr->pointers; } /* *---------------------------------------------------------------------- * * TreePtrList_Concat -- * * Join two pointer lists. * * Results: * The return value is a pointer to the list of pointers. * * Side effects: * Memory gets reallocated if needed. * *---------------------------------------------------------------------- */ ClientData * TreePtrList_Concat( TreePtrList *tplPtr, /* Structure describing pointer list. */ TreePtrList *tpl2Ptr /* Item list to append. */ ) { TreePtrList_Grow(tplPtr, tplPtr->count + tpl2Ptr->count); memcpy(tplPtr->pointers + tplPtr->count, tpl2Ptr->pointers, tpl2Ptr->count * sizeof(ClientData)); tplPtr->count += tpl2Ptr->count; tplPtr->pointers[tplPtr->count] = NULL; return tplPtr->pointers; } /* *---------------------------------------------------------------------- * * TreePtrList_Free -- * * Frees up any memory allocated for the pointer list and * reinitializes the pointer list to an empty state. * * Results: * None. * * Side effects: * The previous contents of the pointer list are lost. * *---------------------------------------------------------------------- */ void TreePtrList_Free( TreePtrList *tplPtr /* Structure describing pointer list. */ ) { if (tplPtr->pointers != tplPtr->pointerSpace) { ckfree((char *) tplPtr->pointers); } tplPtr->pointers = tplPtr->pointerSpace; tplPtr->count = 0; tplPtr->space = TIL_STATIC_SPACE; tplPtr->pointers[0] = NULL; } #define TAG_INFO_SIZE(tagSpace) \ (Tk_Offset(TagInfo, tagPtr) + ((tagSpace) * sizeof(Tk_Uid))) static CONST char *TagInfoUid = "TagInfo"; /* *---------------------------------------------------------------------- * * TagInfo_Add -- * * Adds tags to a list of tags. * * Results: * Non-duplicate tags are added. * * Side effects: * Memory may be (re)allocated. * *---------------------------------------------------------------------- */ TagInfo * TagInfo_Add( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo, /* Tag list. May be NULL. */ Tk_Uid tags[], int numTags ) { int i, j; if (tagInfo == NULL) { if (numTags <= TREE_TAG_SPACE) { #ifdef ALLOC_HAX tagInfo = (TagInfo *) AllocHax_Alloc(tree->allocData, TagInfoUid, sizeof(TagInfo)); #else tagInfo = (TagInfo *) ckalloc(sizeof(TagInfo)); #endif tagInfo->tagSpace = TREE_TAG_SPACE; } else { int tagSpace = (numTags / TREE_TAG_SPACE) * TREE_TAG_SPACE + ((numTags % TREE_TAG_SPACE) ? TREE_TAG_SPACE : 0); if (tagSpace % TREE_TAG_SPACE) panic("TagInfo_Add miscalc"); #ifdef ALLOC_HAX tagInfo = (TagInfo *) AllocHax_Alloc(tree->allocData, TagInfoUid, TAG_INFO_SIZE(tagSpace)); #else tagInfo = (TagInfo *) ckalloc(sizeof(TagInfo) + TAG_INFO_SIZE(tagSpace)); #endif tagInfo->tagSpace = tagSpace; } tagInfo->numTags = 0; } for (i = 0; i < numTags; i++) { for (j = 0; j < tagInfo->numTags; j++) { if (tagInfo->tagPtr[j] == tags[i]) break; } if (j >= tagInfo->numTags) { /* Resize existing storage if needed. */ if (tagInfo->tagSpace == tagInfo->numTags) { tagInfo->tagSpace += TREE_TAG_SPACE; #ifdef ALLOC_HAX tagInfo = (TagInfo *) AllocHax_Realloc(tree->allocData, TagInfoUid, (char *) tagInfo, TAG_INFO_SIZE(tagInfo->tagSpace - TREE_TAG_SPACE), TAG_INFO_SIZE(tagInfo->tagSpace)); #else tagInfo = (TagInfo *) ckrealloc((char *) tagInfo, TAG_INFO_SIZE(tagInfo->tagSpace)); #endif } tagInfo->tagPtr[tagInfo->numTags++] = tags[i]; } } return tagInfo; } /* *---------------------------------------------------------------------- * * TagInfo_Remove -- * * Removes tags from a list of tags. * * Results: * Existing tags are removed. * * Side effects: * Memory may be reallocated. * *---------------------------------------------------------------------- */ TagInfo * TagInfo_Remove( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo, /* Tag list. May be NULL. */ Tk_Uid tags[], int numTags ) { int i, j; if (tagInfo == NULL) return tagInfo; for (i = 0; i < numTags; i++) { for (j = 0; j < tagInfo->numTags; j++) { if (tagInfo->tagPtr[j] == tags[i]) { tagInfo->tagPtr[j] = tagInfo->tagPtr[tagInfo->numTags - 1]; tagInfo->numTags--; break; } } } if (tagInfo->numTags == 0) { TagInfo_Free(tree, tagInfo); tagInfo = NULL; } return tagInfo; } /* *---------------------------------------------------------------------- * * TagInfo_Names -- * * Build a list of unique tag names. * * Results: * Unique tags are added to a dynamically-allocated list. * * Side effects: * Memory may be (re)allocated. * *---------------------------------------------------------------------- */ Tk_Uid * TagInfo_Names( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo, /* Tag list. May be NULL. */ Tk_Uid *tags, /* Current list, may be NULL. */ int *numTagsPtr, /* Number of tags in tags[]. */ int *tagSpacePtr /* Size of tags[]. */ ) { int numTags = *numTagsPtr, tagSpace = *tagSpacePtr; int i, j; if (tagInfo == NULL) return tags; for (i = 0; i < tagInfo->numTags; i++) { Tk_Uid tag = tagInfo->tagPtr[i]; for (j = 0; j < numTags; j++) { if (tag == tags[j]) break; } if (j < numTags) continue; if ((tags == NULL) || (numTags == tagSpace)) { if (tags == NULL) { tagSpace = 32; tags = (Tk_Uid *) ckalloc(sizeof(Tk_Uid) * tagSpace); } else { tagSpace *= 2; tags = (Tk_Uid *) ckrealloc((char *) tags, sizeof(Tk_Uid) * tagSpace); } } tags[numTags++] = tag; } *numTagsPtr = numTags; *tagSpacePtr = tagSpace; return tags; } /* *---------------------------------------------------------------------- * * TagInfo_Copy -- * * Copy a list of tags. * * Results: * Allocates a new TagInfo if given one is not NULL. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ TagInfo * TagInfo_Copy( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo /* Tag list. May be NULL. */ ) { TagInfo *copy = NULL; if (tagInfo != NULL) { int tagSpace = tagInfo->tagSpace; #ifdef ALLOC_HAX copy = (TagInfo *) AllocHax_Alloc(tree->allocData, TagInfoUid, TAG_INFO_SIZE(tagSpace)); #else copy = (TagInfo *) ckalloc(TAG_INFO_SIZE(tagSpace)); #endif memcpy((void*)copy->tagPtr, (const void*)tagInfo->tagPtr, tagInfo->numTags * sizeof(Tk_Uid)); copy->numTags = tagInfo->numTags; copy->tagSpace = tagSpace; } return copy; } /* *---------------------------------------------------------------------- * * TagInfo_Free -- * * Free a list of tags. * * Results: * TagInfo struct is freed if non-NULL. * * Side effects: * Memory may be freed. * *---------------------------------------------------------------------- */ void TagInfo_Free( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo /* Tag list. May be NULL. */ ) { if (tagInfo != NULL) #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, TagInfoUid, (char *) tagInfo, TAG_INFO_SIZE(tagInfo->tagSpace)); #else ckfree((char *) tagInfo); #endif } int TagInfo_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, TagInfo **tagInfoPtr ) { int i, numTags; Tcl_Obj **listObjv; TagInfo *tagInfo = NULL; if (Tcl_ListObjGetElements(tree->interp, objPtr, &numTags, &listObjv) != TCL_OK) { return TCL_ERROR; } if (numTags == 0) { *tagInfoPtr = NULL; return TCL_OK; } for (i = 0; i < numTags; i++) { Tk_Uid tag = Tk_GetUid(Tcl_GetString(listObjv[i])); tagInfo = TagInfo_Add(tree, tagInfo, &tag, 1); } *tagInfoPtr = tagInfo; return TCL_OK; } Tcl_Obj * TagInfo_ToObj( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo ) { Tcl_Obj *listObj; int i; if (tagInfo == NULL) return NULL; listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < tagInfo->numTags; i++) { Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewStringObj((char *) tagInfo->tagPtr[i], -1)); } return listObj; } /* *---------------------------------------------------------------------- * * TagInfoCO_Set -- * TagInfoCO_Get -- * TagInfoCO_Restore -- * TagInfoCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a TagInfo record. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TagInfoCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; TagInfo *new, **internalPtr; if (internalOffset >= 0) internalPtr = (TagInfo **) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (TagInfo_FromObj(tree, (*value), &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { if ((*value) == NULL) new = NULL; *((TagInfo **) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * TagInfoCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; TagInfo *value = *(TagInfo **) (recordPtr + internalOffset); return TagInfo_ToObj(tree, value); } static void TagInfoCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(TagInfo **) internalPtr = *(TagInfo **) saveInternalPtr; } static void TagInfoCO_Free( ClientData clientData, /* unused. */ Tk_Window tkwin, /* A window; unused */ char *internalPtr /* Pointer to the place, where the internal * form resides. */ ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; TagInfo_Free(tree, *(TagInfo **)internalPtr); } Tk_ObjCustomOption TagInfoCO = { "tag list", TagInfoCO_Set, TagInfoCO_Get, TagInfoCO_Restore, TagInfoCO_Free, (ClientData) NULL }; /* *---------------------------------------------------------------------- * * TagExpr_Init -- * * This procedure initializes a TagExpr struct by parsing a Tcl_Obj * string representation of a tag expression. * * Results: * A standard Tcl result. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int TagExpr_Init( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *exprObj, /* Tag expression string. */ TagExpr *expr /* Struct to initialize. */ ) { int i; char *tag; expr->tree = tree; expr->index = 0; expr->length = 0; expr->uid = NULL; expr->allocated = sizeof(expr->staticUids) / sizeof(Tk_Uid); expr->uids = expr->staticUids; expr->simple = TRUE; expr->rewritebuffer = expr->staticRWB; tag = Tcl_GetStringFromObj(exprObj, &expr->stringLength); /* short circuit impossible searches for null tags */ if (expr->stringLength == 0) { return TCL_OK; } /* * Pre-scan tag for at least one unquoted "&&" "||" "^" "!" * if not found then use string as simple tag */ for (i = 0; i < expr->stringLength ; i++) { if (tag[i] == '"') { i++; for ( ; i < expr->stringLength; i++) { if (tag[i] == '\\') { i++; continue; } if (tag[i] == '"') { break; } } } else { if ((tag[i] == '&' && tag[i+1] == '&') || (tag[i] == '|' && tag[i+1] == '|') || (tag[i] == '^') || (tag[i] == '!')) { expr->simple = FALSE; break; } } } if (expr->simple) { expr->uid = Tk_GetUid(tag); return TCL_OK; } expr->string = tag; expr->stringIndex = 0; /* Allocate buffer for rewritten tags (after de-escaping) */ if (expr->stringLength >= sizeof(expr->staticRWB)) expr->rewritebuffer = ckalloc(expr->stringLength + 1); if (TagExpr_Scan(expr) != TCL_OK) { TagExpr_Free(expr); return TCL_ERROR; } expr->length = expr->index; return TCL_OK; } /* * Uids for operands in compiled tag expressions. * Initialization is done by GetStaticUids(). */ typedef struct { Tk_Uid andUid; Tk_Uid orUid; Tk_Uid xorUid; Tk_Uid parenUid; Tk_Uid negparenUid; Tk_Uid endparenUid; Tk_Uid tagvalUid; Tk_Uid negtagvalUid; } SearchUids; static Tcl_ThreadDataKey dataKey; /* *---------------------------------------------------------------------- * * GetStaticUids -- * * This procedure is invoked to return a structure filled with * the Uids used when doing tag searching. If it was never before * called in the current thread, it initializes the structure for * that thread (uids are only ever local to one thread [Bug * 1114977]). * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static SearchUids * GetStaticUids() { SearchUids *searchUids = (SearchUids *) Tcl_GetThreadData(&dataKey, sizeof(SearchUids)); if (searchUids->andUid == NULL) { searchUids->andUid = Tk_GetUid("&&"); searchUids->orUid = Tk_GetUid("||"); searchUids->xorUid = Tk_GetUid("^"); searchUids->parenUid = Tk_GetUid("("); searchUids->endparenUid = Tk_GetUid(")"); searchUids->negparenUid = Tk_GetUid("!("); searchUids->tagvalUid = Tk_GetUid("!!"); searchUids->negtagvalUid = Tk_GetUid("!"); } return searchUids; } /* *---------------------------------------------------------------------- * * TagExpr_Scan -- * * This procedure recursively parses a string representation of a * tag expression into an array of Tk_Uids. * * Results: * The return value indicates if the tag expression * was successfully scanned (syntax). * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int TagExpr_Scan( TagExpr *expr /* Info about a tag expression. */ ) { Tcl_Interp *interp = expr->tree->interp; int looking_for_tag; /* When true, scanner expects * next char(s) to be a tag, * else operand expected */ int found_tag; /* One or more tags found */ int found_endquote; /* For quoted tag string parsing */ int negate_result; /* Pending negation of next tag value */ char *tag; /* tag from tag expression string */ SearchUids *searchUids; /* Collection of uids for basic search * expression terms. */ char c; searchUids = GetStaticUids(); negate_result = 0; found_tag = 0; looking_for_tag = 1; while (expr->stringIndex < expr->stringLength) { c = expr->string[expr->stringIndex++]; if (expr->allocated == expr->index) { expr->allocated += 15; if (expr->uids != expr->staticUids) { expr->uids = (Tk_Uid *) ckrealloc((char *)(expr->uids), (expr->allocated)*sizeof(Tk_Uid)); } else { expr->uids = (Tk_Uid *) ckalloc((expr->allocated)*sizeof(Tk_Uid)); memcpy((void*)expr->uids, (const void*)expr->staticUids, sizeof(expr->staticUids)); } } if (looking_for_tag) { switch (c) { case ' ' : /* ignore unquoted whitespace */ case '\t' : case '\n' : case '\r' : break; case '!' : /* negate next tag or subexpr */ if (looking_for_tag > 1) { Tcl_AppendResult(interp, "Too many '!' in tag search expression", (char *) NULL); return TCL_ERROR; } looking_for_tag++; negate_result = 1; break; case '(' : /* scan (negated) subexpr recursively */ if (negate_result) { expr->uids[expr->index++] = searchUids->negparenUid; negate_result = 0; } else { expr->uids[expr->index++] = searchUids->parenUid; } if (TagExpr_Scan(expr) != TCL_OK) { /* Result string should be already set * by nested call to tag_expr_scan() */ return TCL_ERROR; } looking_for_tag = 0; found_tag = 1; break; case '"' : /* quoted tag string */ if (negate_result) { expr->uids[expr->index++] = searchUids->negtagvalUid; negate_result = 0; } else { expr->uids[expr->index++] = searchUids->tagvalUid; } tag = expr->rewritebuffer; found_endquote = 0; while (expr->stringIndex < expr->stringLength) { c = expr->string[expr->stringIndex++]; if (c == '\\') { c = expr->string[expr->stringIndex++]; } if (c == '"') { found_endquote = 1; break; } *tag++ = c; } if (! found_endquote) { Tcl_AppendResult(interp, "Missing endquote in tag search expression", (char *) NULL); return TCL_ERROR; } if (! (tag - expr->rewritebuffer)) { Tcl_AppendResult(interp, "Null quoted tag string in tag search expression", (char *) NULL); return TCL_ERROR; } *tag++ = '\0'; expr->uids[expr->index++] = Tk_GetUid(expr->rewritebuffer); looking_for_tag = 0; found_tag = 1; break; case '&' : /* illegal chars when looking for tag */ case '|' : case '^' : case ')' : Tcl_AppendResult(interp, "Unexpected operator in tag search expression", (char *) NULL); return TCL_ERROR; default : /* unquoted tag string */ if (negate_result) { expr->uids[expr->index++] = searchUids->negtagvalUid; negate_result = 0; } else { expr->uids[expr->index++] = searchUids->tagvalUid; } tag = expr->rewritebuffer; *tag++ = c; /* copy rest of tag, including any embedded whitespace */ while (expr->stringIndex < expr->stringLength) { c = expr->string[expr->stringIndex]; if (c == '!' || c == '&' || c == '|' || c == '^' || c == '(' || c == ')' || c == '"') { break; } *tag++ = c; expr->stringIndex++; } /* remove trailing whitespace */ while (1) { c = *--tag; /* there must have been one non-whitespace char, * so this will terminate */ if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { break; } } *++tag = '\0'; expr->uids[expr->index++] = Tk_GetUid(expr->rewritebuffer); looking_for_tag = 0; found_tag = 1; } } else { /* ! looking_for_tag */ switch (c) { case ' ' : /* ignore whitespace */ case '\t' : case '\n' : case '\r' : break; case '&' : /* AND operator */ c = expr->string[expr->stringIndex++]; if (c != '&') { Tcl_AppendResult(interp, "Singleton '&' in tag search expression", (char *) NULL); return TCL_ERROR; } expr->uids[expr->index++] = searchUids->andUid; looking_for_tag = 1; break; case '|' : /* OR operator */ c = expr->string[expr->stringIndex++]; if (c != '|') { Tcl_AppendResult(interp, "Singleton '|' in tag search expression", (char *) NULL); return TCL_ERROR; } expr->uids[expr->index++] = searchUids->orUid; looking_for_tag = 1; break; case '^' : /* XOR operator */ expr->uids[expr->index++] = searchUids->xorUid; looking_for_tag = 1; break; case ')' : /* end subexpression */ expr->uids[expr->index++] = searchUids->endparenUid; goto breakwhile; default : /* syntax error */ Tcl_AppendResult(interp, "Invalid boolean operator in tag search expression", (char *) NULL); return TCL_ERROR; } } } breakwhile: if (found_tag && ! looking_for_tag) { return TCL_OK; } Tcl_AppendResult(interp, "Missing tag in tag search expression", (char *) NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TagExpr_Eval -- * * This procedure recursively evaluates a compiled tag expression. * * Results: * The return value indicates if the tag expression * successfully matched the tags of the given item. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int _TagExpr_Eval( TagExpr *expr, /* Info about a tag expression. */ TagInfo *tagInfo /* Tags to test. */ ) { int looking_for_tag; /* When true, scanner expects * next char(s) to be a tag, * else operand expected */ int negate_result; /* Pending negation of next tag value */ Tk_Uid uid; Tk_Uid *tagPtr; int count; int result; /* Value of expr so far */ int parendepth; SearchUids *searchUids; /* Collection of uids for basic search * expression terms. */ TagInfo dummy; if (expr->stringLength == 0) /* empty expression (an error?) */ return 0; /* No tags given. */ if (tagInfo == NULL) { dummy.numTags = 0; tagInfo = &dummy; } /* A single tag. */ if (expr->simple) { for (tagPtr = tagInfo->tagPtr, count = tagInfo->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == expr->uid) { return 1; } } return 0; } searchUids = GetStaticUids(); result = 0; /* just to keep the compiler quiet */ negate_result = 0; looking_for_tag = 1; while (expr->index < expr->length) { uid = expr->uids[expr->index++]; if (looking_for_tag) { if (uid == searchUids->tagvalUid) { /* * assert(expr->index < expr->length); */ uid = expr->uids[expr->index++]; result = 0; /* * set result 1 if tag is found in item's tags */ for (tagPtr = tagInfo->tagPtr, count = tagInfo->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == uid) { result = 1; break; } } } else if (uid == searchUids->negtagvalUid) { negate_result = ! negate_result; /* * assert(expr->index < expr->length); */ uid = expr->uids[expr->index++]; result = 0; /* * set result 1 if tag is found in item's tags */ for (tagPtr = tagInfo->tagPtr, count = tagInfo->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == uid) { result = 1; break; } } } else if (uid == searchUids->parenUid) { /* * evaluate subexpressions with recursion */ result = _TagExpr_Eval(expr, tagInfo); } else if (uid == searchUids->negparenUid) { negate_result = ! negate_result; /* * evaluate subexpressions with recursion */ result = _TagExpr_Eval(expr, tagInfo); /* * } else { * assert(0); */ } if (negate_result) { result = ! result; negate_result = 0; } looking_for_tag = 0; } else { /* ! looking_for_tag */ if (((uid == searchUids->andUid) && (!result)) || ((uid == searchUids->orUid) && result)) { /* * short circuit expression evaluation * * if result before && is 0, or result before || is 1, * then the expression is decided and no further * evaluation is needed. */ parendepth = 0; while (expr->index < expr->length) { uid = expr->uids[expr->index++]; if (uid == searchUids->tagvalUid || uid == searchUids->negtagvalUid) { expr->index++; continue; } if (uid == searchUids->parenUid || uid == searchUids->negparenUid) { parendepth++; continue; } if (uid == searchUids->endparenUid) { parendepth--; if (parendepth < 0) { break; } } } return result; } else if (uid == searchUids->xorUid) { /* * if the previous result was 1 * then negate the next result */ negate_result = result; } else if (uid == searchUids->endparenUid) { return result; /* * } else { * assert(0); */ } looking_for_tag = 1; } } /* * assert(! looking_for_tag); */ return result; } int TagExpr_Eval( TagExpr *expr, /* Info about a tag expression. */ TagInfo *tagInfo /* Tags to test. */ ) { expr->index = 0; return _TagExpr_Eval(expr, tagInfo); } /* *---------------------------------------------------------------------- * * TagExpr_Free -- * * This procedure frees the given struct. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TagExpr_Free( TagExpr *expr ) { if (expr->rewritebuffer != expr->staticRWB) ckfree(expr->rewritebuffer); if (expr->uids != expr->staticUids) ckfree((char *) expr->uids); } /* *---------------------------------------------------------------------- * * OptionHax_Remember -- * OptionHax_Forget -- * * These procedures are used to work around a limitation in * the Tk_SavedOption structure: the internal form of a configuration * option cannot be larger than a double. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void OptionHax_Remember( TreeCtrl *tree, char *ptr ) { #ifdef TREECTRL_DEBUG int i; for (i = 0; i < tree->optionHaxCnt; i++) { if (ptr == tree->optionHax[i]) { panic("OptionHax_Remember: ptr is not new"); } } if (tree->optionHaxCnt == sizeof(tree->optionHax) / sizeof(tree->optionHax[0])) panic("OptionHax_Remember: too many options"); #endif tree->optionHax[tree->optionHaxCnt++] = ptr; /*dbwin("OptionHax_Remember %p\n", ptr);*/ } int OptionHax_Forget( TreeCtrl *tree, char *ptr ) { int i; for (i = 0; i < tree->optionHaxCnt; i++) { if (ptr == tree->optionHax[i]) { tree->optionHax[i] = tree->optionHax[--tree->optionHaxCnt]; /*dbwin("OptionHax_Forget %p\n", ptr);*/ return 1; } } return 0; } /* *---------------------------------------------------------------------- * * OptionSpec_Find -- * * Return a pointer to a name Tk_OptionSpec in a table. * * Results: * Returns a pointer or panics. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tk_OptionSpec * OptionSpec_Find( Tk_OptionSpec *optionTable, CONST char *optionName ) { while (optionTable->type != TK_OPTION_END) { if (strcmp(optionTable->optionName, optionName) == 0) return optionTable; optionTable++; } panic("OptionSpec_Find: can't find %s", optionName); return NULL; } /* *---------------------------------------------------------------------- * * PerStateCO_Set -- * PerStateCO_Get -- * PerStateCO_Restore -- * PerStateCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a PerStateInfo record. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ typedef struct PerStateCOClientData { PerStateType *typePtr; StateFromObjProc proc; } PerStateCOClientData; static int PerStateCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { PerStateCOClientData *cd = (PerStateCOClientData *) clientData; TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; PerStateInfo new, *internalPtr, *hax; if (internalOffset >= 0) internalPtr = (PerStateInfo *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { new.obj = (*value); new.data = NULL; new.count = 0; /* Tcl_IncrRefCount((*value));*/ if (PerStateInfo_FromObj(tree, cd->proc, cd->typePtr, &new) != TCL_OK) { /* Tcl_DecrRefCount((*value));*/ return TCL_ERROR; } } if (internalPtr != NULL) { if ((*value) == NULL) { new.obj = NULL; new.data = NULL; new.count = 0; } OptionHax_Remember(tree, saveInternalPtr); if (internalPtr->obj != NULL) { hax = (PerStateInfo *) ckalloc(sizeof(PerStateInfo)); *hax = *internalPtr; *((PerStateInfo **) saveInternalPtr) = hax; } else { *((PerStateInfo **) saveInternalPtr) = NULL; } *internalPtr = new; /*dbwin("PerStateCO_Set %p %s\n", internalPtr, cd->typePtr->name);*/ } return TCL_OK; } static Tcl_Obj * PerStateCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { PerStateInfo *value = (PerStateInfo *) (recordPtr + internalOffset); return value->obj; /* May be NULL. */ } static void PerStateCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; PerStateInfo *psi = (PerStateInfo *) internalPtr; PerStateInfo *hax = *(PerStateInfo **) saveInternalPtr; /*dbwin("PerStateCO_Restore\n");*/ if (hax != NULL) { #ifdef TREECTRL_DEBUG psi->type = hax->type; #endif psi->data = hax->data; psi->count = hax->count; ckfree((char *) hax); } else { #ifdef TREECTRL_DEBUG psi->type = NULL; #endif /* psi->obj = NULL;*/ psi->data = NULL; psi->count = 0; } OptionHax_Forget(tree, saveInternalPtr); } static void PerStateCO_Free( ClientData clientData, /* unused. */ Tk_Window tkwin, /* A window; unused */ char *internalPtr /* Pointer to the place, where the internal * form resides. */ ) { PerStateCOClientData *cd = (PerStateCOClientData *) clientData; TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; PerStateInfo *hax; Tcl_Obj *objPtr = NULL; if (OptionHax_Forget(tree, internalPtr)) { hax = *(PerStateInfo **) internalPtr; if (hax != NULL) { objPtr = hax->obj; PerStateInfo_Free(tree, cd->typePtr, hax); ckfree((char *) hax); } } else { /*dbwin("PerStateCO_Free %p %s\n", internalPtr, cd->typePtr->name);*/ objPtr = ((PerStateInfo *) internalPtr)->obj; PerStateInfo_Free(tree, cd->typePtr, (PerStateInfo *) internalPtr); } /* if (objPtr != NULL) Tcl_DecrRefCount(objPtr);*/ } /* *---------------------------------------------------------------------- * * PerStateCO_Alloc -- * * Allocates a Tk_ObjCustomOption record and clientData. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tk_ObjCustomOption * PerStateCO_Alloc( CONST char *optionName, PerStateType *typePtr, StateFromObjProc proc ) { PerStateCOClientData *cd; Tk_ObjCustomOption *co; /* ClientData for the Tk custom option record */ cd = (PerStateCOClientData *) ckalloc(sizeof(PerStateCOClientData)); cd->typePtr = typePtr; cd->proc = proc; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = (char *) optionName + 1; co->setProc = PerStateCO_Set; co->getProc = PerStateCO_Get; co->restoreProc = PerStateCO_Restore; co->freeProc = PerStateCO_Free; co->clientData = (ClientData) cd; return co; } /* *---------------------------------------------------------------------- * * PerStateCO_Init -- * * Initializes a Tk_OptionSpec.clientData for a custom option. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ int PerStateCO_Init( Tk_OptionSpec *optionTable, CONST char *optionName, PerStateType *typePtr, StateFromObjProc proc ) { Tk_OptionSpec *specPtr; specPtr = OptionSpec_Find(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("PerStateCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; specPtr->clientData = PerStateCO_Alloc(optionName, typePtr, proc); return TCL_OK; } #define DEBUG_DYNAMICxxx static CONST char *DynamicOptionUid = "DynamicOption"; /* *---------------------------------------------------------------------- * * DynamicOption_Find -- * * Returns a pointer to a dynamic-option record or NULL. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ DynamicOption * DynamicOption_Find( DynamicOption *first, /* Head of linked list. */ int id /* Unique id. */ ) { DynamicOption *opt = first; while (opt != NULL) { if (opt->id == id) return opt; opt = opt->next; } return NULL; } /* *---------------------------------------------------------------------- * * DynamicOption_FindData -- * * Returns a pointer to the option-specific data for a * dynamic-option record or NULL. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * DynamicOption_FindData( DynamicOption *first, /* Head of linked list. */ int id /* Unique id. */ ) { DynamicOption *opt = DynamicOption_Find(first, id); if (opt != NULL) return opt->data; return NULL; } /* *---------------------------------------------------------------------- * * DynamicOption_AllocIfNeeded -- * * Returns a pointer to a dynamic-option record. * * Results: * If the dynamic-option record exists, it is returned. Otherwise * a new one is allocated and initialized. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ DynamicOption * DynamicOption_AllocIfNeeded( TreeCtrl *tree, DynamicOption **firstPtr, /* Pointer to the head of linked list. * Will be updated if a new record is * created. */ int id, /* Unique id. */ int size, /* Size of option-specific data. */ DynamicOptionInitProc *init /* Proc to intialized the option-specific * data. May be NULL. */ ) { DynamicOption *opt = *firstPtr; while (opt != NULL) { if (opt->id == id) return opt; opt = opt->next; } #ifdef DEBUG_DYNAMIC dbwin("DynamicOption_AllocIfNeeded allocated id=%d\n", id); #endif #ifdef ALLOC_HAX opt = (DynamicOption *) AllocHax_Alloc(tree->allocData, DynamicOptionUid, Tk_Offset(DynamicOption, data) + size); #else opt = (DynamicOption *) ckalloc(Tk_Offset(DynamicOption, data) + size); #endif opt->id = id; memset(opt->data, '\0', size); if (init != NULL) (*init)(opt->data); opt->next = *firstPtr; *firstPtr = opt; return opt; } /* *---------------------------------------------------------------------- * * DynamicCO_Set -- * DynamicCO_Get -- * DynamicCO_Restore -- * DynamicCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a DynamicOption record. * * A dynamic option is one for which storage is not allocated until * the option is configured for the first time. Dynamic options are * saved in a linked list. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* This is the Tk_OptionSpec.clientData field for a dynamic option. */ typedef struct DynamicCOClientData { int id; /* Unique id. */ int size; /* Size of client data. */ int objOffset; /* Offset in the client data to store the * object representation of the option. * May be < 0. */ int internalOffset; /* Offset in the client data to store the * internal representation of the option. * May be < 0. */ Tk_ObjCustomOption *custom; /* Table of procedures and clientData for * the actual option. */ DynamicOptionInitProc *init;/* This gets called to initialize the client * data when it is first allocated. May be * NULL. */ } DynamicCOClientData; /* This is used to save the current value of an option when a call to * Tk_SetOptions is in progress. */ typedef struct DynamicCOSave { Tcl_Obj *objPtr; /* The object representation of the option. */ double internalForm; /* The internal form of the option. */ } DynamicCOSave; static int DynamicCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; DynamicCOClientData *cd = (DynamicCOClientData *) clientData; DynamicOption **firstPtr, *opt; DynamicCOSave *save; Tcl_Obj **objPtrPtr = NULL; /* Get pointer to the head of the list of dynamic options. */ firstPtr = (DynamicOption **) (recordPtr + internalOffset); /* Get the dynamic option record. Create it if needed, and update the * linked list of dynamic options. */ opt = DynamicOption_AllocIfNeeded(tree, firstPtr, cd->id, cd->size, cd->init); if (cd->objOffset >= 0) objPtrPtr = (Tcl_Obj **) (opt->data + cd->objOffset); save = (DynamicCOSave *) ckalloc(sizeof(DynamicCOSave)); #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Set id=%d saveInternalPtr=%p save=%p\n", cd->id, saveInternalPtr, save); #endif if (objPtrPtr != NULL) { save->objPtr = *objPtrPtr; #ifdef DEBUG_DYNAMIC if (save->objPtr) dbwin(" old object '%s' refCount=%d\n", Tcl_GetString(save->objPtr), save->objPtr->refCount); else dbwin(" old object NULL\n"); #endif } if (cd->custom->setProc(cd->custom->clientData, interp, tkwin, value, opt->data, cd->internalOffset, (char *) &save->internalForm, flags) != TCL_OK) { ckfree((char *) save); return TCL_ERROR; } if (objPtrPtr != NULL) { #ifdef DEBUG_DYNAMIC if (*value) dbwin(" new object '%s' refCount=%d\n", Tcl_GetString(*value), (*value)->refCount); else dbwin(" new object NULL\n"); #endif *objPtrPtr = *value; if (*value != NULL) Tcl_IncrRefCount(*value); } *(DynamicCOSave **) saveInternalPtr = save; OptionHax_Remember(tree, saveInternalPtr); return TCL_OK; } static Tcl_Obj * DynamicCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { DynamicCOClientData *cd = (DynamicCOClientData *) clientData; DynamicOption *first = *(DynamicOption **) (recordPtr + internalOffset); DynamicOption *opt = DynamicOption_Find(first, cd->id); #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Get id=%d opt=%p objOffset=%d\n", cd->id, opt, cd->objOffset); #endif if (opt == NULL) return NULL; if (cd->objOffset >= 0) { #ifdef TREECTRL_DEBUG Tcl_Obj *objPtr = *(Tcl_Obj **) (opt->data + cd->objOffset); if (objPtr && objPtr->refCount == 0) panic("DynamicCO_Get refCount=0"); #endif return *(Tcl_Obj **) (opt->data + cd->objOffset); } if (cd->custom->getProc != NULL) return cd->custom->getProc(cd->custom->clientData, tkwin, opt->data, cd->internalOffset); return NULL; } static void DynamicCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; DynamicCOClientData *cd = (DynamicCOClientData *) clientData; DynamicOption *first = *(DynamicOption **) internalPtr; DynamicOption *opt = DynamicOption_Find(first, cd->id); DynamicCOSave *save = *(DynamicCOSave **)saveInternalPtr; Tcl_Obj **objPtrPtr; if (opt == NULL) panic("DynamicCO_Restore: opt=NULL"); #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Restore id=%d internalOffset=%d save=%p\n", cd->id, cd->internalOffset, save); #endif if (cd->internalOffset >= 0 && cd->custom->restoreProc != NULL) cd->custom->restoreProc(cd->custom->clientData, tkwin, opt->data + cd->internalOffset, (char *) &save->internalForm); if (cd->objOffset >= 0) { objPtrPtr = (Tcl_Obj **) (opt->data + cd->objOffset); #ifdef DEBUG_DYNAMIC if (*objPtrPtr) dbwin("DynamicCO_Restore replace object '%s' refCount=%d\n", Tcl_GetString(*objPtrPtr), (*objPtrPtr)->refCount); else dbwin("DynamicCO_Restore replace object NULL\n"); if (save->objPtr) dbwin("DynamicCO_Restore restore object '%s' refCount=%d\n", Tcl_GetString(save->objPtr), save->objPtr->refCount); else dbwin("DynamicCO_Restore restore object NULL\n"); #endif /* if (*objPtrPtr != NULL) Tcl_DecrRefCount(*objPtrPtr);*/ *objPtrPtr = save->objPtr; } ckfree((char *) save); OptionHax_Forget(tree, saveInternalPtr); } static void DynamicCO_Free( ClientData clientData, Tk_Window tkwin, char *internalPtr ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; DynamicCOClientData *cd = (DynamicCOClientData *) clientData; Tcl_Obj **objPtrPtr; if (OptionHax_Forget(tree, internalPtr)) { DynamicCOSave *save = *(DynamicCOSave **) internalPtr; #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Free id=%d internalPtr=%p save=%p\n", cd->id, internalPtr, save); #endif if (cd->internalOffset >= 0 && cd->custom->freeProc != NULL) cd->custom->freeProc(cd->custom->clientData, tkwin, (char *) &save->internalForm); if (cd->objOffset >= 0) { #ifdef DEBUG_DYNAMIC if (save->objPtr) { dbwin("DynamicCO_Free free object '%s' refCount=%d-1\n", Tcl_GetString(save->objPtr), (save->objPtr)->refCount); if (save->objPtr->refCount == 0) panic("DynamicCO_Free refCount=0"); } else dbwin("DynamicCO_Free free object NULL\n"); #endif if (save->objPtr) { Tcl_DecrRefCount(save->objPtr); } } ckfree((char *) save); } else { DynamicOption *first = *(DynamicOption **) internalPtr; DynamicOption *opt = DynamicOption_Find(first, cd->id); #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Free id=%d internalPtr=%p save=NULL\n", cd->id, internalPtr); #endif if (opt != NULL && cd->internalOffset >= 0 && cd->custom->freeProc != NULL) cd->custom->freeProc(cd->custom->clientData, tkwin, opt->data + cd->internalOffset); if (opt != NULL && cd->objOffset >= 0) { objPtrPtr = (Tcl_Obj **) (opt->data + cd->objOffset); #ifdef DEBUG_DYNAMIC if (*objPtrPtr) { dbwin("DynamicCO_Free free object '%s' refCount=%d-1\n", Tcl_GetString(*objPtrPtr), (*objPtrPtr)->refCount); if ((*objPtrPtr)->refCount == 0) panic("DynamicCO_Free refCount=0"); } else dbwin("DynamicCO_Free free object NULL\n"); #endif if (*objPtrPtr != NULL) { Tcl_DecrRefCount(*objPtrPtr); } } } } /* *---------------------------------------------------------------------- * * DynamicOption_Init -- * * Initialize a Tk_OptionSpec.clientData field before calling * Tk_CreateOptionTable. * * Results: * None. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int DynamicCO_Init( Tk_OptionSpec *optionTable, /* Table to search. */ CONST char *optionName, /* Name of the option. */ int id, /* Unique id. */ int size, /* Size of client data. */ int objOffset, /* Offset in the client data to store the * object representation of the option. * May be < 0. */ int internalOffset, /* Offset in the client data to store the * internal representation of the option. * May be < 0. */ Tk_ObjCustomOption *custom, /* Table of procedures and clientData for * the actual option. */ DynamicOptionInitProc *init /* This gets called to initialize the client * data when it is first allocated. May be * NULL. */ ) { Tk_OptionSpec *specPtr; DynamicCOClientData *cd; Tk_ObjCustomOption *co; if (size <= 0) panic("DynamicCO_Init: option %s size=%d", optionName, size); specPtr = OptionSpec_Find(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("DynamicCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; /* ClientData for the Tk custom option record */ cd = (DynamicCOClientData *) ckalloc(sizeof(DynamicCOClientData)); cd->id = id; cd->size = size; cd->objOffset = objOffset; cd->internalOffset = internalOffset; cd->custom = custom; cd->init = init; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = (char *) optionName + 1; co->setProc = DynamicCO_Set; co->getProc = DynamicCO_Get; co->restoreProc = DynamicCO_Restore; co->freeProc = DynamicCO_Free; co->clientData = (ClientData) cd; /* Update the option table */ specPtr->clientData = co; #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Init id=%d size=%d objOffset=%d internalOffset=%d custom->name=%s\n", id, size, objOffset, internalOffset, custom->name); #endif return TCL_OK; } /* *---------------------------------------------------------------------- * * DynamicOption_Free -- * * Free a linked list of dynamic-option records. This gets called * after Tk_FreeConfigOptions. * * Results: * None. * * Side effects: * Memory may be freed. * *---------------------------------------------------------------------- */ void DynamicOption_Free( TreeCtrl *tree, DynamicOption *first, Tk_OptionSpec *optionTable ) { DynamicOption *opt = first; DynamicCOClientData *cd; Tk_ObjCustomOption *co; int i; while (opt != NULL) { DynamicOption *next = opt->next; for (i = 0; optionTable[i].type != TK_OPTION_END; i++) { if (optionTable[i].type != TK_OPTION_CUSTOM) continue; co = (Tk_ObjCustomOption *) optionTable[i].clientData; if (co->setProc != DynamicCO_Set) continue; cd = (DynamicCOClientData *) co->clientData; if (cd->id != opt->id) continue; #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, DynamicOptionUid, (char *) opt, Tk_Offset(DynamicOption, data) + cd->size); #else ckfree((char *) opt); #endif break; } opt = next; } } /* *---------------------------------------------------------------------- * * DynamicOption_Free1 -- * * Free a single dynamic-option record. This is a big hack so that * dynamic-option records that aren't associated with a Tk_OptionSpec * array can be used. * * Results: * None. * * Side effects: * Memory may be freed. * *---------------------------------------------------------------------- */ void DynamicOption_Free1( TreeCtrl *tree, DynamicOption **firstPtr, int id, int size ) { DynamicOption *opt = *firstPtr, *prev = NULL; while (opt != NULL) { if (opt->id == id) { if (prev == NULL) *firstPtr = opt->next; else prev->next = opt->next; #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, DynamicOptionUid, (char *) opt, Tk_Offset(DynamicOption, data) + size); #else ckfree((char *) opt); #endif return; } prev = opt; opt = opt->next; } } /* *---------------------------------------------------------------------- * * StringCO_Set -- * StringCO_Get -- * StringCO_Restore -- * StringCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is exactly the same as a TK_OPTION_STRING. This is used * when storage for the option is dynamically allocated. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int StringCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **valuePtr, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { int objEmpty; char *internalPtr, *new, *value; int length; if (internalOffset >= 0) internalPtr = (char *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*valuePtr)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*valuePtr) = NULL; if (internalPtr != NULL) { if (*valuePtr != NULL) { value = Tcl_GetStringFromObj(*valuePtr, &length); new = ckalloc((unsigned) (length + 1)); strcpy(new, value); } else { new = NULL; } *((char **) saveInternalPtr) = *((char **) internalPtr); *((char **) internalPtr) = new; } return TCL_OK; } static Tcl_Obj * StringCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { char **internalPtr = (char **) (recordPtr + internalOffset); return Tcl_NewStringObj(*internalPtr, -1); } static void StringCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(char **) internalPtr = *(char **) saveInternalPtr; } static void StringCO_Free( ClientData clientData, Tk_Window tkwin, char *internalPtr ) { if (*((char **) internalPtr) != NULL) { ckfree(*((char **) internalPtr)); *((char **) internalPtr) = NULL; } } Tk_ObjCustomOption stringCO = { "string", StringCO_Set, StringCO_Get, StringCO_Restore, StringCO_Free, (ClientData) NULL }; /* *---------------------------------------------------------------------- * * PixelsCO_Set -- * PixelsCO_Get -- * PixelsCO_Restore -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is exactly the same as a TK_OPTION_PIXELS. This is used * when storage for the option is dynamically allocated. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PixelsCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **valuePtr, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { int objEmpty; int *internalPtr, new; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*valuePtr)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) { (*valuePtr) = NULL; new = 0; } else { if (Tk_GetPixelsFromObj(interp, tkwin, *valuePtr, &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { *((int *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * PixelsCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { int *internalPtr = (int *) (recordPtr + internalOffset); return Tcl_NewIntObj(*internalPtr); } static void PixelsCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(int *) internalPtr = *(int *) saveInternalPtr; } Tk_ObjCustomOption pixelsCO = { "string", PixelsCO_Set, PixelsCO_Get, PixelsCO_Restore, NULL, (ClientData) NULL }; /* *---------------------------------------------------------------------- * * StyleCO_Set -- * StyleCO_Get -- * StyleCO_Restore -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a TreeStyle. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int StyleCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **valuePtr, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; TreeStyle *internalPtr, new; if (internalOffset >= 0) internalPtr = (TreeStyle *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*valuePtr)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) { (*valuePtr) = NULL; new = NULL; } else { if (TreeStyle_FromObj(tree, *valuePtr, &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { *((TreeStyle *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * StyleCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { TreeStyle *internalPtr = (TreeStyle *) (recordPtr + internalOffset); if (*internalPtr == NULL) return NULL; return TreeStyle_ToObj(*internalPtr); } static void StyleCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(TreeStyle *) internalPtr = *(TreeStyle *) saveInternalPtr; } Tk_ObjCustomOption styleCO = { "style", StyleCO_Set, StyleCO_Get, StyleCO_Restore, NULL, (ClientData) NULL }; /* *---------------------------------------------------------------------- * * BooleanFlagCO_Set -- * BooleanFlagCO_Get -- * BooleanFlagCO_Restore -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a boolean value whose internal rep is a single bit of * an int rather than the entire int. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int BooleanFlagCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { int theFlag = (int) clientData; int new, *internalPtr; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; if (Tcl_GetBooleanFromObj(interp, (*value), &new) != TCL_OK) return TCL_ERROR; if (internalPtr != NULL) { *((int *) saveInternalPtr) = *internalPtr; if (new) *internalPtr |= theFlag; else *internalPtr &= ~theFlag; } return TCL_OK; } static Tcl_Obj * BooleanFlagCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { int theFlag = (int) clientData; int value = *(int *) (recordPtr + internalOffset); return Tcl_NewBooleanObj(value & theFlag); } static void BooleanFlagCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { int theFlag = (int) clientData; int value = *(int *) saveInternalPtr; if (value & theFlag) *((int *) internalPtr) |= theFlag; else *((int *) internalPtr) &= ~theFlag; } int BooleanFlagCO_Init( Tk_OptionSpec *optionTable, CONST char *optionName, int theFlag ) { Tk_OptionSpec *specPtr; Tk_ObjCustomOption *co; specPtr = OptionSpec_Find(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("IntegerCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = "boolean"; co->setProc = BooleanFlagCO_Set; co->getProc = BooleanFlagCO_Get; co->restoreProc = BooleanFlagCO_Restore; co->freeProc = NULL; co->clientData = (ClientData) theFlag; specPtr->clientData = co; return TCL_OK; } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeColumn.c0000644000175000017500000046057311044115430025263 0ustar domibeldomibel/* * tkTreeColumn.c -- * * This module implements treectrl widget's columns. * * Copyright (c) 2002-2006 Tim Baker * Copyright (c) 2002-2003 Christian Krone * Copyright (c) 2003 ActiveState Corporation * * RCS: @(#) $Id: tkTreeColumn.c,v 1.4 2008-07-30 16:47:20 barre Exp $ */ #include "tkTreeCtrl.h" typedef struct TreeColumn_ TreeColumn_; #ifdef UNIFORM_GROUP typedef struct UniformGroup { Tcl_HashEntry *hPtr; /* Entry in TreeCtrl.uniformGroupHash */ int refCount; /* Number of columns in this group. */ int minSize; /* Used during layout. */ } UniformGroup; #endif /* * The following structure holds information about a single * column in a TreeCtrl. */ struct TreeColumn_ { Tcl_Obj *textObj; /* -text */ char *text; /* -text */ int width; /* -width */ Tcl_Obj *widthObj; /* -width */ int minWidth; /* -minwidth */ Tcl_Obj *minWidthObj; /* -minwidth */ int maxWidth; /* -maxwidth */ Tcl_Obj *maxWidthObj; /* -maxwidth */ #ifdef DEPRECATED int stepWidth; /* -stepwidth */ Tcl_Obj *stepWidthObj; /* -stepwidth */ int widthHack; /* -widthhack */ #endif /* DEPRECATED */ Tk_Font tkfont; /* -font */ Tk_Justify justify; /* -justify */ PerStateInfo border; /* -background */ Tcl_Obj *borderWidthObj; /* -borderwidth */ int borderWidth; /* -borderwidth */ XColor *textColor; /* -textcolor */ int expand; /* -expand */ int squeeze; /* -squeeze */ int visible; /* -visible */ int resize; /* -resize */ TagInfo *tagInfo; /* -tags */ char *imageString; /* -image */ PerStateInfo arrowBitmap; /* -arrowbitmap */ PerStateInfo arrowImage; /* -arrowimage */ Pixmap bitmap; /* -bitmap */ Tcl_Obj *itemBgObj; /* -itembackground */ TreeStyle itemStyle; /* -itemstyle */ int button; /* -button */ Tcl_Obj *textPadXObj; /* -textpadx */ int *textPadX; /* -textpadx */ Tcl_Obj *textPadYObj; /* -textpady */ int *textPadY; /* -textpady */ Tcl_Obj *imagePadXObj; /* -imagepadx */ int *imagePadX; /* -imagepadx */ Tcl_Obj *imagePadYObj; /* -imagepady */ int *imagePadY; /* -imagepady */ Tcl_Obj *arrowPadXObj; /* -arrowpadx */ int *arrowPadX; /* -arrowpadx */ Tcl_Obj *arrowPadYObj; /* -arrowpady */ int *arrowPadY; /* -arrowpady */ #define ARROW_NONE 0 #define ARROW_UP 1 #define ARROW_DOWN 2 int arrow; /* -arrow */ #define SIDE_LEFT 0 #define SIDE_RIGHT 1 int arrowSide; /* -arrowside */ int arrowGravity; /* -arrowgravity */ #define COLUMN_STATE_NORMAL 0 #define COLUMN_STATE_ACTIVE 1 #define COLUMN_STATE_PRESSED 2 int state; /* -state */ int lock; /* -lock */ TreeCtrl *tree; Tk_OptionTable optionTable; int id; /* unique column identifier */ int index; /* order in list of columns */ int textLen; int textWidth; Tk_Image image; int neededWidth; /* calculated from borders + image/bitmap + * text + arrow */ int neededHeight; /* calculated from borders + image/bitmap + * text */ int offset; /* Total width of preceding columns */ int useWidth; /* -width, -minwidth, or required+expansion */ int widthOfItems; /* width of all TreeItemColumns */ int itemBgCount; XColor **itemBgColor; GC bitmapGC; TreeColumn prev; TreeColumn next; TextLayout textLayout; /* multi-line titles */ int textLayoutWidth; /* width passed to TextLayout_Compute */ int textLayoutInvalid; #define TEXT_WRAP_NULL -1 #define TEXT_WRAP_CHAR 0 #define TEXT_WRAP_WORD 1 int textWrap; /* -textwrap */ int textLines; /* -textlines */ #ifdef UNIFORM_GROUP UniformGroup *uniform; /* -uniform */ int weight; /* -weight */ #endif }; #ifdef UNIFORM_GROUP /* *---------------------------------------------------------------------- * * UniformGroupCO_Set -- * UniformGroupCO_Get -- * UniformGroupCO_Restore -- * UniformGroupCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a UniformGroup. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int UniformGroupCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **valuePtr, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; UniformGroup **internalPtr, *new; if (internalOffset >= 0) internalPtr = (UniformGroup **) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*valuePtr)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*valuePtr) = NULL; if (internalPtr != NULL) { if (*valuePtr != NULL) { int isNew; Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tree->uniformGroupHash, Tcl_GetString(*valuePtr), &isNew); if (isNew) { new = (UniformGroup *) ckalloc(sizeof(UniformGroup)); new->refCount = 0; new->hPtr = hPtr; Tcl_SetHashValue(hPtr, (ClientData) new); } else { new = (UniformGroup *) Tcl_GetHashValue(hPtr); } new->refCount++; #ifdef TREECTRL_DEBUG if (tree->debug.enable) dbwin("UniformGroupCO_Set: %s refCount=%d\n", Tcl_GetString(*valuePtr), new->refCount); #endif } else { new = NULL; } *((UniformGroup **) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * UniformGroupCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; UniformGroup *uniform = *(UniformGroup **) (recordPtr + internalOffset); if (uniform == NULL) return NULL; return Tcl_NewStringObj(Tcl_GetHashKey(&tree->uniformGroupHash, uniform->hPtr), -1); } static void UniformGroupCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(UniformGroup **) internalPtr = *(UniformGroup **) saveInternalPtr; } static void UniformGroupCO_Free( ClientData clientData, Tk_Window tkwin, char *internalPtr ) { UniformGroup *uniform = *(UniformGroup **) internalPtr; #ifdef TREECTRL_DEBUG TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; if (tree->debug.enable && uniform != NULL) { dbwin("UniformGroupCO_Free: %s refCount=%d\n", Tcl_GetHashKey(&tree->uniformGroupHash, uniform->hPtr), uniform->refCount - 1); } #endif if ((uniform != NULL) && (--uniform->refCount <= 0)) { Tcl_DeleteHashEntry(uniform->hPtr); ckfree((char *) uniform); *((UniformGroup **) internalPtr) = NULL; } } Tk_ObjCustomOption uniformGroupCO = { "uniform group", UniformGroupCO_Set, UniformGroupCO_Get, UniformGroupCO_Restore, UniformGroupCO_Free, (ClientData) NULL }; #endif /* UNIFORM_GROUP */ static char *arrowST[] = { "none", "up", "down", (char *) NULL }; static char *arrowSideST[] = { "left", "right", (char *) NULL }; static char *stateST[] = { "normal", "active", "pressed", (char *) NULL }; static CONST84 char *lockST[] = { "left", "none", "right", (char *) NULL }; #define COLU_CONF_IMAGE 0x0001 #define COLU_CONF_NWIDTH 0x0002 /* neededWidth */ #define COLU_CONF_NHEIGHT 0x0004 /* neededHeight */ #define COLU_CONF_TWIDTH 0x0008 /* totalWidth */ #define COLU_CONF_ITEMBG 0x0010 #define COLU_CONF_DISPLAY 0x0040 #define COLU_CONF_JUSTIFY 0x0080 #define COLU_CONF_TAGS 0x0100 #define COLU_CONF_TEXT 0x0200 #define COLU_CONF_BITMAP 0x0400 #define COLU_CONF_RANGES 0x0800 static Tk_OptionSpec columnSpecs[] = { {TK_OPTION_STRING_TABLE, "-arrow", (char *) NULL, (char *) NULL, "none", -1, Tk_Offset(TreeColumn_, arrow), 0, (ClientData) arrowST, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-arrowbitmap", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, arrowBitmap.obj), Tk_Offset(TreeColumn_, arrowBitmap), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_STRING_TABLE, "-arrowgravity", (char *) NULL, (char *) NULL, "left", -1, Tk_Offset(TreeColumn_, arrowGravity), 0, (ClientData) arrowSideST, COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-arrowimage", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, arrowImage.obj), Tk_Offset(TreeColumn_, arrowImage), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-arrowpadx", (char *) NULL, (char *) NULL, "6", Tk_Offset(TreeColumn_, arrowPadXObj), Tk_Offset(TreeColumn_, arrowPadX), 0, (ClientData) &PadAmountOption, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-arrowpady", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeColumn_, arrowPadYObj), Tk_Offset(TreeColumn_, arrowPadY), 0, (ClientData) &PadAmountOption, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, {TK_OPTION_STRING_TABLE, "-arrowside", (char *) NULL, (char *) NULL, "right", -1, Tk_Offset(TreeColumn_, arrowSide), 0, (ClientData) arrowSideST, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, /* NOTE: -background is a per-state option, so DEF_BUTTON_BG_COLOR * must be a list of one element */ {TK_OPTION_CUSTOM, "-background", (char *) NULL, (char *) NULL, (char *) NULL /* initialized later */, Tk_Offset(TreeColumn_, border.obj), Tk_Offset(TreeColumn_, border), 0, (ClientData) NULL, COLU_CONF_DISPLAY}, {TK_OPTION_BITMAP, "-bitmap", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, bitmap), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_BITMAP | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_PIXELS, "-borderwidth", (char *) NULL, (char *) NULL, "2", Tk_Offset(TreeColumn_, borderWidthObj), Tk_Offset(TreeColumn_, borderWidth), 0, (ClientData) NULL, COLU_CONF_TWIDTH | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_BOOLEAN, "-button", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, button), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-expand", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeColumn_, expand), 0, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_FONT, "-font", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, tkfont), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY | COLU_CONF_TEXT}, {TK_OPTION_STRING, "-image", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, imageString), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_IMAGE | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-imagepadx", (char *) NULL, (char *) NULL, "6", Tk_Offset(TreeColumn_, imagePadXObj), Tk_Offset(TreeColumn_, imagePadX), 0, (ClientData) &PadAmountOption, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-imagepady", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeColumn_, imagePadYObj), Tk_Offset(TreeColumn_, imagePadY), 0, (ClientData) &PadAmountOption, COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_STRING, "-itembackground", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, itemBgObj), -1, TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_ITEMBG}, {TK_OPTION_CUSTOM, "-itemstyle", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, itemStyle), TK_OPTION_NULL_OK, (ClientData) &styleCO, 0}, {TK_OPTION_JUSTIFY, "-justify", (char *) NULL, (char *) NULL, "left", -1, Tk_Offset(TreeColumn_, justify), 0, (ClientData) NULL, COLU_CONF_DISPLAY | COLU_CONF_JUSTIFY}, {TK_OPTION_STRING_TABLE, "-lock", (char *) NULL, (char *) NULL, "none", -1, Tk_Offset(TreeColumn_, lock), 0, (ClientData) lockST, 0}, {TK_OPTION_PIXELS, "-maxwidth", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, maxWidthObj), Tk_Offset(TreeColumn_, maxWidth), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_PIXELS, "-minwidth", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, minWidthObj), Tk_Offset(TreeColumn_, minWidth), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_BOOLEAN, "-resize", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, resize), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-squeeze", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeColumn_, squeeze), 0, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL, "normal", -1, Tk_Offset(TreeColumn_, state), 0, (ClientData) stateST, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, #ifdef DEPRECATED {TK_OPTION_PIXELS, "-stepwidth", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, stepWidthObj), Tk_Offset(TreeColumn_, stepWidth), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_RANGES}, #endif /* DEPRECATED */ {TK_OPTION_CUSTOM, "-tags", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, tagInfo), TK_OPTION_NULL_OK, (ClientData) &TagInfoCO, COLU_CONF_TAGS}, {TK_OPTION_STRING, "-text", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, textObj), Tk_Offset(TreeColumn_, text), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TEXT | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_COLOR, "-textcolor", (char *) NULL, (char *) NULL, DEF_BUTTON_FG, -1, Tk_Offset(TreeColumn_, textColor), 0, (ClientData) NULL, COLU_CONF_DISPLAY}, {TK_OPTION_INT, "-textlines", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, textLines), 0, (ClientData) NULL, COLU_CONF_TEXT | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-textpadx", (char *) NULL, (char *) NULL, "6", Tk_Offset(TreeColumn_, textPadXObj), Tk_Offset(TreeColumn_, textPadX), 0, (ClientData) &PadAmountOption, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-textpady", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeColumn_, textPadYObj), Tk_Offset(TreeColumn_, textPadY), 0, (ClientData) &PadAmountOption, COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, #ifdef UNIFORM_GROUP {TK_OPTION_CUSTOM, "-uniform", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, uniform), TK_OPTION_NULL_OK, (ClientData) &uniformGroupCO, COLU_CONF_TWIDTH}, {TK_OPTION_INT, "-weight", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, weight), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TWIDTH}, #endif {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, widthObj), Tk_Offset(TreeColumn_, width), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_BOOLEAN, "-visible", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, visible), 0, (ClientData) NULL, COLU_CONF_TWIDTH | COLU_CONF_DISPLAY}, #ifdef DEPRECATED {TK_OPTION_BOOLEAN, "-widthhack", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeColumn_, widthHack), 0, (ClientData) NULL, COLU_CONF_RANGES}, #endif /* DEPRECATED */ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; #define IS_TAIL(C) ((C) == tree->columnTail) #define IS_ALL(C) (((C) == COLUMN_ALL) || ((C) == COLUMN_NTAIL)) /* *---------------------------------------------------------------------- * * ColumnCO_Set -- * * Tk_ObjCustomOption.setProc(). Converts a Tcl_Obj holding a * column description into a pointer to a Column. * * Results: * A standard Tcl result. * * Side effects: * May store a TreeColumn pointer into the internal representation * pointer. May change the pointer to the Tcl_Obj to NULL to indicate * that the specified string was empty and that is acceptable. * *---------------------------------------------------------------------- */ static int ColumnCO_Set( ClientData clientData, /* CFO_xxx flags to control the conversion. */ Tcl_Interp *interp, /* Current interpreter. */ Tk_Window tkwin, /* Window for which option is being set. */ Tcl_Obj **value, /* Pointer to the pointer to the value object. * We use a pointer to the pointer because * we may need to return a value (NULL). */ char *recordPtr, /* Pointer to storage for the widget record. */ int internalOffset, /* Offset within *recordPtr at which the * internal value is to be stored. */ char *saveInternalPtr, /* Pointer to storage for the old value. */ int flags /* Flags for the option, set Tk_SetOptions. */ ) { int cfoFlags = (int) clientData; TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; TreeColumn new, *internalPtr; if (internalOffset >= 0) internalPtr = (TreeColumn *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (TreeColumn_FromObj(tree, (*value), &new, cfoFlags) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { if ((*value) == NULL) new = NULL; *((TreeColumn *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } /* *---------------------------------------------------------------------- * * ColumnCO_Get -- * * Tk_ObjCustomOption.getProc(). Converts a TreeColumn into a * Tcl_Obj string representation. * * Results: * Tcl_Obj containing the string representation of the column. * Returns NULL if the TreeColumn is NULL. * * Side effects: * May create a new Tcl_Obj. * *---------------------------------------------------------------------- */ static Tcl_Obj * ColumnCO_Get( ClientData clientData, /* Not used. */ Tk_Window tkwin, /* Window for which option is being set. */ char *recordPtr, /* Pointer to widget record. */ int internalOffset /* Offset within *recordPtr containing the * sticky value. */ ) { TreeColumn value = *(TreeColumn *) (recordPtr + internalOffset); TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; if (value == NULL) return NULL; #if 0 if (value == COLUMN_ALL) return Tcl_NewStringObj("all", -1); #endif return TreeColumn_ToObj(tree, value); } /* *---------------------------------------------------------------------- * * ColumnCO_Restore -- * * Tk_ObjCustomOption.restoreProc(). Restores a TreeColumn value * from a saved value. * * Results: * None. * * Side effects: * Restores the old value. * *---------------------------------------------------------------------- */ static void ColumnCO_Restore( ClientData clientData, /* Not used. */ Tk_Window tkwin, /* Not used. */ char *internalPtr, /* Where to store old value. */ char *saveInternalPtr) /* Pointer to old value. */ { *(TreeColumn *) internalPtr = *(TreeColumn *) saveInternalPtr; } /* * The following structure contains pointers to functions used for processing * a custom config option that handles Tcl_Obj<->TreeColumn conversion. * A column description must refer to a single column. */ Tk_ObjCustomOption columnCO = { "column", ColumnCO_Set, ColumnCO_Get, ColumnCO_Restore, NULL, (ClientData) (CFO_NOT_NULL) }; /* * The following structure contains pointers to functions used for processing * a custom config option that handles Tcl_Obj<->TreeColumn conversion. * A column description must refer to a single column. * "tail" is not allowed. */ Tk_ObjCustomOption columnCO_NOT_TAIL = { "column", ColumnCO_Set, ColumnCO_Get, ColumnCO_Restore, NULL, (ClientData) (CFO_NOT_NULL | CFO_NOT_TAIL) }; static Tk_OptionSpec dragSpecs[] = { {TK_OPTION_BOOLEAN, "-enable", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeCtrl, columnDrag.enable), 0, (ClientData) NULL, 0}, {TK_OPTION_INT, "-imagealpha", (char *) NULL, (char *) NULL, "128", -1, Tk_Offset(TreeCtrl, columnDrag.alpha), 0, (ClientData) NULL, 0}, {TK_OPTION_COLOR, "-imagecolor", (char *) NULL, (char *) NULL, "gray75", -1, Tk_Offset(TreeCtrl, columnDrag.color), 0, (ClientData) NULL, 0}, {TK_OPTION_CUSTOM, "-imagecolumn", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeCtrl, columnDrag.column), TK_OPTION_NULL_OK, (ClientData) &columnCO_NOT_TAIL, 0}, {TK_OPTION_PIXELS, "-imageoffset", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeCtrl, columnDrag.offsetObj), Tk_Offset(TreeCtrl, columnDrag.offset), 0, (ClientData) NULL, 0}, {TK_OPTION_COLOR, "-indicatorcolor", (char *) NULL, (char *) NULL, "Black", -1, Tk_Offset(TreeCtrl, columnDrag.indColor), 0, (ClientData) NULL, 0}, {TK_OPTION_CUSTOM, "-indicatorcolumn", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeCtrl, columnDrag.indColumn), TK_OPTION_NULL_OK, (ClientData) &columnCO, 0}, {TK_OPTION_STRING_TABLE, "-indicatorside", (char *) NULL, (char *) NULL, "left", -1, Tk_Offset(TreeCtrl, columnDrag.indSide), 0, (ClientData) arrowSideST, 0}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; /* *---------------------------------------------------------------------- * * ImageChangedProc -- * * This procedure is invoked by the image code whenever the manager * for an image does something that affects the size or contents * of an image displayed in a column header. * * Results: * None. * * Side effects: * Invalidates the size of the column and schedules a redisplay. * *---------------------------------------------------------------------- */ static void ImageChangedProc( ClientData clientData, /* Pointer to Column record. */ int x, int y, /* Upper left pixel (within image) * that must be redisplayed. */ int width, int height, /* Dimensions of area to redisplay * (may be <= 0). */ int imageWidth, int imageHeight /* New dimensions of image. */ ) { /* I would like to know the image was deleted... */ TreeColumn column = clientData; TreeCtrl *tree = column->tree; /* Duplicate the effects of configuring the -image option. */ column->neededWidth = -1; column->neededHeight = -1; tree->headerHeight = -1; tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH | DINFO_DRAW_HEADER); } /* *---------------------------------------------------------------------- * * ColumnStateFromObj -- * * Parses a string object containing "state" or "!state" to a * state bit flag. * This function is passed to PerStateInfo_FromObj(). * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ColumnStateFromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* String object to parse. */ int *stateOff, /* OR'd with state bit if "!state" is * specified. Caller must initialize. */ int *stateOn /* OR'd with state bit if "state" is * specified. Caller must initialize. */ ) { Tcl_Interp *interp = tree->interp; int i, op = STATE_OP_ON, op2, op3, length, state = 0; char ch0, *string; CONST char *stateNames[4] = { "normal", "active", "pressed", "up" }; int states[3]; states[STATE_OP_ON] = 0; states[STATE_OP_OFF] = 0; states[STATE_OP_TOGGLE] = 0; string = Tcl_GetStringFromObj(obj, &length); if (length == 0) goto unknown; ch0 = string[0]; if (ch0 == '!') { op = STATE_OP_OFF; ++string; ch0 = string[0]; } else if (ch0 == '~') { if (1) { FormatResult(interp, "can't specify '~' for this command"); return TCL_ERROR; } op = STATE_OP_TOGGLE; ++string; ch0 = string[0]; } for (i = 0; i < 4; i++) { if ((ch0 == stateNames[i][0]) && !strcmp(string, stateNames[i])) { state = 1L << i; break; } } if (state == 0) goto unknown; if (op == STATE_OP_ON) { op2 = STATE_OP_OFF; op3 = STATE_OP_TOGGLE; } else if (op == STATE_OP_OFF) { op2 = STATE_OP_ON; op3 = STATE_OP_TOGGLE; } else { op2 = STATE_OP_ON; op3 = STATE_OP_OFF; } states[op2] &= ~state; states[op3] &= ~state; states[op] |= state; *stateOn |= states[STATE_OP_ON]; *stateOff |= states[STATE_OP_OFF]; return TCL_OK; unknown: FormatResult(interp, "unknown state \"%s\"", string); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Column_MakeState -- * * Return a bit mask suitable for passing to the PerState_xxx * functions. * * Results: * State flags for the column's current state. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Column_MakeState( TreeColumn column /* Column record. */ ) { int state = 0; if (column->state == COLUMN_STATE_NORMAL) state |= 1L << 0; else if (column->state == COLUMN_STATE_ACTIVE) state |= 1L << 1; else if (column->state == COLUMN_STATE_PRESSED) state |= 1L << 2; if (column->arrow == ARROW_UP) state |= 1L << 3; return state; } /* *---------------------------------------------------------------------- * * TreeColumn_FirstAndLast -- * * Determine the order of two columns and swap them if needed. * * Results: * The return value is the number of columns in the range between * first and last. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_FirstAndLast( TreeColumn *first, /* Column token. */ TreeColumn *last /* Column token. */ ) { int indexFirst, indexLast, index; indexFirst = TreeColumn_Index(*first); indexLast = TreeColumn_Index(*last); if (indexFirst > indexLast) { TreeColumn column = *first; *first = *last; *last = column; index = indexFirst; indexFirst = indexLast; indexLast = index; } return indexLast - indexFirst + 1; } typedef struct Qualifiers { TreeCtrl *tree; int visible; /* 1 for -visible TRUE, 0 for -visible FALSE, -1 for unspecified. */ int states[3]; /* States that must be on or off. */ TagExpr expr; /* Tag expression. */ int exprOK; /* TRUE if expr is valid. */ int lock; /* COLUMN_LOCK_xxx or -1 */ int ntail; /* 1 for !tail, * 0 for unspecified. */ } Qualifiers; /* *---------------------------------------------------------------------- * * Qualifiers_Init -- * * Helper routine for TreeItem_FromObj. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Qualifiers_Init( TreeCtrl *tree, /* Widget info. */ Qualifiers *q /* Out: Initialized qualifiers. */ ) { q->tree = tree; q->visible = -1; q->states[0] = q->states[1] = q->states[2] = 0; q->exprOK = FALSE; q->lock = -1; q->ntail = 0; } /* *---------------------------------------------------------------------- * * Qualifiers_Scan -- * * Helper routine for TreeItem_FromObj. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Qualifiers_Scan( Qualifiers *q, /* Must call Qualifiers_Init first, * and Qualifiers_Free if result is TCL_OK. */ int objc, /* Number of arguments. */ Tcl_Obj **objv, /* Argument values. */ int startIndex, /* First objv[] index to look at. */ int *argsUsed /* Out: number of objv[] used. */ ) { TreeCtrl *tree = q->tree; Tcl_Interp *interp = tree->interp; int qual, j = startIndex; static CONST84 char *qualifiers[] = { "lock", "state", "tag", "visible", "!tail", "!visible", NULL }; enum qualEnum { QUAL_LOCK, QUAL_STATE, QUAL_TAG, QUAL_VISIBLE, QUAL_NOT_TAIL, QUAL_NOT_VISIBLE }; /* Number of arguments used by qualifiers[]. */ static int qualArgs[] = { 2, 2, 2, 1, 1, 1 }; *argsUsed = 0; for (; j < objc; ) { if (Tcl_GetIndexFromObj(NULL, objv[j], qualifiers, NULL, 0, &qual) != TCL_OK) break; if (objc - j < qualArgs[qual]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(objv[j]), "\" qualifier", NULL); goto errorExit; } switch ((enum qualEnum) qual) { case QUAL_LOCK: { if (Tcl_GetIndexFromObj(interp, objv[j + 1], lockST, "lock", 0, &q->lock) != TCL_OK) goto errorExit; break; } case QUAL_STATE: { int i, listObjc; Tcl_Obj **listObjv; if (Tcl_ListObjGetElements(interp, objv[j + 1], &listObjc, &listObjv) != TCL_OK) goto errorExit; q->states[STATE_OP_OFF] = q->states[STATE_OP_ON] = 0; for (i = 0; i < listObjc; i++) { if (ColumnStateFromObj(tree, listObjv[i], &q->states[STATE_OP_OFF], &q->states[STATE_OP_ON]) != TCL_OK) goto errorExit; } break; } case QUAL_TAG: { if (q->exprOK) TagExpr_Free(&q->expr); if (TagExpr_Init(tree, objv[j + 1], &q->expr) != TCL_OK) return TCL_ERROR; q->exprOK = TRUE; break; } case QUAL_VISIBLE: { q->visible = 1; break; } case QUAL_NOT_TAIL: { q->ntail = 1; break; } case QUAL_NOT_VISIBLE: { q->visible = 0; break; } } *argsUsed += qualArgs[qual]; j += qualArgs[qual]; } return TCL_OK; errorExit: if (q->exprOK) TagExpr_Free(&q->expr); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Qualifies -- * * Helper routine for TreeItem_FromObj. * * Results: * Returns TRUE if the item meets the given criteria. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Qualifies( Qualifiers *q, /* Qualifiers to check. */ TreeColumn column /* The column to test. May be NULL. */ ) { /* Note: if the column is NULL it is a "match" because we have run * out of columns to check. */ if (column == NULL) return 1; if ((q->ntail == 1) && (column == column->tree->columnTail)) return 0; if ((q->visible == 1) && !column->visible) return 0; else if ((q->visible == 0) && column->visible) return 0; if (q->states[STATE_OP_OFF] & Column_MakeState(column)) return 0; if ((q->states[STATE_OP_ON] & Column_MakeState(column)) != q->states[STATE_OP_ON]) return 0; if (q->exprOK && !TagExpr_Eval(&q->expr, column->tagInfo)) return 0; if ((q->lock != -1) && (column->lock != q->lock)) return 0; return 1; } /* *---------------------------------------------------------------------- * * Qualifiers_Free -- * * Helper routine for TreeItem_FromObj. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Qualifiers_Free( Qualifiers *q /* Out: Initialized qualifiers. */ ) { if (q->exprOK) TagExpr_Free(&q->expr); } /* *---------------------------------------------------------------------- * * TreeColumnList_FromObj -- * * Parse a Tcl_Obj column description to get a list of columns. * * -- returning a single column -- * ID MODIFIERS * first QUALIFIERS MODIFIERS * end|last QUALIFIERS MODIFIERS * order N QUALIFIERS MODIFIERS * tail * tree * -- returning multiple columns -- * all QUALIFIERS * QUALIFIERS (like "all QUALIFIERS") * list listOfDescs * range first last QUALIFIERS * tag tagExpr QUALIFIERS * TAG-EXPR QUALIFIERS MODIFIERS * * MODIFIERS: * -- returning a single column -- * next QUALIFIERS * prev QUALIFIERS * * QUALIFIERS: * state stateList * tag tagExpr * visible * !visible * !tail * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumnList_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, /* Column description. */ TreeColumnList *columns, /* Uninitialized list. Caller must free * it with TreeColumnList_Free unless the * result of this function is TCL_ERROR. */ int flags /* CFO_xxx flags. */ ) { Tcl_Interp *interp = tree->interp; int i, objc, index, listIndex; Tcl_Obj **objv, *elemPtr; TreeColumn column = NULL; Qualifiers q; int qualArgsTotal; static CONST84 char *indexName[] = { "all", "end", "first", "last", "list", "order", "range", "tail", "tree", (char *) NULL }; enum indexEnum { INDEX_ALL, INDEX_END, INDEX_FIRST, INDEX_LAST, INDEX_LIST, INDEX_ORDER, INDEX_RANGE, INDEX_TAIL, INDEX_TREE } ; /* Number of arguments used by indexName[]. */ static int indexArgs[] = { 1, 1, 1, 1, 2, 2, 3, 1, 1 }; /* Boolean: can indexName[] be followed by 1 or more qualifiers. */ static int indexQual[] = { 1, 0, 1, 1, 0, 1, 1, 0, 0 }; static CONST84 char *modifiers[] = { "next", "prev", (char *) NULL }; enum modEnum { TMOD_NEXT, TMOD_PREV }; /* Number of arguments used by modifiers[]. */ static int modArgs[] = { 1, 1 }; /* Boolean: can modifiers[] be followed by 1 or more qualifiers. */ static int modQual[] = { 1, 1 }; TreeColumnList_Init(tree, columns, 0); Qualifiers_Init(tree, &q); if (Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK) goto badDesc; if (objc == 0) goto badDesc; listIndex = 0; elemPtr = objv[listIndex]; if (Tcl_GetIndexFromObj(NULL, elemPtr, indexName, NULL, 0, &index) == TCL_OK) { if (objc - listIndex < indexArgs[index]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(elemPtr), "\" keyword", NULL); goto errorExit; } qualArgsTotal = 0; if (indexQual[index]) { if (Qualifiers_Scan(&q, objc, objv, listIndex + indexArgs[index], &qualArgsTotal) != TCL_OK) { goto errorExit; } } switch ((enum indexEnum) index) { case INDEX_ALL: { if (qualArgsTotal) { column = tree->columns; while (column != NULL) { if (Qualifies(&q, column)) { TreeColumnList_Append(columns, column); } column = column->next; } if (!(flags & CFO_NOT_TAIL) && Qualifies(&q, tree->columnTail)) { TreeColumnList_Append(columns, tree->columnTail); } column = NULL; } else if (flags & CFO_LIST_ALL) { column = tree->columns; while (column != NULL) { TreeColumnList_Append(columns, column); column = column->next; } if (!(flags & CFO_NOT_TAIL)) TreeColumnList_Append(columns, tree->columnTail); column = NULL; } else if (flags & CFO_NOT_TAIL) { column = COLUMN_NTAIL; } else { column = COLUMN_ALL; } break; } case INDEX_FIRST: { column = tree->columns; while (!Qualifies(&q, column)) column = column->next; break; } case INDEX_END: case INDEX_LAST: { column = tree->columnLast; while (!Qualifies(&q, column)) { column = column->prev; } break; } case INDEX_LIST: { int listObjc; Tcl_Obj **listObjv; int count; if (Tcl_ListObjGetElements(interp, objv[listIndex + 1], &listObjc, &listObjv) != TCL_OK) goto errorExit; for (i = 0; i < listObjc; i++) { TreeColumnList column2s; if (TreeColumnList_FromObj(tree, listObjv[i], &column2s, flags) != TCL_OK) goto errorExit; TreeColumnList_Concat(columns, &column2s); TreeColumnList_Free(&column2s); } /* If any of the column descriptions in the list is "all", then * clear the list of columns and use "all". */ count = TreeColumnList_Count(columns); for (i = 0; i < count; i++) { TreeColumn column = TreeColumnList_Nth(columns, i); if (IS_ALL(column)) break; } if (i < count) { TreeColumnList_Free(columns); if (flags & CFO_NOT_TAIL) column = COLUMN_NTAIL; else column = COLUMN_ALL; } else column = NULL; break; } case INDEX_ORDER: { int order; if (Tcl_GetIntFromObj(NULL, objv[listIndex + 1], &order) != TCL_OK) goto errorExit; column = tree->columns; while (column != NULL) { if (Qualifies(&q, column)) if (order-- <= 0) break; column = column->next; } break; } case INDEX_RANGE: { TreeColumn _first, _last; if (TreeColumn_FromObj(tree, objv[listIndex + 1], &_first, CFO_NOT_NULL) != TCL_OK) goto errorExit; if (TreeColumn_FromObj(tree, objv[listIndex + 2], &_last, CFO_NOT_NULL) != TCL_OK) goto errorExit; (void) TreeColumn_FirstAndLast(&_first, &_last); column = _first; while (1) { if (Qualifies(&q, column)) { TreeColumnList_Append(columns, column); } if (column == _last) break; column = column->next; if (column == NULL) column = tree->columnTail; } column = NULL; break; } case INDEX_TAIL: { column = tree->columnTail; break; } case INDEX_TREE: { column = tree->columnTree; break; } } listIndex += indexArgs[index] + qualArgsTotal; /* No indexName[] was found. */ } else { int gotId = FALSE, id; TagExpr expr; if (tree->columnPrefixLen) { char *end, *t = Tcl_GetString(elemPtr); if (strncmp(t, tree->columnPrefix, tree->columnPrefixLen) == 0) { t += tree->columnPrefixLen; id = strtoul(t, &end, 10); if ((end != t) && (*end == '\0')) gotId = TRUE; } } else if (Tcl_GetIntFromObj(NULL, elemPtr, &id) == TCL_OK) { gotId = TRUE; } if (gotId) { column = tree->columns; while (column) { if (column->id == id) break; column = column->next; } listIndex++; goto gotFirstPart; } /* Try a list of qualifiers. This has the same effect as * "all QUALIFIERS". */ if (Qualifiers_Scan(&q, objc, objv, listIndex, &qualArgsTotal) != TCL_OK) { goto errorExit; } if (qualArgsTotal) { column = tree->columns; while (column != NULL) { if (Qualifies(&q, column)) { TreeColumnList_Append(columns, column); } column = column->next; } if (!(flags & CFO_NOT_TAIL) && Qualifies(&q, tree->columnTail)) { TreeColumnList_Append(columns, tree->columnTail); } column = NULL; listIndex += qualArgsTotal; goto gotFirstPart; } /* Try a tag expression. */ if (objc > 1) { if (Qualifiers_Scan(&q, objc, objv, listIndex + 1, &qualArgsTotal) != TCL_OK) { goto errorExit; } } if (TagExpr_Init(tree, elemPtr, &expr) != TCL_OK) goto errorExit; column = tree->columns; while (column != NULL) { if (TagExpr_Eval(&expr, column->tagInfo) && Qualifies(&q, column)) { TreeColumnList_Append(columns, column); } column = column->next; } if (!(flags & CFO_NOT_TAIL) && TagExpr_Eval(&expr, tree->columnTail->tagInfo) && Qualifies(&q, tree->columnTail)) { TreeColumnList_Append(columns, tree->columnTail); } TagExpr_Free(&expr); column = NULL; listIndex += 1 + qualArgsTotal; } gotFirstPart: /* If 1 column, use it and clear the list. */ if (TreeColumnList_Count(columns) == 1) { column = TreeColumnList_Nth(columns, 0); columns->count = 0; } /* If "all" but only tail column exists, use it. */ if (IS_ALL(column) && (tree->columns == NULL) && !(flags & CFO_NOT_TAIL)) column = tree->columnTail; /* If > 1 column, no modifiers may follow. */ if ((TreeColumnList_Count(columns) > 1) || IS_ALL(column)) { if (listIndex < objc) { Tcl_AppendResult(interp, "unexpected arguments after \"", (char *) NULL); for (i = 0; i < listIndex; i++) { Tcl_AppendResult(interp, Tcl_GetString(objv[i]), (char *) NULL); if (i != listIndex - 1) Tcl_AppendResult(interp, " ", (char *) NULL); } Tcl_AppendResult(interp, "\"", (char *) NULL); goto errorExit; } } /* This means a valid specification was given, but there is no such column */ if ((TreeColumnList_Count(columns) == 0) && (column == NULL)) { if (flags & CFO_NOT_NULL) goto notNull; /* Empty list returned */ goto goodExit; } /* Process any modifiers following the column we matched above. */ for (; listIndex < objc; /* nothing */) { int qualArgsTotal = 0; elemPtr = objv[listIndex]; if (Tcl_GetIndexFromObj(interp, elemPtr, modifiers, "modifier", 0, &index) != TCL_OK) { goto errorExit; } if (objc - listIndex < modArgs[index]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(elemPtr), "\" modifier", NULL); goto errorExit; } if (modQual[index]) { Qualifiers_Free(&q); Qualifiers_Init(tree, &q); if (Qualifiers_Scan(&q, objc, objv, listIndex + modArgs[index], &qualArgsTotal) != TCL_OK) { goto errorExit; } } switch ((enum modEnum) index) { case TMOD_NEXT: { int isTail = IS_TAIL(column); if (isTail) { column = NULL; break; } column = column->next; while (!Qualifies(&q, column)) column = column->next; if (column == NULL) { column = tree->columnTail; if (!Qualifies(&q, column)) column = NULL; } break; } case TMOD_PREV: { int isTail = IS_TAIL(column); if (isTail) column = tree->columnLast; else column = column->prev; while (!Qualifies(&q, column)) column = column->prev; break; } } if ((TreeColumnList_Count(columns) == 0) && (column == NULL)) { if (flags & CFO_NOT_NULL) goto notNull; /* Empty list returned. */ goto goodExit; } listIndex += modArgs[index] + qualArgsTotal; } if ((flags & CFO_NOT_MANY) && (IS_ALL(column) || (TreeColumnList_Count(columns) > 1))) { FormatResult(interp, "can't specify > 1 column for this command"); goto errorExit; } if ((flags & CFO_NOT_NULL) && (TreeColumnList_Count(columns) == 0) && (column == NULL)) { notNull: FormatResult(interp, "column \"%s\" doesn't exist", Tcl_GetString(objPtr)); goto errorExit; } if (TreeColumnList_Count(columns)) { if (flags & (CFO_NOT_TAIL)) { int i; for (i = 0; i < TreeColumnList_Count(columns); i++) { column = TreeColumnList_Nth(columns, i); if ((flags & CFO_NOT_TAIL) && IS_TAIL(column)) goto notTail; } } } else if (IS_ALL(column)) { TreeColumnList_Append(columns, column); } else { if ((flags & CFO_NOT_TAIL) && IS_TAIL(column)) { notTail: FormatResult(interp, "can't specify \"tail\" for this command"); goto errorExit; } TreeColumnList_Append(columns, column); } goodExit: Qualifiers_Free(&q); return TCL_OK; badDesc: FormatResult(interp, "bad column description \"%s\"", Tcl_GetString(objPtr)); goto errorExit; errorExit: Qualifiers_Free(&q); TreeColumnList_Free(columns); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TreeColumn_FromObj -- * * Parse a Tcl_Obj column description to get a single column. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, /* Object to parse to a column. */ TreeColumn *columnPtr, /* Returned column. */ int flags /* CFO_xxx flags */ ) { TreeColumnList columns; if (TreeColumnList_FromObj(tree, objPtr, &columns, flags | CFO_NOT_MANY) != TCL_OK) return TCL_ERROR; /* May be NULL. */ (*columnPtr) = TreeColumnList_Nth(&columns, 0); TreeColumnList_Free(&columns); return TCL_OK; } /* *---------------------------------------------------------------------- * * ColumnForEach_Start -- * * Begin iterating over items. A command might accept two column * descriptions for a range of column, or a single column description * which may itself refer to multiple column. Either column * description could be "all". * * Results: * Returns the first column to iterate over. If an error occurs * then ColumnForEach.error is set to 1. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn ColumnForEach_Start( TreeColumnList *columns, /* List of columns. */ TreeColumnList *column2s, /* List of columns or NULL. */ ColumnForEach *iter /* Returned info, pass to ColumnForEach_Next. */ ) { TreeCtrl *tree = columns->tree; TreeColumn column, column2 = NULL; column = TreeColumnList_Nth(columns, 0); if (column2s) column2 = TreeColumnList_Nth(column2s, 0); iter->tree = tree; iter->all = FALSE; iter->ntail = FALSE; iter->error = 0; iter->list = NULL; if (IS_ALL(column) || IS_ALL(column2)) { iter->all = TRUE; iter->ntail = (column == COLUMN_NTAIL) || (column2 == COLUMN_NTAIL); if (tree->columns == NULL) return iter->current = iter->ntail ? NULL : tree->columnTail; iter->next = TreeColumn_Next(tree->columns); return iter->current = tree->columns; } if (column2 != NULL) { if (TreeColumn_FirstAndLast(&column, &column2) == 0) { iter->error = 1; return NULL; } iter->next = TreeColumn_Next(column); iter->last = column2; return iter->current = column; } iter->list = columns; iter->index = 0; return iter->current = column; } /* *---------------------------------------------------------------------- * * ColumnForEach_Next -- * * Returns the next column to iterate over. Keep calling this until * the result is NULL. * * Results: * Returns the next column to iterate over or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn ColumnForEach_Next( ColumnForEach *iter /* Initialized by ColumnForEach_Start. */ ) { TreeCtrl *tree = iter->tree; TreeColumn column; if (iter->all) { if (iter->current == tree->columnTail) return iter->current = NULL; column = iter->next; if (column == NULL) return iter->current = iter->ntail ? NULL : tree->columnTail; iter->next = TreeColumn_Next(column); return iter->current = column; } if (iter->list != NULL) { if (iter->index >= TreeColumnList_Count(iter->list)) return iter->current = NULL; return iter->current = TreeColumnList_Nth(iter->list, ++iter->index); } if (iter->current == iter->last) return iter->current = NULL; column = iter->next; iter->next = TreeColumn_Next(column); return iter->current = column; } /* *---------------------------------------------------------------------- * * TreeColumn_ToObj -- * * Return a Tcl_Obj representing a column. * * Results: * A Tcl_Obj. * * Side effects: * Allocates a Tcl_Obj. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeColumn_ToObj( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column token to get Tcl_Obj for. */ ) { if (column == tree->columnTail) return Tcl_NewStringObj("tail", -1); if (tree->columnPrefixLen) { char buf[100 + TCL_INTEGER_SPACE]; (void) sprintf(buf, "%s%d", tree->columnPrefix, column->id); return Tcl_NewStringObj(buf, -1); } return Tcl_NewIntObj(column->id); } /* *---------------------------------------------------------------------- * * Tree_FindColumn -- * * Get the N'th column in a TreeCtrl. * * Results: * Token for the N'th column. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn Tree_FindColumn( TreeCtrl *tree, /* Widget info. */ int columnIndex /* 0-based index of the column to return. */ ) { TreeColumn column = tree->columns; while (column != NULL) { if (column->index == columnIndex) break; column = column->next; } return column; } /* *---------------------------------------------------------------------- * * TreeColumn_Next -- * * Return the column to the right of the given one. * * Results: * Token for the next column. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn TreeColumn_Next( TreeColumn column /* Column token. */ ) { return column->next; } /* *---------------------------------------------------------------------- * * TreeColumn_Prev -- * * Return the column to the left of the given one. * * Results: * Token for the previous column. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn TreeColumn_Prev( TreeColumn column /* Column token. */ ) { return column->prev; } /* *---------------------------------------------------------------------- * * Column_FreeColors -- * * Frees an array of XColors. This is used to free the -itembackground * array of colors. * * Results: * None. * * Side effects: * Memory is deallocated, colors are freed. * *---------------------------------------------------------------------- */ static void Column_FreeColors( XColor **colors, /* Array of colors. May be NULL. */ int count /* Number of colors. */ ) { int i; if (colors == NULL) { return; } for (i = 0; i < count; i++) { if (colors[i] != NULL) { Tk_FreeColor(colors[i]); } } WCFREE(colors, XColor *, count); } /* *---------------------------------------------------------------------- * * Column_Move -- * * Move a column before another. * * Results: * If the column is moved, then the list of item-columns for every item * is rearranged and the treectrl option -defaultstyles is rearranged. * Whether the column is moved or not, the .index field of every * column is recalculated. * * Side effects: * A redisplay is scheduled if the moved column is visible. * *---------------------------------------------------------------------- */ static void Column_Move( TreeColumn move, /* Column to move. */ TreeColumn before /* Column to place 'move' in front of. * May be the same as 'move'. */ ) { TreeCtrl *tree = move->tree; TreeColumn column, prev, next, last; Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeItem item; int index, numStyles; if (move == before) goto renumber; if (move->index == before->index - 1) goto renumber; /* Move the column in every item */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_MoveColumn(tree, item, move->index, before->index); hPtr = Tcl_NextHashEntry(&search); } /* Indicate that all items must recalculate their list of spans. */ TreeItem_SpansInvalidate(tree, NULL); #ifdef DEPRECATED /* Re-order -defaultstyle */ numStyles = tree->defaultStyle.numStyles; if ((numStyles > 0) && ((before->index < numStyles) || (move->index < numStyles))) { TreeStyle style, *styles; int i, j; Tcl_Obj *staticObjv[STATIC_SIZE], **objv = staticObjv; /* Case 1: move existing */ if ((before->index <= numStyles) && (move->index < numStyles)) { styles = tree->defaultStyle.styles; style = styles[move->index]; for (i = move->index; i < numStyles - 1; i++) styles[i] = styles[i + 1]; j = before->index; if (move->index < before->index) j--; for (i = numStyles - 1; i > j; i--) styles[i] = styles[i - 1]; styles[j] = style; /* Case 2: insert empty between existing */ } else if (before->index < numStyles) { numStyles++; styles = (TreeStyle *) ckalloc(numStyles * sizeof(TreeStyle)); for (i = 0; i < before->index; i++) styles[i] = tree->defaultStyle.styles[i]; styles[i++] = NULL; for (; i < numStyles; i++) styles[i] = tree->defaultStyle.styles[i - 1]; /* Case 3: move existing past end */ } else { numStyles += before->index - numStyles; styles = (TreeStyle *) ckalloc(numStyles * sizeof(TreeStyle)); style = tree->defaultStyle.styles[move->index]; for (i = 0; i < move->index; i++) styles[i] = tree->defaultStyle.styles[i]; for (; i < tree->defaultStyle.numStyles - 1; i++) styles[i] = tree->defaultStyle.styles[i + 1]; for (; i < numStyles - 1; i++) styles[i] = NULL; styles[i] = style; } Tcl_DecrRefCount(tree->defaultStyle.stylesObj); STATIC_ALLOC(objv, Tcl_Obj *, numStyles); for (i = 0; i < numStyles; i++) { if (styles[i] != NULL) objv[i] = TreeStyle_ToObj(styles[i]); else objv[i] = Tcl_NewObj(); } tree->defaultStyle.stylesObj = Tcl_NewListObj(numStyles, objv); Tcl_IncrRefCount(tree->defaultStyle.stylesObj); STATIC_FREE(objv, Tcl_Obj *, numStyles); if (styles != tree->defaultStyle.styles) { ckfree((char *) tree->defaultStyle.styles); tree->defaultStyle.styles = styles; tree->defaultStyle.numStyles = numStyles; } } #endif /* DEPRECATED */ /* Unlink. */ prev = move->prev; next = move->next; if (prev == NULL) tree->columns = next; else prev->next = next; if (next == NULL) tree->columnLast = prev; else next->prev = prev; /* Link. */ if (before == tree->columnTail) { last = tree->columnLast; last->next = move; move->prev = last; move->next = NULL; tree->columnLast = move; } else { prev = before->prev; if (prev == NULL) tree->columns = move; else prev->next = move; before->prev = move; move->prev = prev; move->next = before; } /* Renumber columns */ renumber: tree->columnLockLeft = NULL; tree->columnLockNone = NULL; tree->columnLockRight = NULL; index = 0; column = tree->columns; while (column != NULL) { column->index = index++; if (column->lock == COLUMN_LOCK_LEFT && tree->columnLockLeft == NULL) tree->columnLockLeft = column; if (column->lock == COLUMN_LOCK_NONE && tree->columnLockNone == NULL) tree->columnLockNone = column; if (column->lock == COLUMN_LOCK_RIGHT && tree->columnLockRight == NULL) tree->columnLockRight = column; column = column->next; } if (move->visible) { /* Must update column widths because of expansion. */ /* Also update columnTreeLeft. */ tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH | DINFO_INVALIDATE | DINFO_OUT_OF_DATE); /* BUG 784245 */ Tree_DInfoChanged(tree, DINFO_DRAW_HEADER); } } /* *---------------------------------------------------------------------- * * Column_Config -- * * This procedure is called to process an objc/objv list to set * configuration options for a Column. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then an error message is left in interp's result. * * Side effects: * Configuration information, such as text string, colors, font, * etc. get set for column; old resources get freed, if there * were any. Display changes may occur. * *---------------------------------------------------------------------- */ static int Column_Config( TreeColumn column, /* Column record. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[], /* Argument values. */ int createFlag /* TRUE if the Column is being created. */ ) { TreeCtrl *tree = column->tree; TreeColumn_ saved; TreeColumn walk; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int mask, maskFree = 0; XGCValues gcValues; unsigned long gcMask; /* int stateOld = Column_MakeState(column), stateNew;*/ int visible = column->visible; int lock = column->lock; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) column, column->optionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* Wouldn't have to do this if Tk_InitOptions() would return * a mask of configured options like Tk_SetOptions() does. */ if (createFlag) { if (column->imageString != NULL) mask |= COLU_CONF_IMAGE; if (column->itemBgObj != NULL) mask |= COLU_CONF_ITEMBG; } /* * Step 1: Save old values */ if (mask & COLU_CONF_IMAGE) saved.image = column->image; if (mask & COLU_CONF_ITEMBG) { saved.itemBgColor = column->itemBgColor; saved.itemBgCount = column->itemBgCount; } if (column == tree->columnTail) { if (column->itemStyle != NULL) { FormatResult(tree->interp, "can't change the -itemstyle option of the tail column"); continue; } if (column->lock != COLUMN_LOCK_NONE) { FormatResult(tree->interp, "can't change the -lock option of the tail column"); continue; } } /* * Step 2: Process new values */ if (mask & COLU_CONF_IMAGE) { if (column->imageString == NULL) { column->image = NULL; } else { column->image = Tk_GetImage(tree->interp, tree->tkwin, column->imageString, ImageChangedProc, (ClientData) column); if (column->image == NULL) continue; maskFree |= COLU_CONF_IMAGE; } } if (mask & COLU_CONF_ITEMBG) { if (column->itemBgObj == NULL) { column->itemBgColor = NULL; column->itemBgCount = 0; } else { int i, length, listObjc; Tcl_Obj **listObjv; XColor **colors; if (Tcl_ListObjGetElements(tree->interp, column->itemBgObj, &listObjc, &listObjv) != TCL_OK) continue; colors = (XColor **) ckalloc(sizeof(XColor *) * listObjc); for (i = 0; i < listObjc; i++) colors[i] = NULL; for (i = 0; i < listObjc; i++) { /* Can specify "" for tree background */ (void) Tcl_GetStringFromObj(listObjv[i], &length); if (length != 0) { colors[i] = Tk_AllocColorFromObj(tree->interp, tree->tkwin, listObjv[i]); if (colors[i] == NULL) break; } } if (i < listObjc) { Column_FreeColors(colors, listObjc); continue; } column->itemBgColor = colors; column->itemBgCount = listObjc; maskFree |= COLU_CONF_ITEMBG; } } /* * Step 3: Free saved values */ if (mask & COLU_CONF_IMAGE) { if (saved.image != NULL) Tk_FreeImage(saved.image); } if (mask & COLU_CONF_ITEMBG) Column_FreeColors(saved.itemBgColor, saved.itemBgCount); Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* * Free new values. */ if (maskFree & COLU_CONF_IMAGE) Tk_FreeImage(column->image); if (maskFree & COLU_CONF_ITEMBG) Column_FreeColors(column->itemBgColor, column->itemBgCount); /* * Restore old values. */ if (mask & COLU_CONF_IMAGE) column->image = saved.image; if (mask & COLU_CONF_ITEMBG) { column->itemBgColor = saved.itemBgColor; column->itemBgCount = saved.itemBgCount; } Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } /* Indicate that all items must recalculate their list of spans. */ if (visible != column->visible || lock != column->lock) TreeItem_SpansInvalidate(tree, NULL); /* Wouldn't have to do this if Tk_InitOptions() would return * a mask of configured options like Tk_SetOptions() does. */ if (createFlag) { if (column->textObj != NULL) mask |= COLU_CONF_TEXT; if (column->bitmap != None) mask |= COLU_CONF_BITMAP; } if (mask & COLU_CONF_TEXT) { if (column->textObj != NULL) (void) Tcl_GetStringFromObj(column->textObj, &column->textLen); else column->textLen = 0; if (column->textLen) { Tk_Font tkfont = column->tkfont ? column->tkfont : tree->tkfont; column->textWidth = Tk_TextWidth(tkfont, column->text, column->textLen); } else column->textWidth = 0; } if (mask & COLU_CONF_BITMAP) { if (column->bitmapGC != None) { Tk_FreeGC(tree->display, column->bitmapGC); column->bitmapGC = None; } if (column->bitmap != None) { gcValues.clip_mask = column->bitmap; gcValues.graphics_exposures = False; gcMask = GCClipMask | GCGraphicsExposures; column->bitmapGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } } if (mask & COLU_CONF_ITEMBG) { if (!createFlag) { /* Set max -itembackground */ tree->columnBgCnt = 0; walk = tree->columns; while (walk != NULL) { if (walk->visible) { if (walk->itemBgCount > tree->columnBgCnt) tree->columnBgCnt = walk->itemBgCount; } walk = walk->next; } } Tree_DInfoChanged(tree, DINFO_INVALIDATE | DINFO_OUT_OF_DATE); } if (!createFlag && (column->lock != lock)) { TreeColumn before = NULL; switch (column->lock) { case COLUMN_LOCK_LEFT: before = tree->columnLockNone; if (before == NULL) before = tree->columnLockRight; break; case COLUMN_LOCK_NONE: if (lock == COLUMN_LOCK_LEFT) { before = tree->columnLockNone; if (before == NULL) before = tree->columnLockRight; } else before = tree->columnLockRight; break; case COLUMN_LOCK_RIGHT: before = NULL; break; } if (before == NULL) before = tree->columnTail; Column_Move(column, before); Tree_DInfoChanged(tree, DINFO_REDO_COLUMN_WIDTH); } if (mask & (COLU_CONF_NWIDTH | COLU_CONF_TWIDTH)) mask |= COLU_CONF_NHEIGHT; if (mask & (COLU_CONF_JUSTIFY | COLU_CONF_TEXT)) column->textLayoutInvalid = TRUE; if (mask & COLU_CONF_NWIDTH) column->neededWidth = -1; if (mask & COLU_CONF_NHEIGHT) { column->neededHeight = -1; tree->headerHeight = -1; } /* FIXME: only this column needs to be redisplayed. */ if (mask & COLU_CONF_JUSTIFY) Tree_DInfoChanged(tree, DINFO_INVALIDATE | DINFO_OUT_OF_DATE); /* -stepwidth and -widthhack */ if (mask & COLU_CONF_RANGES) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); /* If one column becomes visible and another of equal width becomes * hidden, and the two columns swap places with each other, then * display ranges are unaffected but items must be redrawn. */ if (visible != column->visible) Tree_DInfoChanged(tree, DINFO_INVALIDATE | DINFO_OUT_OF_DATE); /* Redraw everything */ if (mask & (COLU_CONF_TWIDTH | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT)) { tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH | DINFO_DRAW_HEADER); } /* Redraw header only */ else if (mask & COLU_CONF_DISPLAY) { Tree_DInfoChanged(tree, DINFO_DRAW_HEADER); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Column_Alloc -- * * Allocate and initialize a new Column record. * * Results: * Pointer to the new Column, or NULL if errors occurred. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static TreeColumn Column_Alloc( TreeCtrl *tree /* Widget info. */ ) { TreeColumn column; column = (TreeColumn) ckalloc(sizeof(TreeColumn_)); memset(column, '\0', sizeof(TreeColumn_)); column->tree = tree; column->optionTable = Tk_CreateOptionTable(tree->interp, columnSpecs); if (Tk_InitOptions(tree->interp, (char *) column, column->optionTable, tree->tkwin) != TCL_OK) { WFREE(column, TreeColumn_); return NULL; } #if 0 if (Tk_SetOptions(header->tree->interp, (char *) column, column->optionTable, 0, NULL, header->tree->tkwin, &savedOptions, (int *) NULL) != TCL_OK) { WFREE(column, TreeColumn_); return NULL; } #endif column->neededWidth = column->neededHeight = -1; tree->headerHeight = tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; column->id = tree->nextColumnId++; tree->columnCount++; return column; } /* *---------------------------------------------------------------------- * * Column_Free -- * * Free a Column. * * Results: * Pointer to the next column. * * Side effects: * Memory is deallocated. If this is the last column being * deleted, the TreeCtrl.nextColumnId field is reset to zero. * *---------------------------------------------------------------------- */ static TreeColumn Column_Free( TreeColumn column /* Column record. */ ) { TreeCtrl *tree = column->tree; TreeColumn next = column->next; Column_FreeColors(column->itemBgColor, column->itemBgCount); if (column->bitmapGC != None) Tk_FreeGC(tree->display, column->bitmapGC); if (column->image != NULL) Tk_FreeImage(column->image); if (column->textLayout != NULL) TextLayout_Free(column->textLayout); Tk_FreeConfigOptions((char *) column, column->optionTable, tree->tkwin); WFREE(column, TreeColumn_); tree->columnCount--; if (tree->columnCount == 0) tree->nextColumnId = 0; return next; } /* *---------------------------------------------------------------------- * * TreeColumn_FixedWidth -- * * Return the value of the -width option. * * Results: * The pixel width or -1 if the -width option is unspecified. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_FixedWidth( TreeColumn column /* Column token. */ ) { return column->widthObj ? column->width : -1; } /* *---------------------------------------------------------------------- * * TreeColumn_MinWidth -- * * Return the value of the -minwidth option. * * Results: * The pixel width or -1 if the -minwidth option is unspecified. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_MinWidth( TreeColumn column /* Column token. */ ) { return column->minWidthObj ? column->minWidth : -1; } /* *---------------------------------------------------------------------- * * TreeColumn_MaxWidth -- * * Return the value of the -maxwidth option. * * Results: * The pixel width or -1 if the -maxwidth option is unspecified. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_MaxWidth( TreeColumn column /* Column token. */ ) { return column->maxWidthObj ? column->maxWidth : -1; } #ifdef DEPRECATED /* *---------------------------------------------------------------------- * * TreeColumn_StepWidth -- * * Return the value of the -stepwidth option. * NOTE: -stepwidth is deprecated. * * Results: * The pixel width or -1 if the -stepwidth option is unspecified. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_StepWidth( TreeColumn column /* Column token. */ ) { return column->stepWidthObj ? column->stepWidth : -1; } #endif /* DEPRECATED */ /* *---------------------------------------------------------------------- * * Column_UpdateTextLayout -- * * Recalculate the TextLayout for the text displayed in the * column header. The old TextLayout (if any) is freed. If * there is no text or if it is only one line then no TextLayout * is created. * * Results: * None. * * Side effects: * Memory may be allocated/deallocated. * *---------------------------------------------------------------------- */ static void Column_UpdateTextLayout( TreeColumn column, /* Column record. */ int width /* Maximum line length. Zero means there * is no limit. */ ) { Tk_Font tkfont; char *text = column->text; int textLen = column->textLen; int justify = column->justify; int maxLines = MAX(column->textLines, 0); /* -textlines */ int wrap = TEXT_WRAP_WORD; /* -textwrap */ int flags = 0; int i, multiLine = FALSE; if (column->textLayout != NULL) { TextLayout_Free(column->textLayout); column->textLayout = NULL; } if ((text == NULL) || (textLen == 0)) return; for (i = 0; i < textLen; i++) { if ((text[i] == '\n') || (text[i] == '\r')) { multiLine = TRUE; break; } } #ifdef MAC_OSX_TK /* The height of the header is fixed on Aqua. There is only room for * a single line of text. */ if (column->tree->useTheme) maxLines = 1; #endif if (!multiLine && ((maxLines == 1) || (!width || (width >= column->textWidth)))) return; tkfont = column->tkfont ? column->tkfont : column->tree->tkfont; if (wrap == TEXT_WRAP_WORD) flags |= TK_WHOLE_WORDS; column->textLayout = TextLayout_Compute(tkfont, text, Tcl_NumUtfChars(text, textLen), width, justify, maxLines, flags); } /* *---------------------------------------------------------------------- * * Column_GetArrowSize -- * * Return the size of the sort arrow displayed in the column header * for the column's current state. * * Results: * Height and width of the arrow. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Column_GetArrowSize( TreeColumn column, /* Column record. */ int *widthPtr, /* Returned width. */ int *heightPtr /* Returned height. */ ) { TreeCtrl *tree = column->tree; int state = Column_MakeState(column); int arrowWidth = -1, arrowHeight; Tk_Image image; Pixmap bitmap; /* image > bitmap > theme > draw */ image = PerStateImage_ForState(tree, &column->arrowImage, state, NULL); if (image != NULL) { Tk_SizeOfImage(image, &arrowWidth, &arrowHeight); } if (arrowWidth == -1) { bitmap = PerStateBitmap_ForState(tree, &column->arrowBitmap, state, NULL); if (bitmap != None) { Tk_SizeOfBitmap(tree->display, bitmap, &arrowWidth, &arrowHeight); } } if ((arrowWidth == -1) && tree->useTheme && TreeTheme_GetArrowSize(tree, Tk_WindowId(tree->tkwin), column->arrow == ARROW_UP, &arrowWidth, &arrowHeight) == TCL_OK) { } if (arrowWidth == -1) { Tk_Font tkfont = column->tkfont ? column->tkfont : tree->tkfont; Tk_FontMetrics fm; Tk_GetFontMetrics(tkfont, &fm); arrowWidth = (fm.linespace + column->textPadY[PAD_TOP_LEFT] + column->textPadY[PAD_BOTTOM_RIGHT] + column->borderWidth * 2) / 2; if (!(arrowWidth & 1)) arrowWidth--; arrowHeight = arrowWidth; } (*widthPtr) = arrowWidth; (*heightPtr) = arrowHeight; } /* * The following structure holds size/position info for all the graphical * elements of a column header. */ struct Layout { Tk_Font tkfont; Tk_FontMetrics fm; int width; /* Provided by caller */ int height; /* Provided by caller */ int textLeft; int textWidth; int bytesThatFit; int imageLeft; int imageWidth; int arrowLeft; int arrowWidth; int arrowHeight; }; /* * The following structure is used by the Column_DoLayout() procedure to * hold size/position info for each graphical element displayed in the * header. */ struct LayoutPart { int padX[2]; int padY[2]; int width; int height; int left; int top; }; /* *---------------------------------------------------------------------- * * Column_DoLayout -- * * Arrange all the graphical elements making up a column header. * * Results: * Layout info is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Column_DoLayout( TreeColumn column, /* Column record. */ struct Layout *layout /* Returned layout info. The width and * height fields must be initialized. */ ) { #if defined(MAC_OSX_TK) TreeCtrl *tree = column->tree; #endif struct LayoutPart *parts[3]; struct LayoutPart partArrow, partImage, partText; int i, padList[4], widthList[3], n = 0; int iArrow = -1, iImage = -1, iText = -1; int left, right; int widthForText = 0; #if defined(MAC_OSX_TK) int margins[4]; int arrow = column->arrow; int arrowSide = column->arrowSide; int arrowGravity = column->arrowGravity; #endif #if defined(MAC_OSX_TK) /* Under Aqua, we let the Appearance Manager draw the sort arrow */ if (tree->useTheme) { column->arrow = ARROW_NONE; column->arrowSide = SIDE_RIGHT; column->arrowGravity = SIDE_RIGHT; } #endif if (column->arrow != ARROW_NONE) { Column_GetArrowSize(column, &partArrow.width, &partArrow.height); partArrow.padX[PAD_TOP_LEFT] = column->arrowPadX[PAD_TOP_LEFT]; partArrow.padX[PAD_BOTTOM_RIGHT] = column->arrowPadX[PAD_BOTTOM_RIGHT]; partArrow.padY[PAD_TOP_LEFT] = column->arrowPadY[PAD_TOP_LEFT]; partArrow.padY[PAD_BOTTOM_RIGHT] = column->arrowPadY[PAD_BOTTOM_RIGHT]; } if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_LEFT)) { parts[n] = &partArrow; padList[n] = partArrow.padX[PAD_TOP_LEFT]; padList[n + 1] = partArrow.padX[PAD_BOTTOM_RIGHT]; iArrow = n++; } if ((column->image != NULL) || (column->bitmap != None)) { if (column->image != NULL) Tk_SizeOfImage(column->image, &partImage.width, &partImage.height); else Tk_SizeOfBitmap(column->tree->display, column->bitmap, &partImage.width, &partImage.height); partImage.padX[PAD_TOP_LEFT] = column->imagePadX[PAD_TOP_LEFT]; partImage.padX[PAD_BOTTOM_RIGHT] = column->imagePadX[PAD_BOTTOM_RIGHT]; partImage.padY[PAD_TOP_LEFT] = column->imagePadY[PAD_TOP_LEFT]; partImage.padY[PAD_BOTTOM_RIGHT] = column->imagePadY[PAD_BOTTOM_RIGHT]; parts[n] = &partImage; padList[n] = MAX(partImage.padX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = partImage.padX[PAD_BOTTOM_RIGHT]; iImage = n++; } if (column->textLen > 0) { struct LayoutPart *parts2[3]; int n2 = 0; partText.padX[PAD_TOP_LEFT] = column->textPadX[PAD_TOP_LEFT]; partText.padX[PAD_BOTTOM_RIGHT] = column->textPadX[PAD_BOTTOM_RIGHT]; partText.padY[PAD_TOP_LEFT] = column->textPadY[PAD_TOP_LEFT]; partText.padY[PAD_BOTTOM_RIGHT] = column->textPadY[PAD_BOTTOM_RIGHT]; /* Calculate space for the text */ if (iArrow != -1) parts2[n2++] = &partArrow; if (iImage != -1) parts2[n2++] = &partImage; parts2[n2++] = &partText; if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_RIGHT)) parts2[n2++] = &partArrow; widthForText = layout->width; for (i = 0; i < n2; i++) { if (i) widthForText -= MAX(parts2[i]->padX[0], parts2[i-1]->padX[1]); else widthForText -= parts2[i]->padX[0]; if (parts2[i] != &partText) widthForText -= parts2[i]->width; } widthForText -= parts2[n2-1]->padX[1]; } layout->bytesThatFit = 0; if (widthForText > 0) { if (column->textLayoutInvalid || (column->textLayoutWidth != widthForText)) { Column_UpdateTextLayout(column, widthForText); column->textLayoutInvalid = FALSE; column->textLayoutWidth = widthForText; } if (column->textLayout != NULL) { TextLayout_Size(column->textLayout, &partText.width, &partText.height); parts[n] = &partText; padList[n] = MAX(partText.padX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = partText.padX[PAD_BOTTOM_RIGHT]; iText = n++; } else { layout->tkfont = column->tkfont ? column->tkfont : column->tree->tkfont; Tk_GetFontMetrics(layout->tkfont, &layout->fm); if (widthForText >= column->textWidth) { partText.width = column->textWidth; partText.height = layout->fm.linespace; layout->bytesThatFit = column->textLen; } else { partText.width = widthForText; partText.height = layout->fm.linespace; layout->bytesThatFit = Ellipsis(layout->tkfont, column->text, column->textLen, &partText.width, "...", FALSE); } parts[n] = &partText; padList[n] = MAX(partText.padX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = partText.padX[PAD_BOTTOM_RIGHT]; iText = n++; } } if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_RIGHT)) { parts[n] = &partArrow; padList[n] = MAX(partArrow.padX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = partArrow.padX[PAD_BOTTOM_RIGHT]; iArrow = n++; } #if defined(MAC_OSX_TK) /* Under Aqua, we let the Appearance Manager draw the sort arrow */ /* This code assumes the arrow is on the right */ if (tree->useTheme && (arrow != ARROW_NONE)) { if (TreeTheme_GetHeaderContentMargins(tree, column->state, arrow, margins) == TCL_OK) { parts[n] = &partArrow; partArrow.width = margins[2]; padList[n] = MAX(0, padList[n]); /* ignore -arrowpadx */ padList[n + 1] = 0; iArrow = n++; } } if (n == 0) { column->arrow = arrow; column->arrowSide = arrowSide; column->arrowGravity = arrowGravity; } #endif if (n == 0) return; for (i = 0; i < n; i++) { padList[i] = parts[i]->padX[0]; if (i) padList[i] = MAX(padList[i], parts[i-1]->padX[1]); padList[i + 1] = parts[i]->padX[1]; widthList[i] = parts[i]->width; } if (iText != -1) { switch (column->justify) { case TK_JUSTIFY_LEFT: partText.left = 0; break; case TK_JUSTIFY_RIGHT: partText.left = layout->width; break; case TK_JUSTIFY_CENTER: if (iImage == -1) partText.left = (layout->width - partText.width) / 2; else partText.left = (layout->width - partImage.width - padList[iText] - partText.width) / 2 + partImage.width + padList[iText]; break; } } if (iImage != -1) { switch (column->justify) { case TK_JUSTIFY_LEFT: partImage.left = 0; break; case TK_JUSTIFY_RIGHT: partImage.left = layout->width; break; case TK_JUSTIFY_CENTER: if (iText == -1) partImage.left = (layout->width - partImage.width) / 2; else partImage.left = (layout->width - partImage.width - padList[iText] - partText.width) / 2; break; } } if (iArrow == -1) goto finish; switch (column->justify) { case TK_JUSTIFY_LEFT: switch (column->arrowSide) { case SIDE_LEFT: partArrow.left = 0; break; case SIDE_RIGHT: switch (column->arrowGravity) { case SIDE_LEFT: partArrow.left = 0; break; case SIDE_RIGHT: partArrow.left = layout->width; break; } break; } break; case TK_JUSTIFY_RIGHT: switch (column->arrowSide) { case SIDE_LEFT: switch (column->arrowGravity) { case SIDE_LEFT: partArrow.left = 0; break; case SIDE_RIGHT: partArrow.left = layout->width; break; } break; case SIDE_RIGHT: partArrow.left = layout->width; break; } break; case TK_JUSTIFY_CENTER: switch (column->arrowSide) { case SIDE_LEFT: switch (column->arrowGravity) { case SIDE_LEFT: partArrow.left = 0; break; case SIDE_RIGHT: if (n == 3) partArrow.left = (layout->width - widthList[1] - padList[2] - widthList[2]) / 2 - padList[1] - widthList[0]; else if (n == 2) partArrow.left = (layout->width - widthList[1]) / 2 - padList[1] - widthList[0]; else partArrow.left = layout->width; break; } break; case SIDE_RIGHT: switch (column->arrowGravity) { case SIDE_LEFT: if (n == 3) partArrow.left = (layout->width - widthList[0] - padList[1] - widthList[1]) / 2 + widthList[0] + padList[1] + widthList[1] + padList[2]; else if (n == 2) partArrow.left = (layout->width - widthList[0]) / 2 + widthList[0] + padList[1]; else partArrow.left = 0; break; case SIDE_RIGHT: partArrow.left = layout->width; break; } break; } break; } finish: right = layout->width - padList[n]; for (i = n - 1; i >= 0; i--) { if (parts[i]->left + parts[i]->width > right) parts[i]->left = right - parts[i]->width; right -= parts[i]->width + padList[i]; } left = padList[0]; for (i = 0; i < n; i++) { if (parts[i]->left < left) parts[i]->left = left; left += parts[i]->width + padList[i + 1]; } if (iArrow != -1) { layout->arrowLeft = partArrow.left; layout->arrowWidth = partArrow.width; layout->arrowHeight = partArrow.height; } if (iImage != -1) { layout->imageLeft = partImage.left; layout->imageWidth = partImage.width; } if (iText != -1) { layout->textLeft = partText.left; layout->textWidth = partText.width; } #if defined(MAC_OSX_TK) /* Under Aqua, we let the Appearance Manager draw the sort arrow */ column->arrow = arrow; column->arrowSide = arrowSide; column->arrowGravity = arrowGravity; #endif } /* *---------------------------------------------------------------------- * * TreeColumn_NeededWidth -- * * Return the total width requested by all the graphical elements * that make up a column header. The width is recalculated if it * is marked out-of-date. * * Results: * The width needed by the current arrangement of the * bitmap/image/text/arrow. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_NeededWidth( TreeColumn column /* Column token. */ ) { TreeCtrl *tree = column->tree; int i, widthList[3], padList[4], n = 0; int arrowWidth, arrowHeight; #if defined(MAC_OSX_TK) int margins[4]; int arrow = column->arrow; #endif if (!tree->showHeader) return 0; if (column->neededWidth >= 0) return column->neededWidth; for (i = 0; i < 3; i++) widthList[i] = 0; for (i = 0; i < 4; i++) padList[i] = 0; #if defined(MAC_OSX_TK) /* Under OSX we let the Appearance Manager draw the sort arrow. */ if (tree->useTheme) column->arrow = ARROW_NONE; #endif if (column->arrow != ARROW_NONE) Column_GetArrowSize(column, &arrowWidth, &arrowHeight); if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_LEFT)) { widthList[n] = arrowWidth; padList[n] = column->arrowPadX[PAD_TOP_LEFT]; padList[n + 1] = column->arrowPadX[PAD_BOTTOM_RIGHT]; n++; } if ((column->image != NULL) || (column->bitmap != None)) { int imgWidth, imgHeight; if (column->image != NULL) Tk_SizeOfImage(column->image, &imgWidth, &imgHeight); else Tk_SizeOfBitmap(tree->display, column->bitmap, &imgWidth, &imgHeight); padList[n] = MAX(column->imagePadX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = column->imagePadX[PAD_BOTTOM_RIGHT]; widthList[n] = imgWidth; n++; } if (column->textLen > 0) { padList[n] = MAX(column->textPadX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = column->textPadX[PAD_BOTTOM_RIGHT]; if (column->textLayoutInvalid || (column->textLayoutWidth != 0)) { Column_UpdateTextLayout(column, 0); column->textLayoutInvalid = FALSE; column->textLayoutWidth = 0; } if (column->textLayout != NULL) TextLayout_Size(column->textLayout, &widthList[n], NULL); else widthList[n] = column->textWidth; n++; } if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_RIGHT)) { widthList[n] = arrowWidth; padList[n] = MAX(column->arrowPadX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = column->arrowPadX[PAD_BOTTOM_RIGHT]; n++; } column->neededWidth = 0; for (i = 0; i < n; i++) column->neededWidth += widthList[i] + padList[i]; column->neededWidth += padList[n]; #if defined(MAC_OSX_TK) if (tree->useTheme) column->arrow = arrow; /* Under OSX we let the Appearance Manager draw the sort arrow. This code * assumes the arrow is on the right. */ if (tree->useTheme && (TreeTheme_GetHeaderContentMargins(tree, column->state, column->arrow, margins) == TCL_OK)) { column->neededWidth += margins[2]; } #endif /* Notice I'm not considering column->borderWidth. */ return column->neededWidth; } /* *---------------------------------------------------------------------- * * TreeColumn_NeededHeight -- * * Return the total height requested by all the graphical elements * that make up a column header. The height is recalculated if it * is marked out-of-date. * * Results: * The height needed by the current arrangement of the * bitmap/image/text/arrow. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_NeededHeight( TreeColumn column /* Column token. */ ) { TreeCtrl *tree = column->tree; int margins[4]; if (column->neededHeight >= 0) return column->neededHeight; #if defined(MAC_OSX_TK) /* List headers are a fixed height on Aqua */ if (tree->useTheme) { (void) TreeTheme_GetHeaderFixedHeight(tree, &column->neededHeight); return column->neededHeight; } #endif column->neededHeight = 0; if (column->arrow != ARROW_NONE) { int arrowWidth, arrowHeight; Column_GetArrowSize(column, &arrowWidth, &arrowHeight); arrowHeight += column->arrowPadY[PAD_TOP_LEFT] + column->arrowPadY[PAD_BOTTOM_RIGHT]; column->neededHeight = MAX(column->neededHeight, arrowHeight); } if ((column->image != NULL) || (column->bitmap != None)) { int imgWidth, imgHeight; if (column->image != NULL) Tk_SizeOfImage(column->image, &imgWidth, &imgHeight); else Tk_SizeOfBitmap(tree->display, column->bitmap, &imgWidth, &imgHeight); imgHeight += column->imagePadY[PAD_TOP_LEFT] + column->imagePadY[PAD_BOTTOM_RIGHT]; column->neededHeight = MAX(column->neededHeight, imgHeight); } if (column->text != NULL) { struct Layout layout; layout.width = TreeColumn_UseWidth(column); layout.height = -1; Column_DoLayout(column, &layout); if (column->textLayout != NULL) { int height; TextLayout_Size(column->textLayout, NULL, &height); height += column->textPadY[PAD_TOP_LEFT] + column->textPadY[PAD_BOTTOM_RIGHT]; column->neededHeight = MAX(column->neededHeight, height); } else { Tk_Font tkfont = column->tkfont ? column->tkfont : column->tree->tkfont; Tk_FontMetrics fm; Tk_GetFontMetrics(tkfont, &fm); fm.linespace += column->textPadY[PAD_TOP_LEFT] + column->textPadY[PAD_BOTTOM_RIGHT]; column->neededHeight = MAX(column->neededHeight, fm.linespace); } } if (column->tree->useTheme && (TreeTheme_GetHeaderContentMargins(tree, column->state, column->arrow, margins) == TCL_OK)) { #ifdef WIN32 /* I'm hacking these margins since the default XP theme does not give * reasonable ContentMargins for HP_HEADERITEM */ int bw = MAX(column->borderWidth, 3); margins[1] = MAX(margins[1], bw); margins[3] = MAX(margins[3], bw); #endif /* WIN32 */ column->neededHeight += margins[1] + margins[3]; } else { column->neededHeight += column->borderWidth * 2; } return column->neededHeight; } /* *---------------------------------------------------------------------- * * TreeColumn_UseWidth -- * * Return the actual display width of a column. * * Results: * Pixel width. * * Side effects: * The size of any column that is marked out-of-date is * recalculated. This could involve recalculating the size of * every element and style in the column in all items. * *---------------------------------------------------------------------- */ int TreeColumn_UseWidth( TreeColumn column /* Column token. */ ) { /* Update layout if needed */ (void) Tree_WidthOfColumns(column->tree); return column->useWidth; } /* *---------------------------------------------------------------------- * * TreeColumn_Offset -- * * Return the x-offset of a column. * * Results: * Pixel offset. * * Side effects: * Column layout is updated if needed. * *---------------------------------------------------------------------- */ int TreeColumn_Offset( TreeColumn column /* Column token. */ ) { /* Update layout if needed */ (void) Tree_WidthOfColumns(column->tree); return column->offset; } /* *---------------------------------------------------------------------- * * TreeColumn_Justify -- * * Return the value of the -justify config option for a column. * * Results: * TK_JUSTIFY_xxx constant. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tk_Justify TreeColumn_Justify( TreeColumn column /* Column token. */ ) { return column->justify; } #ifdef DEPRECATED /* *---------------------------------------------------------------------- * * TreeColumn_WidthHack -- * * Return the value of the -widthhack config option for a column. * NOTE: -widthhack is deprecated. * * Results: * Boolean value. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_WidthHack( TreeColumn column /* Column token. */ ) { return column->widthHack; } #endif /* DEPRECATED */ /* *---------------------------------------------------------------------- * * TreeColumn_Squeeze -- * * Return the value of the -squeeze config option for a column. * * Results: * Boolean value. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_Squeeze( TreeColumn column /* Column token. */ ) { return column->squeeze; } /* *---------------------------------------------------------------------- * * TreeColumn_BackgroundCount -- * * Return the number of -itembackground colors for a column. * * Results: * column->itemBgCount. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_BackgroundCount( TreeColumn column /* Column token. */ ) { return column->itemBgCount; } /* *---------------------------------------------------------------------- * * TreeColumn_BackgroundGC -- * * Return a graphics context for one color of the -itembackground * config option for a column. * * Results: * A graphics context, or None. * * Side effects: * Might allocate a new graphics context? But the GC is freed * when the last reference to the color is lost, so the caller * need not worry about it. * *---------------------------------------------------------------------- */ GC TreeColumn_BackgroundGC( TreeColumn column, /* Column token. */ int index /* This number is determined by the display * code. */ ) { XColor *color; if ((index < 0) || (column->itemBgCount == 0)) return None; color = column->itemBgColor[index % column->itemBgCount]; if (color == NULL) return None; return Tk_GCForColor(color, Tk_WindowId(column->tree->tkwin)); } /* *---------------------------------------------------------------------- * * TreeColumn_ItemStyle -- * * Return the value of the -itemstyle config option for a column. * * Results: * TreeStyle or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeStyle TreeColumn_ItemStyle( TreeColumn column /* Column token. */ ) { return column->itemStyle; } /* *---------------------------------------------------------------------- * * TreeColumn_StyleDeleted -- * * Called when a master style is deleted. * * Results: * Clear the column's -itemstyle option if it is the style being * deleted. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeColumn_StyleDeleted( TreeColumn column, /* Column token. */ TreeStyle style /* Style that was deleted. */ ) { if (column->itemStyle == style) column->itemStyle = NULL; } /* *---------------------------------------------------------------------- * * TreeColumn_Visible -- * * Return the value of the -visible config option for a column. * * Results: * Boolean value. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_Visible( TreeColumn column /* Column token. */ ) { return column->visible; } /* *---------------------------------------------------------------------- * * TreeColumn_GetID -- * * Return the unique identifier for a column. * * Results: * Unique integer id. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_GetID( TreeColumn column /* Column token. */ ) { return column->id; } /* *---------------------------------------------------------------------- * * TreeColumn_Lock -- * * Return the value of the -lock option for a column. * * Results: * One of the COLUMN_LOCK_xxx constants. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_Lock( TreeColumn column /* Column token. */ ) { return column->lock; } /* *---------------------------------------------------------------------- * * TreeColumn_Index -- * * Return the 0-based index for a column. * * Results: * Position of the column in the list of columns. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_Index( TreeColumn column /* Column token. */ ) { return column->index; } /* *---------------------------------------------------------------------- * * ColumnTagCmd -- * * This procedure is invoked to process the [column tag] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ColumnTagCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandNames[] = { "add", "expr", "names", "remove", (char *) NULL }; enum { COMMAND_ADD, COMMAND_EXPR, COMMAND_NAMES, COMMAND_REMOVE }; int index; ColumnForEach iter; TreeColumnList columns; TreeColumn column; int result = TCL_OK; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T column tag add C tagList */ case COMMAND_ADD: { int i, numTags; Tcl_Obj **listObjv; Tk_Uid staticTags[STATIC_SIZE], *tags = staticTags; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "column tagList"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[4], &columns, 0) != TCL_OK) { return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[5], &numTags, &listObjv) != TCL_OK) { result = TCL_ERROR; break; } STATIC_ALLOC(tags, Tk_Uid, numTags); for (i = 0; i < numTags; i++) { tags[i] = Tk_GetUid(Tcl_GetString(listObjv[i])); } COLUMN_FOR_EACH(column, &columns, NULL, &iter) { column->tagInfo = TagInfo_Add(tree, column->tagInfo, tags, numTags); } STATIC_FREE(tags, Tk_Uid, numTags); break; } /* T column tag expr C tagExpr */ case COMMAND_EXPR: { TagExpr expr; int ok = TRUE; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "column tagExpr"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[4], &columns, 0) != TCL_OK) { return TCL_ERROR; } if (TagExpr_Init(tree, objv[5], &expr) != TCL_OK) { result = TCL_ERROR; break; } COLUMN_FOR_EACH(column, &columns, NULL, &iter) { if (!TagExpr_Eval(&expr, column->tagInfo)) { ok = FALSE; break; } } TagExpr_Free(&expr); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ok)); break; } /* T column tag names C */ case COMMAND_NAMES: { Tcl_Obj *listObj; Tk_Uid *tags = NULL; int i, tagSpace, numTags = 0; if (objc != 5) { Tcl_WrongNumArgs(interp, 4, objv, "column"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[4], &columns, 0) != TCL_OK) { return TCL_ERROR; } COLUMN_FOR_EACH(column, &columns, NULL, &iter) { tags = TagInfo_Names(tree, column->tagInfo, tags, &numTags, &tagSpace); } if (numTags) { listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < numTags; i++) { Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewStringObj((char *) tags[i], -1)); } Tcl_SetObjResult(interp, listObj); ckfree((char *) tags); } break; } /* T column tag remove C tagList */ case COMMAND_REMOVE: { int i, numTags; Tcl_Obj **listObjv; Tk_Uid staticTags[STATIC_SIZE], *tags = staticTags; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "column tagList"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[4], &columns, 0) != TCL_OK) { return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[5], &numTags, &listObjv) != TCL_OK) { result = TCL_ERROR; break; } STATIC_ALLOC(tags, Tk_Uid, numTags); for (i = 0; i < numTags; i++) { tags[i] = Tk_GetUid(Tcl_GetString(listObjv[i])); } COLUMN_FOR_EACH(column, &columns, NULL, &iter) { column->tagInfo = TagInfo_Remove(tree, column->tagInfo, tags, numTags); } STATIC_FREE(tags, Tk_Uid, numTags); break; } } TreeColumnList_Free(&columns); return result; } /* *---------------------------------------------------------------------- * * TreeColumnCmd -- * * This procedure is invoked to process the [column] widget * command. See the user documentation for details on what it * does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeColumnCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandNames[] = { "bbox", "cget", "compare", "configure", "count", "create", "delete", "dragcget", "dragconfigure", "id", #ifdef DEPRECATED "index", #endif "list", "move", "neededwidth", "order", "tag", "width", (char *) NULL }; enum { COMMAND_BBOX, COMMAND_CGET, COMMAND_COMPARE, COMMAND_CONFIGURE, COMMAND_COUNT, COMMAND_CREATE, COMMAND_DELETE, COMMAND_DRAGCGET, COMMAND_DRAGCONF, COMMAND_ID, #ifdef DEPRECATED COMMAND_INDEX, #endif COMMAND_LIST, COMMAND_MOVE, COMMAND_NEEDEDWIDTH, COMMAND_ORDER, COMMAND_TAG, COMMAND_WIDTH }; int index; TreeColumnList columns; TreeColumn column; ColumnForEach citer; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_BBOX: { int left, top, width, height; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "column"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; if (TreeColumn_Bbox(column, &left, &top, &width, &height) < 0) break; FormatResult(interp, "%d %d %d %d", left, top, left + width, top + height); break; } case COMMAND_CGET: { TreeColumn column; Tcl_Obj *resultObjPtr; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "column option"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; resultObjPtr = Tk_GetOptionValue(interp, (char *) column, column->optionTable, objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T column compare C op C */ case COMMAND_COMPARE: { TreeColumn column1, column2; static CONST84 char *opName[] = { "<", "<=", "==", ">=", ">", "!=", NULL }; int op, compare = 0, index1, index2; if (objc != 6) { Tcl_WrongNumArgs(interp, 3, objv, "column1 op column2"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column1, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (Tcl_GetIndexFromObj(interp, objv[4], opName, "comparison operator", 0, &op) != TCL_OK) return TCL_ERROR; if (TreeColumn_FromObj(tree, objv[5], &column2, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; index1 = TreeColumn_Index(column1); index2 = TreeColumn_Index(column2); switch (op) { case 0: compare = index1 < index2; break; case 1: compare = index1 <= index2; break; case 2: compare = index1 == index2; break; case 3: compare = index1 >= index2; break; case 4: compare = index1 > index2; break; case 5: compare = index1 != index2; break; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(compare)); break; } case COMMAND_CONFIGURE: { if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "column ?option? ?value? ?option value ...?"); return TCL_ERROR; } if (objc <= 5) { Tcl_Obj *resultObjPtr; if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; resultObjPtr = Tk_GetOptionInfo(interp, (char *) column, column->optionTable, (objc == 4) ? (Tcl_Obj *) NULL : objv[4], tree->tkwin); if (resultObjPtr == NULL) goto errorExit; Tcl_SetObjResult(interp, resultObjPtr); break; } /* If "all" is specified, get a list of columns instead of * COLUMN_ALL, since changing the -lock option of a column * may reorder columns. */ if (TreeColumnList_FromObj(tree, objv[3], &columns, CFO_LIST_ALL | CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; COLUMN_FOR_EACH(column, &columns, NULL, &citer) { if (Column_Config(column, objc - 4, objv + 4, FALSE) != TCL_OK) goto errorExit; } TreeColumnList_Free(&columns); break; } case COMMAND_CREATE: { TreeColumn column, last = tree->columnLast; /* FIXME: -count N -tags $tags */ column = Column_Alloc(tree); if (Column_Config(column, objc - 3, objv + 3, TRUE) != TCL_OK) { Column_Free(column); return TCL_ERROR; } if (tree->columns == NULL) { column->index = 0; tree->columns = column; } else { last->next = column; column->prev = last; column->index = last->index + 1; } tree->columnLast = column; tree->columnTail->index++; { TreeColumn before = NULL; switch (column->lock) { case COLUMN_LOCK_LEFT: before = tree->columnLockNone; if (before == NULL) before = tree->columnLockRight; break; case COLUMN_LOCK_NONE: before = tree->columnLockRight; break; case COLUMN_LOCK_RIGHT: before = NULL; break; } if (before == NULL) before = tree->columnTail; Column_Move(column, before); } /* Indicate that all items must recalculate their list of spans. */ TreeItem_SpansInvalidate(tree, NULL); Tree_DInfoChanged(tree, DINFO_REDO_COLUMN_WIDTH); Tcl_SetObjResult(interp, TreeColumn_ToObj(tree, column)); break; } /* T column delete first ?last? */ case COMMAND_DELETE: { TreeColumnList columns, column2s; TreeColumn prev, next; int flags = CFO_NOT_NULL | CFO_NOT_TAIL; TreeItem item; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int index; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "first ?last?"); return TCL_ERROR; } if (objc == 5) flags |= CFO_NOT_MANY; if (TreeColumnList_FromObj(tree, objv[3], &columns, flags) != TCL_OK) return TCL_ERROR; if (objc == 5) { if (TreeColumnList_FromObj(tree, objv[4], &column2s, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; } COLUMN_FOR_EACH(column, &columns, (objc == 5) ? &column2s : NULL, &citer) { /* T column delete "all" */ if (citer.all) { column = tree->columns; while (column != NULL) { TreeDisplay_ColumnDeleted(tree, column); column = Column_Free(column); } tree->columnTail->index = 0; tree->columns = NULL; tree->columnLast = NULL; tree->columnLockLeft = NULL; tree->columnLockNone = NULL; tree->columnLockRight = NULL; /* Delete all TreeItemColumns */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_RemoveAllColumns(tree, item); hPtr = Tcl_NextHashEntry(&search); } tree->columnTree = NULL; tree->columnDrag.column = tree->columnDrag.indColumn = NULL; tree->widthOfColumns = tree->headerHeight = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_REDO_COLUMN_WIDTH); goto doneDELETE; } /* Delete all TreeItemColumns */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_RemoveColumns(tree, item, column->index, column->index); hPtr = Tcl_NextHashEntry(&search); } TreeDisplay_ColumnDeleted(tree, column); /* Unlink. */ prev = column->prev; next = column->next; if (prev == NULL) tree->columns = next; else prev->next = next; if (next == NULL) tree->columnLast = prev; else next->prev = prev; if (column == tree->columnTree) tree->columnTree = NULL; if (column == tree->columnDrag.column) tree->columnDrag.column = NULL; if (column == tree->columnDrag.indColumn) tree->columnDrag.indColumn = NULL; (void) Column_Free(column); /* Renumber trailing columns */ column = next; while (column != NULL) { column->index--; column = column->next; } } tree->columnLockLeft = NULL; tree->columnLockNone = NULL; tree->columnLockRight = NULL; index = 0; column = tree->columns; while (column != NULL) { column->index = index++; if (column->lock == COLUMN_LOCK_LEFT && tree->columnLockLeft == NULL) tree->columnLockLeft = column; if (column->lock == COLUMN_LOCK_NONE && tree->columnLockNone == NULL) tree->columnLockNone = column; if (column->lock == COLUMN_LOCK_RIGHT && tree->columnLockRight == NULL) tree->columnLockRight = column; column = column->next; } tree->columnTail->index = index; tree->widthOfColumns = tree->headerHeight = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_REDO_COLUMN_WIDTH); doneDELETE: /* Indicate that all items must recalculate their list of spans. */ TreeItem_SpansInvalidate(tree, NULL); TreeItemList_Free(&columns); if (objc == 5) TreeItemList_Free(&column2s); break; } /* T column dragcget option */ case COMMAND_DRAGCGET: { Tcl_Obj *resultObjPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(interp, (char *) tree, tree->columnDrag.optionTable, objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T column dragconfigure ?option? ?value? ?option value ...? */ case COMMAND_DRAGCONF: { Tcl_Obj *resultObjPtr; Tk_SavedOptions savedOptions; int mask, result; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?option? ?value?"); return TCL_ERROR; } if (objc <= 4) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) tree, tree->columnDrag.optionTable, (objc == 3) ? (Tcl_Obj *) NULL : objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } result = Tk_SetOptions(interp, (char *) tree, tree->columnDrag.optionTable, objc - 3, objv + 3, tree->tkwin, &savedOptions, &mask); if (result != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } Tk_FreeSavedOptions(&savedOptions); if (tree->columnDrag.alpha < 0) tree->columnDrag.alpha = 0; if (tree->columnDrag.alpha > 255) tree->columnDrag.alpha = 255; Tree_DInfoChanged(tree, DINFO_DRAW_HEADER); break; } case COMMAND_COUNT: { int count = tree->columnCount; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 3, objv, "?columnDesc?"); return TCL_ERROR; } if (objc == 4) { if (TreeColumnList_FromObj(tree, objv[3], &columns, 0) != TCL_OK) return TCL_ERROR; count = 0; COLUMN_FOR_EACH(column, &columns, NULL, &citer) { count++; } } Tcl_SetObjResult(interp, Tcl_NewIntObj(count)); break; } case COMMAND_WIDTH: { if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "column"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; /* Update layout if needed */ (void) Tree_WidthOfColumns(tree); Tcl_SetObjResult(interp, Tcl_NewIntObj(column->useWidth)); break; } case COMMAND_ID: #ifdef DEPRECATED case COMMAND_INDEX: #endif { Tcl_Obj *listObj; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "column"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[3], &columns, 0) != TCL_OK) return TCL_ERROR; listObj = Tcl_NewListObj(0, NULL); COLUMN_FOR_EACH(column, &columns, NULL, &citer) { Tcl_ListObjAppendElement(interp, listObj, TreeColumn_ToObj(tree, column)); } TreeColumnList_Free(&columns); Tcl_SetObjResult(interp, listObj); break; } /* T column list ?-visible? */ case COMMAND_LIST: { TreeColumn column = tree->columns; Tcl_Obj *listObj; int visible = FALSE; if (objc > 4) { Tcl_WrongNumArgs(interp, 3, objv, "?-visible?"); return TCL_ERROR; } if (objc == 4) { int len; char *s = Tcl_GetStringFromObj(objv[3], &len); if ((s[0] == '-') && (strncmp(s, "-visible", len) == 0)) visible = TRUE; else { FormatResult(interp, "bad switch \"%s\": must be -visible", s); return TCL_ERROR; } } listObj = Tcl_NewListObj(0, NULL); while (column != NULL) { if (!visible || column->visible) Tcl_ListObjAppendElement(interp, listObj, TreeColumn_ToObj(tree, column)); column = column->next; } Tcl_SetObjResult(interp, listObj); break; } /* T column move C before */ case COMMAND_MOVE: { TreeColumn move, before; TreeColumn first = NULL, last = tree->columnTail; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "column before"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &move, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; if (TreeColumn_FromObj(tree, objv[4], &before, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if ((move == before) || (move->index == before->index - 1)) break; switch (move->lock) { case COLUMN_LOCK_LEFT: first = tree->columnLockLeft; if (tree->columnLockNone != NULL) last = tree->columnLockNone; else if (tree->columnLockRight != NULL) last = tree->columnLockRight; break; case COLUMN_LOCK_NONE: first = tree->columnLockNone; if (tree->columnLockRight != NULL) last = tree->columnLockRight; break; case COLUMN_LOCK_RIGHT: first = tree->columnLockRight; break; } if (before->index < first->index || before->index > last->index) { FormatResult(tree->interp, "column %s%d and column %s%d -lock options conflict", tree->columnPrefix, move->id, tree->columnPrefix, before->id); return TCL_ERROR; } Column_Move(move, before); /* Indicate that all items must recalculate their list of spans. */ TreeItem_SpansInvalidate(tree, NULL); break; } case COMMAND_NEEDEDWIDTH: { TreeColumn column; int width; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "column"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; /* Update layout if needed */ (void) Tree_TotalWidth(tree); width = TreeColumn_WidthOfItems(column); width = MAX(width, TreeColumn_NeededWidth(column)); Tcl_SetObjResult(interp, Tcl_NewIntObj(width)); break; } /* T column order C ?-visible? */ case COMMAND_ORDER: { TreeColumn column; int visible = FALSE; int index = 0; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "column ?-visible?"); return TCL_ERROR; } if (objc == 5) { int len; char *s = Tcl_GetStringFromObj(objv[4], &len); if ((s[0] == '-') && (strncmp(s, "-visible", len) == 0)) visible = TRUE; else { FormatResult(interp, "bad switch \"%s\": must be -visible", s); return TCL_ERROR; } } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (visible) { TreeColumn walk = tree->columns; while (walk != NULL) { if (walk == column) break; if (walk->visible) index++; walk = walk->next; } if (!column->visible) index = -1; } else { index = column->index; } Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); break; } case COMMAND_TAG: { return ColumnTagCmd(clientData, interp, objc, objv); } } return TCL_OK; errorExit: TreeColumnList_Free(&columns); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Column_DrawArrow -- * * Draw the sort arrow for a column. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ static void Column_DrawArrow( TreeColumn column, /* Column record. */ Drawable drawable, /* Where to draw. */ int x, int y, /* Top-left corner of the column's header. */ struct Layout layout /* Size/position info. */ ) { TreeCtrl *tree = column->tree; int height = tree->headerHeight; int sunken = column->state == COLUMN_STATE_PRESSED; Tk_Image image = NULL; Pixmap bitmap; Tk_3DBorder border; int state = Column_MakeState(column); int arrowPadY = column->arrowPadY[PAD_TOP_LEFT] + column->arrowPadY[PAD_BOTTOM_RIGHT]; if (column->arrow == ARROW_NONE) return; image = PerStateImage_ForState(tree, &column->arrowImage, state, NULL); if (image != NULL) { Tk_RedrawImage(image, 0, 0, layout.arrowWidth, layout.arrowHeight, drawable, x + layout.arrowLeft + sunken, y + (height - (layout.arrowHeight + arrowPadY)) / 2 + sunken); return; } bitmap = PerStateBitmap_ForState(tree, &column->arrowBitmap, state, NULL); if (bitmap != None) { int bx, by; bx = x + layout.arrowLeft + sunken; by = y + (height - (layout.arrowHeight + arrowPadY)) / 2 + sunken; Tree_DrawBitmap(tree, bitmap, drawable, NULL, NULL, 0, 0, (unsigned int) layout.arrowWidth, (unsigned int) layout.arrowHeight, bx, by); return; } if (tree->useTheme) { if (TreeTheme_DrawHeaderArrow(tree, drawable, column->arrow == ARROW_UP, x + layout.arrowLeft + sunken, y + (height - (layout.arrowHeight + arrowPadY)) / 2 + sunken, layout.arrowWidth, layout.arrowHeight) == TCL_OK) return; } if (1) { int arrowWidth = layout.arrowWidth; int arrowHeight = layout.arrowHeight; int arrowTop = y + (height - (layout.arrowHeight + arrowPadY)) / 2 + column->arrowPadY[PAD_TOP_LEFT]; int arrowBottom = arrowTop + arrowHeight; XPoint points[5]; int color1 = 0, color2 = 0; int i; switch (column->arrow) { case ARROW_UP: points[0].x = x + layout.arrowLeft; points[0].y = arrowBottom - 1; points[1].x = x + layout.arrowLeft + arrowWidth / 2; points[1].y = arrowTop - 1; color1 = TK_3D_DARK_GC; points[4].x = x + layout.arrowLeft + arrowWidth / 2; points[4].y = arrowTop - 1; points[3].x = x + layout.arrowLeft + arrowWidth - 1; points[3].y = arrowBottom - 1; points[2].x = x + layout.arrowLeft; points[2].y = arrowBottom - 1; color2 = TK_3D_LIGHT_GC; break; case ARROW_DOWN: points[0].x = x + layout.arrowLeft + arrowWidth - 1; points[0].y = arrowTop; points[1].x = x + layout.arrowLeft + arrowWidth / 2; points[1].y = arrowBottom; color1 = TK_3D_LIGHT_GC; points[2].x = x + layout.arrowLeft + arrowWidth - 1; points[2].y = arrowTop; points[3].x = x + layout.arrowLeft; points[3].y = arrowTop; points[4].x = x + layout.arrowLeft + arrowWidth / 2; points[4].y = arrowBottom; color2 = TK_3D_DARK_GC; break; } for (i = 0; i < 5; i++) { points[i].x += sunken; points[i].y += sunken; } border = PerStateBorder_ForState(tree, &column->border, Column_MakeState(column), NULL); if (border == NULL) border = tree->border; XDrawLines(tree->display, drawable, Tk_3DBorderGC(tree->tkwin, border, color2), points + 2, 3, CoordModeOrigin); XDrawLines(tree->display, drawable, Tk_3DBorderGC(tree->tkwin, border, color1), points, 2, CoordModeOrigin); } } /* *---------------------------------------------------------------------- * * Column_Draw -- * * Draw the header for a column. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ static void Column_Draw( TreeColumn column, /* Column record. */ Drawable drawable, /* Where to draw. */ int x, int y, /* Top-left corner of the column's header. */ int dragImage /* TRUE if we are creating a transparent * drag image for this header. */ ) { TreeCtrl *tree = column->tree; int height = tree->headerHeight; struct Layout layout; int width = column->useWidth; int sunken = column->state == COLUMN_STATE_PRESSED; int relief = sunken ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED; Tk_3DBorder border; int theme = TCL_ERROR; layout.width = width; layout.height = height; Column_DoLayout(column, &layout); border = PerStateBorder_ForState(tree, &column->border, Column_MakeState(column), NULL); if (border == NULL) border = tree->border; if (dragImage) { GC gc = Tk_GCForColor(tree->columnDrag.color, Tk_WindowId(tree->tkwin)); XFillRectangle(tree->display, drawable, gc, x, y, width, height); } else { if (tree->useTheme) { theme = TreeTheme_DrawHeaderItem(tree, drawable, column->state, column->arrow, x, y, width, height); } if (theme != TCL_OK) Tk_Fill3DRectangle(tree->tkwin, drawable, border, x, y, width, height, 0, TK_RELIEF_FLAT); } if (column->image != NULL) { int imgW, imgH, ix, iy, h; Tk_SizeOfImage(column->image, &imgW, &imgH); ix = x + layout.imageLeft + sunken; h = column->imagePadY[PAD_TOP_LEFT] + imgH + column->imagePadY[PAD_BOTTOM_RIGHT]; iy = y + (height - h) / 2 + sunken; iy += column->imagePadY[PAD_TOP_LEFT]; Tk_RedrawImage(column->image, 0, 0, imgW, imgH, drawable, ix, iy); } else if (column->bitmap != None) { int imgW, imgH, bx, by, h; Tk_SizeOfBitmap(tree->display, column->bitmap, &imgW, &imgH); bx = x + layout.imageLeft + sunken; h = column->imagePadY[PAD_TOP_LEFT] + imgH + column->imagePadY[PAD_BOTTOM_RIGHT]; by = y + (height - h) / 2 + sunken; by += column->imagePadY[PAD_TOP_LEFT]; Tree_DrawBitmapWithGC(tree, column->bitmap, drawable, column->bitmapGC, 0, 0, (unsigned int) imgW, (unsigned int) imgH, bx, by); } if ((column->text != NULL) && (column->textLayout != NULL)) { int h; XGCValues gcValues; GC gc; unsigned long mask; TextLayout_Size(column->textLayout, NULL, &h); h += column->textPadY[PAD_TOP_LEFT] + column->textPadY[PAD_BOTTOM_RIGHT]; gcValues.font = Tk_FontId(column->tkfont ? column->tkfont : tree->tkfont); gcValues.foreground = column->textColor->pixel; gcValues.graphics_exposures = False; mask = GCFont | GCForeground | GCGraphicsExposures; gc = Tk_GetGC(tree->tkwin, mask, &gcValues); TextLayout_Draw(tree->display, drawable, gc, column->textLayout, x + layout.textLeft + sunken, y + (height - h) / 2 + column->textPadY[PAD_TOP_LEFT] + sunken, 0, -1, -1); Tk_FreeGC(tree->display, gc); } else if ((column->text != NULL) && (layout.bytesThatFit != 0)) { XGCValues gcValues; GC gc; unsigned long mask; char staticStr[256], *text = staticStr; int textLen = column->textLen; char *ellipsis = "..."; int ellipsisLen = (int)strlen(ellipsis); int tx, ty, h; if (textLen + ellipsisLen > sizeof(staticStr)) text = ckalloc(textLen + ellipsisLen); memcpy(text, column->text, textLen); if (layout.bytesThatFit != textLen) { textLen = abs(layout.bytesThatFit); if (layout.bytesThatFit > 0) { memcpy(text + layout.bytesThatFit, ellipsis, ellipsisLen); textLen += ellipsisLen; } } gcValues.font = Tk_FontId(layout.tkfont); gcValues.foreground = column->textColor->pixel; gcValues.graphics_exposures = False; mask = GCFont | GCForeground | GCGraphicsExposures; gc = Tk_GetGC(tree->tkwin, mask, &gcValues); tx = x + layout.textLeft + sunken; h = column->textPadY[PAD_TOP_LEFT] + layout.fm.linespace + column->textPadY[PAD_BOTTOM_RIGHT]; ty = y + (height - h) / 2 + layout.fm.ascent + sunken; ty += column->textPadY[PAD_TOP_LEFT]; Tk_DrawChars(tree->display, drawable, gc, layout.tkfont, text, textLen, tx, ty); Tk_FreeGC(tree->display, gc); if (text != staticStr) ckfree(text); } if (dragImage) return; #if defined(MAC_OSX_TK) /* Under Aqua, we let the Appearance Manager draw the sort arrow */ if (theme != TCL_OK) #endif Column_DrawArrow(column, drawable, x, y, layout); if (theme != TCL_OK) Tk_Draw3DRectangle(tree->tkwin, drawable, border, x, y, width, height, column->borderWidth, relief); } /* *---------------------------------------------------------------------- * * SetImageForColumn -- * * Set a photo image containing a simplified picture of the header * of a column. This image is used when dragging and dropping a column * header. * * Results: * Token for a photo image, or NULL if the image could not be * created. * * Side effects: * A photo image called "::TreeCtrl::ImageColumn" will be created if * it doesn't exist. The image is set to contain a picture of the * column header. * *---------------------------------------------------------------------- */ static Tk_Image SetImageForColumn( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column record. */ ) { Tk_PhotoHandle photoH; Pixmap pixmap; int width = column->useWidth; /* the entire column, not just what is visible */ int height = tree->headerHeight; XImage *ximage; photoH = Tk_FindPhoto(tree->interp, "::TreeCtrl::ImageColumn"); if (photoH == NULL) { Tcl_GlobalEval(tree->interp, "image create photo ::TreeCtrl::ImageColumn"); photoH = Tk_FindPhoto(tree->interp, "::TreeCtrl::ImageColumn"); if (photoH == NULL) return NULL; } pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tree->tkwin), width, height, Tk_Depth(tree->tkwin)); Column_Draw(column, pixmap, 0, 0, TRUE); /* Pixmap -> XImage */ ximage = XGetImage(tree->display, pixmap, 0, 0, (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap); if (ximage == NULL) panic("ximage is NULL"); /* XImage -> Tk_Image */ XImage2Photo(tree->interp, photoH, ximage, tree->columnDrag.alpha); XDestroyImage(ximage); Tk_FreePixmap(tree->display, pixmap); return Tk_GetImage(tree->interp, tree->tkwin, "::TreeCtrl::ImageColumn", NULL, (ClientData) NULL); } static void DrawDragIndicator( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ int lock ) { TreeColumn column = tree->columnDrag.indColumn; int x, y, w, h; int minX = 0, maxX = 0; GC gc; if ((column == NULL) || (column->lock != lock)) return; switch (lock) { case COLUMN_LOCK_LEFT: minX = Tree_HeaderLeft(tree); maxX = Tree_ContentLeft(tree); break; case COLUMN_LOCK_NONE: minX = Tree_ContentLeft(tree); maxX = Tree_ContentRight(tree); break; case COLUMN_LOCK_RIGHT: minX = Tree_ContentRight(tree); maxX = Tree_HeaderRight(tree); break; } if (TreeColumn_Bbox(column, &x, &y, &w, &h) == 0) { if (tree->columnDrag.indSide == SIDE_LEFT) { x -= 1; if (x == minX - 1) x += 1; } else { x += w - 1; if (x == maxX - 1) x -= 1; } gc = Tk_GCForColor(tree->columnDrag.indColor, Tk_WindowId(tree->tkwin)); XFillRectangle(tree->display, drawable, gc, x, y, 2, tree->headerHeight); } } static void DrawHeaderLeft( TreeCtrl *tree, /* Widget info. */ Drawable drawable /* Where to draw. */ ) { TreeColumn column = tree->columnLockLeft; Tk_Window tkwin = tree->tkwin; int x = Tree_HeaderLeft(tree), y = Tree_HeaderTop(tree); Drawable pixmap; pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), Tk_Width(tkwin), Tree_HeaderBottom(tree), Tk_Depth(tkwin)); while (column != NULL && column->lock == COLUMN_LOCK_LEFT) { if (column->visible) { Column_Draw(column, pixmap, x, y, FALSE); x += column->useWidth; } column = column->next; } DrawDragIndicator(tree, pixmap, COLUMN_LOCK_LEFT); XCopyArea(tree->display, pixmap, drawable, tree->copyGC, Tree_HeaderLeft(tree), y, x - Tree_HeaderLeft(tree), tree->headerHeight, Tree_HeaderLeft(tree), y); Tk_FreePixmap(tree->display, pixmap); } static void DrawHeaderRight( TreeCtrl *tree, /* Widget info. */ Drawable drawable /* Where to draw. */ ) { TreeColumn column = tree->columnLockRight; Tk_Window tkwin = tree->tkwin; int x = Tree_ContentRight(tree), y = Tree_HeaderTop(tree); Drawable pixmap; pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), Tk_Width(tkwin), Tree_HeaderBottom(tree), Tk_Depth(tkwin)); while (column != NULL && column->lock == COLUMN_LOCK_RIGHT) { if (column->visible) { Column_Draw(column, pixmap, x, y, FALSE); x += column->useWidth; } column = column->next; } DrawDragIndicator(tree, pixmap, COLUMN_LOCK_RIGHT); XCopyArea(tree->display, pixmap, drawable, tree->copyGC, Tree_ContentRight(tree), y, x - Tree_ContentRight(tree), tree->headerHeight, Tree_ContentRight(tree), y); Tk_FreePixmap(tree->display, pixmap); } /* *---------------------------------------------------------------------- * * Tree_DrawHeader -- * * Draw the header of every column. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ void Tree_DrawHeader( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ int x, int y /* Top-left corner of the header. */ ) { TreeColumn column = tree->columns; Tk_Window tkwin = tree->tkwin; int minX, maxX, width, height; Drawable pixmap; /* Update layout if needed */ (void) Tree_HeaderHeight(tree); (void) Tree_WidthOfColumns(tree); minX = Tree_ContentLeft(tree); maxX = Tree_ContentRight(tree); if (tree->doubleBuffer == DOUBLEBUFFER_ITEM) pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), Tk_Width(tkwin), Tree_HeaderBottom(tree), Tk_Depth(tkwin)); else pixmap = drawable; column = tree->columnLockNone; while (column != NULL && column->lock == COLUMN_LOCK_NONE) { if (column->visible) { if ((x < maxX) && (x + column->useWidth > minX)) Column_Draw(column, pixmap, x, y, FALSE); x += column->useWidth; } column = column->next; } /* Draw "tail" column */ if (x < maxX) { column = tree->columnTail; width = maxX - x + column->borderWidth; height = tree->headerHeight; if (!column->visible) { Tk_Fill3DRectangle(tkwin, pixmap, tree->border, x, y, width, height, 0, TK_RELIEF_FLAT); } else if (tree->useTheme && (TreeTheme_DrawHeaderItem(tree, pixmap, 0, 0, x, y, width, height) == TCL_OK)) { } else { Tk_3DBorder border; border = PerStateBorder_ForState(tree, &column->border, Column_MakeState(column), NULL); if (border == NULL) border = tree->border; Tk_Fill3DRectangle(tkwin, pixmap, border, x, y, width, height, column->borderWidth, TK_RELIEF_RAISED); } } if (minX < maxX) DrawDragIndicator(tree, pixmap, COLUMN_LOCK_NONE); if (Tree_WidthOfLeftColumns(tree) > 0) DrawHeaderLeft(tree, pixmap); if (Tree_WidthOfRightColumns(tree) > 0) DrawHeaderRight(tree, pixmap); if (tree->columnDrag.column != NULL) { Tk_Image image; int x, y, w, h; if (TreeColumn_Bbox(tree->columnDrag.column, &x, &y, &w, &h) == 0) { int ix = 0, iy = 0, iw = w, ih = tree->headerHeight; image = SetImageForColumn(tree, tree->columnDrag.column); x += tree->columnDrag.offset; #if !defined(WIN32) && !defined(MAC_TCL) && !defined(MAC_OSX_TK) /* * Do boundary clipping, so that Tk_RedrawImage is passed * valid coordinates. [Tk Bug 979239] */ if (x < minX) { ix = minX - x; iw -= ix; x = minX; w -= ix; } if (x + w > maxX) { iw -= (x + w) - maxX; } #endif Tk_RedrawImage(image, ix, iy, iw, ih, pixmap, x, y); Tk_FreeImage(image); } } if (tree->doubleBuffer == DOUBLEBUFFER_ITEM) { XCopyArea(tree->display, pixmap, drawable, tree->copyGC, Tree_HeaderLeft(tree), y, Tree_HeaderWidth(tree), tree->headerHeight, Tree_HeaderLeft(tree), y); Tk_FreePixmap(tree->display, pixmap); } } /* *---------------------------------------------------------------------- * * TreeColumn_WidthOfItems -- * * Calculate the maximum needed width of the styles in every * ReallyVisible() item for a particular column. The width will * only be recalculated if it is marked out-of-date. * * Results: * Pixel width. * * Side effects: * The size of elements and styles will be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ int TreeColumn_WidthOfItems( TreeColumn column /* Column token. */ ) { TreeCtrl *tree = column->tree; TreeItem item; TreeItemColumn itemColumn; int width; if (column->widthOfItems >= 0) return column->widthOfItems; column->widthOfItems = 0; item = tree->root; if (!TreeItem_ReallyVisible(tree, item)) item = TreeItem_NextVisible(tree, item); while (item != NULL) { #ifdef EXPENSIVE_SPAN_WIDTH /* NOT USED */ width = TreeItem_NeededWidthOfColumn(tree, item, column->index); if (column == tree->columnTree) width += TreeItem_Indent(tree, item); column->widthOfItems = MAX(column->widthOfItems, width); #else itemColumn = TreeItem_FindColumn(tree, item, column->index); if (itemColumn != NULL) { width = TreeItemColumn_NeededWidth(tree, item, itemColumn); if (column == tree->columnTree) width += TreeItem_Indent(tree, item); column->widthOfItems = MAX(column->widthOfItems, width); } #endif item = TreeItem_NextVisible(tree, item); } return column->widthOfItems; } /* *---------------------------------------------------------------------- * * Tree_InvalidateColumnWidth -- * * Marks the width of zero or more columns as out-of-date. * Schedules a redisplay to check the widths of columns which * will perform any relayout necessary. * * Results: * None. * * Side effects: * Idle task may be scheduled. * *---------------------------------------------------------------------- */ void Tree_InvalidateColumnWidth( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column to modify. NULL means * modify every column. */ ) { #ifdef COLUMN_SPANxxx /* It may be necessary to recalculate the width of other columns as * well when column-spanning is in effect. */ column = NULL; #endif if (column == NULL) { column = tree->columns; while (column != NULL) { column->widthOfItems = -1; column = column->next; } } else { column->widthOfItems = -1; } tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH | DINFO_DRAW_HEADER); } /* *---------------------------------------------------------------------- * * Tree_InvalidateColumnHeight -- * * Marks the height of zero or more column headers as out-of-date. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_InvalidateColumnHeight( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column to modify. NULL means * modify every column. */ ) { if (column == NULL) { column = tree->columns; while (column != NULL) { column->neededHeight = -1; column = column->next; } } else { column->neededHeight = -1; } tree->headerHeight = -1; } /* *---------------------------------------------------------------------- * * TreeColumn_TreeChanged -- * * Called when a TreeCtrl is configured. Performs any relayout * necessary on column headers. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeColumn_TreeChanged( TreeCtrl *tree, /* Widget info. */ int flagT /* TREE_CONF_xxx flags. */ ) { TreeColumn column; /* Column widths are invalidated elsewhere */ if (flagT & TREE_CONF_FONT) { column = tree->columns; while (column != NULL) { if ((column->tkfont == NULL) && (column->textLen > 0)) { column->textWidth = Tk_TextWidth(tree->tkfont, column->text, column->textLen); column->neededWidth = column->neededHeight = -1; column->textLayoutInvalid = TRUE; } column = column->next; } tree->headerHeight = -1; } } /* *---------------------------------------------------------------------- * * Tree_HeaderHeight -- * * Return the total height of the column header area. The height * is only recalculated if it is marked out-of-date. * * Results: * Pixel height. Will be zero if the -showheader option is FALSE. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_HeaderHeight( TreeCtrl *tree /* Widget info. */ ) { TreeColumn column; int height; if (!tree->showHeader) return 0; if (tree->headerHeight >= 0) return tree->headerHeight; height = 0; column = tree->columns; while (column != NULL) { if (column->visible) height = MAX(height, TreeColumn_NeededHeight(column)); column = column->next; } return tree->headerHeight = height; } /* *-------------------------------------------------------------- * * TreeColumn_Bbox -- * * Return the bounding box for a column header. * * Results: * Return value is -1 if the item is not visible. * * Side effects: * Column layout will be updated if needed. * *-------------------------------------------------------------- */ int TreeColumn_Bbox( TreeColumn column, /* Column token. */ int *x, int *y, /* Out: window coordinates. */ int *w, int *h /* Out: width and height. */ ) { TreeCtrl *tree = column->tree; int left = 0 - tree->xOrigin; if (!tree->showHeader || !TreeColumn_Visible(column)) return -1; *y = Tree_HeaderTop(tree); *h = Tree_HeaderHeight(tree); if (column == tree->columnTail) { *x = Tree_WidthOfColumns(tree) - tree->xOrigin; *w = 1; /* xxx */ return 0; } /* Get width (and update column layout) */ *w = TreeColumn_UseWidth(column); switch (TreeColumn_Lock(column)) { case COLUMN_LOCK_LEFT: left = Tree_BorderLeft(tree); break; case COLUMN_LOCK_NONE: break; case COLUMN_LOCK_RIGHT: left = Tree_ContentRight(tree); break; } *x = left + TreeColumn_Offset(column); return 0; } /* *-------------------------------------------------------------- * * Tree_HeaderUnderPoint -- * * Return a TreeColumn whose header contains the given coordinates. * * Results: * TreeColumn token or NULL if no column contains the point. * * Side effects: * Column layout will be updated if needed. * *-------------------------------------------------------------- */ TreeColumn Tree_HeaderUnderPoint( TreeCtrl *tree, /* Widget info. */ int *x_, int *y_, /* In: window coordinates. * Out: coordinates relative to top-left * corner of the returned column. */ int *w, int *h, /* Returned width and height. */ int nearest /* TRUE if the column nearest the coordinates * should be returned. */ ) { Tk_Window tkwin = tree->tkwin; int x = *x_, y = *y_; int left, top, width, height; TreeColumn column = tree->columns; int hit; hit = Tree_HitTest(tree, x, y); if (!nearest && (hit != TREE_AREA_HEADER)) return NULL; if (nearest) { if (x < Tree_BorderLeft(tree)) x = Tree_BorderLeft(tree); if (x >= Tree_BorderRight(tree)) x = Tree_BorderRight(tree) - 1; if (y < Tree_BorderTop(tree)) y = Tree_BorderTop(tree); if (y >= Tree_ContentTop(tree)) y = Tree_ContentTop(tree) - 1; } /* Test the columns in reverse of drawing order. */ column = tree->columnLockRight; while ((column != NULL) && (TreeColumn_Lock(column) == COLUMN_LOCK_RIGHT)) { if (TreeColumn_Bbox(column, &left, &top, &width, &height) == 0) { if ((x >= left) && (x < left + width)) { goto done; } } column = TreeColumn_Next(column); } column = tree->columnLockLeft; while ((column != NULL) && (TreeColumn_Lock(column) == COLUMN_LOCK_LEFT)) { if (TreeColumn_Bbox(column, &left, &top, &width, &height) == 0) { if ((x >= left) && (x < left + width)) { goto done; } } column = TreeColumn_Next(column); } column = tree->columnLockNone; while ((column != NULL) && (TreeColumn_Lock(column) == COLUMN_LOCK_NONE)) { if (TreeColumn_Bbox(column, &left, &top, &width, &height) == 0) { if ((x >= left) && (x < left + width)) { goto done; } } column = TreeColumn_Next(column); } column = tree->columnTail; left = Tree_WidthOfColumns(tree) - tree->xOrigin; width = Tk_Width(tkwin) - left; done: (*x_) = x - left; (*y_) = y - Tree_HeaderTop(tree); (*w) = width; (*h) = Tree_HeaderHeight(tree); return column; } /* *---------------------------------------------------------------------- * * LayoutColumns -- * * Calculates the display width and horizontal offset of a range * of columns. * * Results: * The .useWidth and .offset fields of every column in the range * are updated. * The result is the sum of the widths of all visible columns in the * range. * * Side effects: * The size of elements and styles may be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ static int LayoutColumns( TreeColumn first, /* First column to update. All columns * with the same -lock value are updated. */ TreeColumn *visPtr, /* Out: first visible column. */ int *countVisPtr /* Out: number of visible columns. */ ) { TreeCtrl *tree; TreeColumn column; int width, visWidth, totalWidth = 0; int numExpand = 0, numSqueeze = 0; #ifdef UNIFORM_GROUP Tcl_HashEntry *hPtr; Tcl_HashSearch search; UniformGroup *uniform; int uniformCount = 0; #endif if (visPtr != NULL) (*visPtr) = NULL; (*countVisPtr) = 0; if (first == NULL) return 0; tree = first->tree; #ifdef UNIFORM_GROUP /* Initialize the .minSize field of every uniform group. */ hPtr = Tcl_FirstHashEntry(&tree->uniformGroupHash, &search); while (hPtr != NULL) { uniform = (UniformGroup *) Tcl_GetHashValue(hPtr); uniform->minSize = 0; hPtr = Tcl_NextHashEntry(&search); } #endif /* * Determine the initial display width of each column. This will be: * a) the column's -width option (a fixed width), or * b) the maximum of: * 1) the width requested by the column's header * 2) the width requested by each item style in that column * For b) the width is clipped to -minwidth and -maxwidth. */ column = first; while (column != NULL && column->lock == first->lock) { if (column->visible) { if (column->widthObj != NULL) width = column->width; else { width = TreeColumn_WidthOfItems(column); width = MAX(width, TreeColumn_NeededWidth(column)); width = MAX(width, TreeColumn_MinWidth(column)); if (TreeColumn_MaxWidth(column) != -1) width = MIN(width, TreeColumn_MaxWidth(column)); #ifdef UNIFORM_GROUP /* Track the maximum requested width of every column in this * column's uniform group considering -weight. */ if (column->uniform != NULL) { int weight = MAX(column->weight, 1); int minSize = (width + weight - 1) / weight; if (minSize > column->uniform->minSize) column->uniform->minSize = minSize; uniformCount++; } if (column->expand) numExpand += MAX(column->weight, 0); if (column->squeeze) numSqueeze += MAX(column->weight, 0); #else if (column->expand) numExpand++; if (column->squeeze) numSqueeze++; #endif } if (visPtr != NULL && (*visPtr) == NULL) (*visPtr) = column; (*countVisPtr)++; } else width = 0; column->useWidth = width; totalWidth += width; column = column->next; } #ifdef UNIFORM_GROUP /* Apply the -uniform and -weight options. */ if (uniformCount > 0) { column = first; while (column != NULL && column->lock == first->lock) { if (column->visible && column->widthObj == NULL && column->uniform != NULL) { int weight = MAX(column->weight, 1); width = column->uniform->minSize * weight; if (column->maxWidthObj != NULL) width = MIN(width, column->maxWidth); totalWidth -= column->useWidth; column->useWidth = width; totalWidth += width; } column = column->next; } } #endif /* UNIFORM_GROUP */ /* Locked columns don't squeeze or expand. */ if (first->lock != COLUMN_LOCK_NONE) goto doOffsets; visWidth = Tree_ContentWidth(tree); if (visWidth <= 0) goto doOffsets; /* Squeeze columns */ if ((visWidth < totalWidth) && (numSqueeze > 0)) { int spaceRemaining = totalWidth - visWidth; while ((spaceRemaining > 0) && (numSqueeze > 0)) { int each = (spaceRemaining >= numSqueeze) ? spaceRemaining / numSqueeze : 1; numSqueeze = 0; column = first; while (column != NULL && column->lock == first->lock) { if (column->visible && column->squeeze && (column->widthObj == NULL)) { int min = MAX(0, TreeColumn_MinWidth(column)); if (column->useWidth > min) { int sub = MIN(each, column->useWidth - min); column->useWidth -= sub; spaceRemaining -= sub; if (!spaceRemaining) break; if (column->useWidth > min) numSqueeze++; } } column = column->next; } } } /* Expand columns */ if ((visWidth > totalWidth) && (numExpand > 0)) { int spaceRemaining = visWidth - totalWidth; while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? spaceRemaining / numExpand : 1; numExpand = 0; column = first; while (column != NULL && column->lock == first->lock) { #ifdef UNIFORM_GROUP int weight = MAX(column->weight, 0); if (column->visible && column->expand && weight && (column->widthObj == NULL)) { int max = TreeColumn_MaxWidth(column); if ((max == -1) || (column->useWidth < max)) { int eachW = MIN(each * weight, spaceRemaining); int add = (max == -1) ? eachW : MIN(eachW, max - column->useWidth); column->useWidth += add; spaceRemaining -= add; if (!spaceRemaining) break; if ((max == -1) || (column->useWidth < max)) numExpand += weight; #else if (column->visible && column->expand && (column->widthObj == NULL)) { int max = TreeColumn_MaxWidth(column); if ((max == -1) || (column->useWidth < max)) { int add = (max == -1) ? each : MIN(each, max - column->useWidth); column->useWidth += add; spaceRemaining -= add; if (!spaceRemaining) break; if ((max == -1) || (column->useWidth < max)) numExpand++; #endif } } column = column->next; } } } doOffsets: /* Calculate the horizontal offset of each column in the range. * The total width is recalculated as well (needed anyway if any * columns were expanded or squeezed). */ totalWidth = 0; column = first; while (column != NULL && column->lock == first->lock) { if (column->visible) { column->offset = totalWidth; totalWidth += column->useWidth; } column = column->next; } return totalWidth; } /* *---------------------------------------------------------------------- * * Tree_WidthOfColumns -- * * Return the total display width of all non-locked columns (except * the tail). * The width is only recalculated if it is marked out-of-date. * Other fields of the TreeCtrl are updated to reflect the current * arrangement of columns. * * Results: * Pixel width. * * Side effects: * The size of elements and styles may be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ int Tree_WidthOfColumns( TreeCtrl *tree /* Widget info. */ ) { /* This gets called when the layout of all columns needs to be current. * So update the layout of the left- and right-locked columns too. */ (void) Tree_WidthOfLeftColumns(tree); (void) Tree_WidthOfRightColumns(tree); if (tree->widthOfColumns >= 0) return tree->widthOfColumns; tree->widthOfColumns = LayoutColumns( tree->columnLockNone, &tree->columnVis, &tree->columnCountVis); if (tree->columnTree != NULL && TreeColumn_Visible(tree->columnTree)) { tree->columnTreeLeft = tree->columnTree->offset; tree->columnTreeVis = TRUE; } else { tree->columnTreeLeft = 0; tree->columnTreeVis = FALSE; } return tree->widthOfColumns; } /* *---------------------------------------------------------------------- * * Tree_WidthOfLeftColumns -- * * Return the total display width of all left-locked columns. * The width is only recalculated if it is marked out-of-date. * Other fields of the TreeCtrl are updated to reflect the current * arrangement of columns. * * Results: * Pixel width. * * Side effects: * The size of elements and styles may be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ int Tree_WidthOfLeftColumns( TreeCtrl *tree /* Widget info. */ ) { int showLocked = tree->vertical && (tree->wrapMode == TREE_WRAP_NONE); if (!showLocked) { tree->columnCountVisLeft = 0; return tree->widthOfColumnsLeft = 0; } if (tree->widthOfColumnsLeft < 0) { tree->widthOfColumnsLeft = LayoutColumns( tree->columnLockLeft, NULL, &tree->columnCountVisLeft); } return tree->widthOfColumnsLeft; } /* *---------------------------------------------------------------------- * * Tree_WidthOfRightColumns -- * * Return the total display width of all right-locked columns. * The width is only recalculated if it is marked out-of-date. * Other fields of the TreeCtrl are updated to reflect the current * arrangement of columns. * * Results: * Pixel width. * * Side effects: * The size of elements and styles may be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ int Tree_WidthOfRightColumns( TreeCtrl *tree /* Widget info. */ ) { int showLocked = tree->vertical && (tree->wrapMode == TREE_WRAP_NONE); if (!showLocked) { tree->columnCountVisRight = 0; return tree->widthOfColumnsRight = 0; } if (tree->widthOfColumnsRight < 0) { tree->widthOfColumnsRight = LayoutColumns( tree->columnLockRight, NULL, &tree->columnCountVisRight); } return tree->widthOfColumnsRight; } /* *---------------------------------------------------------------------- * * Tree_InitColumns -- * * Perform column-related initialization when a new TreeCtrl is * created. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ void Tree_InitColumns( TreeCtrl *tree /* Widget info. */ ) { TreeColumn column; column = Column_Alloc(tree); column->id = -1; tree->columnTail = column; tree->nextColumnId = 0; tree->columnCount = 0; Column_Config(column, 0, NULL, TRUE); tree->columnDrag.optionTable = Tk_CreateOptionTable(tree->interp, dragSpecs); (void) Tk_InitOptions(tree->interp, (char *) tree, tree->columnDrag.optionTable, tree->tkwin); #ifdef UNIFORM_GROUP Tcl_InitHashTable(&tree->uniformGroupHash, TCL_STRING_KEYS); #endif } /* *---------------------------------------------------------------------- * * Tree_FreeColumns -- * * Free column-related resources for a deleted TreeCtrl. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void Tree_FreeColumns( TreeCtrl *tree /* Widget info. */ ) { TreeColumn column = tree->columns; while (column != NULL) { column = Column_Free(column); } Column_Free(tree->columnTail); tree->columnCount = 0; #ifdef UNIFORM_GROUP Tcl_DeleteHashTable(&tree->uniformGroupHash); #endif } int TreeColumn_InitInterp( Tcl_Interp *interp /* Current interpreter. */ ) { Tk_OptionSpec *specPtr; Tcl_DString dString; specPtr = OptionSpec_Find(columnSpecs, "-background"); if (specPtr->defValue == NULL) { Tcl_DStringInit(&dString); Tcl_DStringAppendElement(&dString, DEF_BUTTON_BG_COLOR); Tcl_DStringAppendElement(&dString, "normal"); Tcl_DStringAppendElement(&dString, DEF_BUTTON_ACTIVE_BG_COLOR); Tcl_DStringAppendElement(&dString, ""); specPtr->defValue = ckalloc(Tcl_DStringLength(&dString) + 1); strcpy((char*)specPtr->defValue, Tcl_DStringValue(&dString)); Tcl_DStringFree(&dString); } PerStateCO_Init(columnSpecs, "-arrowbitmap", &pstBitmap, ColumnStateFromObj); PerStateCO_Init(columnSpecs, "-arrowimage", &pstImage, ColumnStateFromObj); PerStateCO_Init(columnSpecs, "-background", &pstBorder, ColumnStateFromObj); return TCL_OK; } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeElem.h0000644000175000017500000001151510562100026024700 0ustar domibeldomibel/* * tkTreeElem.h -- * * This module is the header for elements in treectrl widgets. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: tkTreeElem.h,v 1.1 2007-02-06 13:18:14 barre Exp $ */ typedef struct ElementType ElementType; typedef struct Element Element; typedef struct ElementArgs ElementArgs; struct ElementArgs { TreeCtrl *tree; Element *elem; int state; struct { TreeItem item; TreeItemColumn column; } create; struct { int noop; } delete; struct { int objc; Tcl_Obj *CONST *objv; int flagSelf; TreeItem item; TreeItemColumn column; } config; struct { int x; int y; int width; int height; #define STICKY_W 0x1000 /* These values must match ELF_STICKY_xxx */ #define STICKY_N 0x2000 #define STICKY_E 0x4000 #define STICKY_S 0x8000 int sticky; Drawable drawable; int bounds[4]; } display; struct { int fixedWidth; int fixedHeight; int maxWidth; int maxHeight; int width; int height; } needed; struct { int fixedWidth; int height; } height; struct { int flagTree; int flagMaster; int flagSelf; } change; struct { int state1; int state2; } states; struct { Tcl_Obj *obj; } actual; struct { int visible; } screen; }; struct ElementType { char *name; /* "image", "text" */ int size; /* size of an Element */ Tk_OptionSpec *optionSpecs; Tk_OptionTable optionTable; int (*createProc)(ElementArgs *args); void (*deleteProc)(ElementArgs *args); int (*configProc)(ElementArgs *args); void (*displayProc)(ElementArgs *args); void (*neededProc)(ElementArgs *args); void (*heightProc)(ElementArgs *args); int (*changeProc)(ElementArgs *args); int (*stateProc)(ElementArgs *args); int (*undefProc)(ElementArgs *args); int (*actualProc)(ElementArgs *args); void (*onScreenProc)(ElementArgs *args); ElementType *next; }; /* list of these for each style */ struct Element { Tk_Uid name; /* "elem2", "eText" etc */ ElementType *typePtr; Element *master; /* NULL if this is master */ DynamicOption *options; /* Dynamically-allocated options. */ /* type-specific data here */ }; extern ElementType elemTypeBitmap; extern ElementType elemTypeBorder; extern ElementType elemTypeCheckButton; extern ElementType elemTypeImage; extern ElementType elemTypeRect; extern ElementType elemTypeText; extern ElementType elemTypeWindow; #define ELEMENT_TYPE_MATCHES(t1,t2) ((t1)->name == (t2)->name) /***** ***** *****/ extern int Element_GetSortData(TreeCtrl *tree, Element *elem, int type, long *lv, double *dv, char **sv); typedef struct TreeIterate_ *TreeIterate; extern int TreeElement_TypeFromObj(TreeCtrl *tree, Tcl_Obj *objPtr, ElementType **typePtrPtr); extern void Tree_RedrawElement(TreeCtrl *tree, TreeItem item, Element *elem); extern TreeIterate Tree_ElementIterateBegin(TreeCtrl *tree, ElementType *elemTypePtr); extern TreeIterate Tree_ElementIterateNext(TreeIterate iter_); extern Element *Tree_ElementIterateGet(TreeIterate iter_); extern void Tree_ElementIterateChanged(TreeIterate iter_, int mask); extern void Tree_ElementChangedItself(TreeCtrl *tree, TreeItem item, TreeItemColumn column, Element *elem, int flags, int mask); typedef struct TreeCtrlStubs TreeCtrlStubs; struct TreeCtrlStubs { int (*TreeCtrl_RegisterElementType)(Tcl_Interp *interp, ElementType *typePtr); void (*Tree_RedrawElement)(TreeCtrl *tree, TreeItem item, Element *elem); TreeIterate (*Tree_ElementIterateBegin)(TreeCtrl *tree, ElementType *elemTypePtr); TreeIterate (*Tree_ElementIterateNext)(TreeIterate iter_); Element *(*Tree_ElementIterateGet)(TreeIterate iter_); void (*Tree_ElementIterateChanged)(TreeIterate iter_, int mask); void (*PerStateInfo_Free)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo); int (*PerStateInfo_FromObj)(TreeCtrl *tree, StateFromObjProc proc, PerStateType *typePtr, PerStateInfo *pInfo); PerStateData *(*PerStateInfo_ForState)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state, int *match); Tcl_Obj *(*PerStateInfo_ObjForState)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state, int *match); int (*PerStateInfo_Undefine)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state); PerStateType *pstBoolean; int (*PerStateBoolean_ForState)(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); void (*PSTSave)(PerStateInfo *pInfo, PerStateInfo *pSave); void (*PSTRestore)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, PerStateInfo *pSave); int (*TreeStateFromObj)(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn); int (*BooleanCO_Init)(Tk_OptionSpec *optionTable, CONST char *optionName); int (*StringTableCO_Init)(Tk_OptionSpec *optionTable, CONST char *optionName, CONST char **tablePtr); }; kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeCtrl.h0000644000175000017500000013211210746173220024731 0ustar domibeldomibel/* * tkTreeCtrl.h -- * * This module is the header for treectrl widgets for the Tk toolkit. * * Copyright (c) 2002-2006 Tim Baker * Copyright (c) 2002-2003 Christian Krone * Copyright (c) 2003 ActiveState Corporation * * RCS: @(#) $Id: tkTreeCtrl.h,v 1.3 2008-01-24 20:35:28 barre Exp $ */ #include "vtkTcl.h" #include "vtkTk.h" #include "vtkTkInternals.h" #ifdef MAC_OSX_TK #ifndef HAVE_LIMITS_H #define HAVE_LIMITS_H #endif #ifndef HAVE_UNISTD_H #define HAVE_UNISTD_H #endif #endif #include "tkPort.h" #include "default.h" #include "tkInt.h" #include "qebind.h" #ifdef HAVE_DBWIN_H #include "dbwin.h" #else /* HAVE_DBWIN_H */ #define dbwin printf #endif /* HAVE_DBWIN_H */ #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif #define SELECTION_VISIBLE #define ALLOC_HAX #define DEPRECATED typedef struct TreeCtrl TreeCtrl; typedef struct TreeColumn_ *TreeColumn; typedef struct TreeDInfo_ *TreeDInfo; typedef struct TreeDragImage_ *TreeDragImage; typedef struct TreeItem_ *TreeItem; typedef struct TreeItemColumn_ *TreeItemColumn; typedef struct TreeItemDInfo_ *TreeItemDInfo; typedef struct TreeMarquee_ *TreeMarquee; typedef struct TreeItemRInfo_ *TreeItemRInfo; typedef struct TreeStyle_ *TreeStyle; typedef struct TreeElement_ *TreeElement; typedef struct TreeThemeData_ *TreeThemeData; /*****/ typedef struct PerStateInfo PerStateInfo; typedef struct PerStateData PerStateData; typedef struct PerStateType PerStateType; /* There is one of these for each XColor, Tk_Font, Tk_Image etc */ struct PerStateData { int stateOff; int stateOn; /* Type-specific fields go here */ }; struct PerStateInfo { #ifdef TREECTRL_DEBUG PerStateType *type; #endif Tcl_Obj *obj; int count; PerStateData *data; }; typedef int (*PerStateType_FromObjProc)(TreeCtrl *, Tcl_Obj *, PerStateData *); typedef void (*PerStateType_FreeProc)(TreeCtrl *, PerStateData *); struct PerStateType { CONST char *name; int size; PerStateType_FromObjProc fromObjProc; PerStateType_FreeProc freeProc; }; /*****/ /* * A TreePtrList is used for dynamically-growing lists of ClientData pointers. * A TreePtrList is NULL-terminated. * Based on Tcl_DString code. */ #define TIL_STATIC_SPACE 128 typedef struct TreePtrList TreePtrList; typedef TreePtrList TreeItemList; typedef TreePtrList TreeColumnList; struct TreePtrList { TreeCtrl *tree; ClientData *pointers; /* NULL-terminated list of pointers. */ int count; /* Number of items. */ int space; /* Number of slots pointed to by pointers[]. */ ClientData pointerSpace[TIL_STATIC_SPACE]; /* Space to use in common case * where the list is small. */ }; enum { LEFT, TOP, RIGHT, BOTTOM }; struct TreeCtrlDebug { Tk_OptionTable optionTable; int enable; /* Turn all debugging on/off */ int data; /* Debug data structures */ int display; /* Debug display routines */ int textLayout; /* Debug text layout */ int displayDelay; /* Delay between copy/draw operations */ XColor *eraseColor; /* Erase "invalidated" areas */ GC gcErase; /* for eraseColor */ XColor *drawColor; /* Erase about-to-be-drawn areas */ GC gcDraw; /* for eraseColor */ }; struct TreeCtrlColumnDrag { Tk_OptionTable optionTable; int enable; /* -enable */ TreeColumn column; /* -imagecolumn */ Tcl_Obj *offsetObj; /* -imageoffset */ int offset; /* -imageoffset */ XColor *color; /* -imagecolor */ int alpha; /* -imagealpha */ TreeColumn indColumn; /* -indicatorcolumn */ XColor *indColor; /* -indicatorcolor */ int indSide; /* -indicatorside */ }; struct TreeCtrl { /* Standard stuff */ Tk_Window tkwin; Display *display; Tcl_Interp *interp; Tcl_Command widgetCmd; Tk_OptionTable optionTable; /* Configuration options */ Tcl_Obj *fgObj; /* -foreground */ XColor *fgColorPtr; /* -foreground */ Tcl_Obj *borderWidthObj; /* -borderwidth */ int borderWidth; /* -borderwidth */ Tk_3DBorder border; /* -background */ Tk_Cursor cursor; /* Current cursor for window, or None. */ int relief; /* -relief */ Tcl_Obj *highlightWidthObj; /* -highlightthickness */ int highlightWidth; /* -highlightthickness */ XColor *highlightBgColorPtr; /* -highlightbackground */ XColor *highlightColorPtr; /* -highlightcolor */ char *xScrollCmd; /* -xscrollcommand */ char *yScrollCmd; /* -yscrollcommand */ Tcl_Obj *xScrollDelay; /* -xscrolldelay: used by scripts */ Tcl_Obj *yScrollDelay; /* -yscrolldelay: used by scripts */ int xScrollIncrement; /* -xscrollincrement */ int yScrollIncrement; /* -yscrollincrement */ Tcl_Obj *scrollMargin; /* -scrollmargin: used by scripts */ char *takeFocus; /* -takfocus */ Tcl_Obj *fontObj; /* -font */ Tk_Font tkfont; /* -font */ int showButtons; /* boolean: Draw expand/collapse buttons */ int showLines; /* boolean: Draw lines connecting parent to * child */ int showRootLines; /* boolean: Draw lines connecting children * of the root item */ int showRoot; /* boolean: Draw the unique root item */ int showRootButton; /* boolean: Draw expand/collapse button for * root item */ int showHeader; /* boolean: show column titles */ Tcl_Obj *indentObj; /* pixels: offset of child relative to * parent */ int indent; /* pixels: offset of child relative to * parent */ char *selectMode; /* -selectmode: used by scripts only */ Tcl_Obj *itemHeightObj; /* -itemheight: Fixed height for all items (unless overridden) */ int itemHeight; /* -itemheight */ Tcl_Obj *minItemHeightObj; /* -minitemheight: Minimum height for all items */ int minItemHeight; /* -minitemheight */ Tcl_Obj *itemWidthObj; /* -itemwidth */ int itemWidth; /* -itemwidth */ int itemWidthEqual; /* -itemwidthequal */ Tcl_Obj *itemWidMultObj; /* -itemwidthmultiple */ int itemWidMult; /* -itemwidthmultiple */ Tcl_Obj *widthObj; /* -width */ int width; /* -width */ Tcl_Obj *heightObj; /* -height */ int height; /* -height */ TreeColumn columnTree; /* column where buttons/lines are drawn */ #define DOUBLEBUFFER_NONE 0 #define DOUBLEBUFFER_ITEM 1 #define DOUBLEBUFFER_WINDOW 2 int doubleBuffer; /* -doublebuffer */ XColor *buttonColor; /* -buttoncolor */ Tcl_Obj *buttonSizeObj; /* -buttonSize */ int buttonSize; /* -buttonsize */ Tcl_Obj *buttonThicknessObj;/* -buttonthickness */ int buttonThickness; /* -buttonthickness */ XColor *lineColor; /* -linecolor */ Tcl_Obj *lineThicknessObj; /* -linethickness */ int lineThickness; /* -linethickness */ #define LINE_STYLE_DOT 0 #define LINE_STYLE_SOLID 1 int lineStyle; /* -linestyle */ int vertical; /* -orient */ Tcl_Obj *wrapObj; /* -wrap */ PerStateInfo buttonImage; /* -buttonimage */ PerStateInfo buttonBitmap; /* -buttonbitmap */ char *backgroundImageString; /* -backgroundimage */ int useIndent; /* MAX of open/closed button width and * indent */ #define BG_MODE_COLUMN 0 #define BG_MODE_ORDER 1 #define BG_MODE_ORDERVIS 2 #define BG_MODE_ROW 3 #ifdef DEPRECATED #define BG_MODE_INDEX 4 /* compatibility */ #define BG_MODE_VISINDEX 5 /* compatibility */ #endif /* DEPRECATED */ int backgroundMode; /* -backgroundmode */ int columnResizeMode; /* -columnresizemode */ int *itemPadX; /* -itempadx */ Tcl_Obj *itemPadXObj; /* -itempadx */ int *itemPadY; /* -itempady */ Tcl_Obj *itemPadYObj; /* -itempady */ struct TreeCtrlDebug debug; struct TreeCtrlColumnDrag columnDrag; /* Other stuff */ int gotFocus; /* flag */ int deleted; /* flag */ int updateIndex; /* flag */ int isActive; /* flag: mac & win "active" toplevel */ int inset; /* borderWidth + highlightWidth */ int xOrigin; /* offset from content x=0 to window x=0 */ int yOrigin; /* offset from content y=0 to window y=0 */ GC copyGC; GC textGC; GC buttonGC; GC lineGC; Tk_Image backgroundImage; /* -backgroundimage */ int useTheme; /* -usetheme */ char *itemPrefix; /* -itemprefix */ char *columnPrefix; /* -columnprefix */ int prevWidth; int prevHeight; int drawableXOrigin; int drawableYOrigin; TreeColumn columns; /* List of columns */ TreeColumn columnLast; /* Last in list of columns */ TreeColumn columnTail; /* Last infinitely-wide column */ TreeColumn columnVis; /* First visible column */ int columnCount; /* Number of columns */ int columnCountVis; /* Number of visible columns */ int headerHeight; /* Height of column titles */ int widthOfColumns; /* Sum of column widths */ int columnTreeLeft; /* left of column where buttons/lines are * drawn */ int columnTreeVis; /* TRUE if columnTree is visible */ int columnBgCnt; /* Max -itembackground colors */ #define COLUMN_LOCK_LEFT 0 #define COLUMN_LOCK_NONE 1 #define COLUMN_LOCK_RIGHT 2 TreeColumn columnLockLeft; /* First left-locked column */ TreeColumn columnLockNone; /* First unlocked column */ TreeColumn columnLockRight; /* First right-locked column */ int widthOfColumnsLeft; /* Sum of left-locked column widths */ int widthOfColumnsRight; /* Sum of right-locked column widths */ int columnCountVisLeft; /* Number of visible left-locked columns */ int columnCountVisRight; /* Number of visible right-locked columns */ #define UNIFORM_GROUP #ifdef UNIFORM_GROUP Tcl_HashTable uniformGroupHash; /* -uniform -> UniformGroup */ #endif TreeItem root; TreeItem activeItem; TreeItem anchorItem; int nextItemId; int nextColumnId; Tcl_HashTable itemHash; /* TreeItem.id -> TreeItem */ Tcl_HashTable itemSpansHash; /* TreeItem -> nothing */ Tcl_HashTable elementHash; /* Element.name -> Element */ Tcl_HashTable styleHash; /* Style.name -> Style */ Tcl_HashTable imageNameHash; /* image name -> TreeImageRef */ Tcl_HashTable imageTokenHash; /* Tk_Image -> TreeImageRef */ int depth; /* max depth of items under root */ int itemCount; /* Total number of items */ int itemVisCount; /* Total number of ReallyVisible() items */ QE_BindingTable bindingTable; TreeDragImage dragImage; TreeMarquee marquee; TreeDInfo dInfo; int selectCount; /* Number of selected items */ Tcl_HashTable selection; /* Selected items */ #define TREE_WRAP_NONE 0 #define TREE_WRAP_ITEMS 1 #define TREE_WRAP_PIXELS 2 #define TREE_WRAP_WINDOW 3 int wrapMode; /* TREE_WRAP_xxx */ int wrapArg; /* Number of items, number of pixels */ int totalWidth; /* Max/Sum of all TreeRanges */ int totalHeight; /* Max/Sum of all TreeRanges */ struct { Tcl_Obj *xObj; int x; /* Window coords */ int sx; /* Window coords */ int onScreen; } columnProxy; char *stateNames[32]; /* Names of static and dynamic item states */ int scanX; /* [scan mark] and [scan dragto] */ int scanY; int scanXOrigin; int scanYOrigin; Tk_OptionTable styleOptionTable; #ifdef DEPRECATED struct { Tcl_Obj *stylesObj; TreeStyle *styles; int numStyles; } defaultStyle; #endif /* DEPRECATED */ Tk_OptionTable itemOptionTable; int itemPrefixLen; /* -itemprefix */ int columnPrefixLen; /* -columnprefix */ #ifdef ALLOC_HAX ClientData allocData; #endif int preserveItemRefCnt; /* Ref count so items-in-use aren't freed. */ TreeItemList preserveItemList; /* List of items to be deleted when * preserveItemRefCnt==0. */ struct { Tcl_Obj *yObj; int y; /* Window coords */ int sy; /* Window coords */ int onScreen; } rowProxy; char *optionHax[64]; /* Used by OptionHax_xxx */ int optionHaxCnt; /* Used by OptionHax_xxx */ TreeThemeData themeData; }; #define TREE_CONF_FONT 0x0001 #define TREE_CONF_ITEMSIZE 0x0002 #define TREE_CONF_INDENT 0x0004 #define TREE_CONF_WRAP 0x0008 #define TREE_CONF_BUTIMG 0x0010 #define TREE_CONF_BUTBMP 0x0020 /* ... */ #define TREE_CONF_RELAYOUT 0x0100 #define TREE_CONF_REDISPLAY 0x0200 #define TREE_CONF_FG 0x0400 #define TREE_CONF_PROXY 0x0800 #define TREE_CONF_BUTTON 0x1000 #define TREE_CONF_LINE 0x2000 #define TREE_CONF_DEFSTYLE 0x4000 #define TREE_CONF_BG_IMAGE 0x8000 #define TREE_CONF_THEME 0x00010000 extern void Tree_AddItem(TreeCtrl *tree, TreeItem item); extern void Tree_RemoveItem(TreeCtrl *tree, TreeItem item); extern Tk_Image Tree_GetImage(TreeCtrl *tree, char *imageName); extern void Tree_FreeImage(TreeCtrl *tree, Tk_Image image); extern void Tree_UpdateScrollbarX(TreeCtrl *tree); extern void Tree_UpdateScrollbarY(TreeCtrl *tree); extern void Tree_AddToSelection(TreeCtrl *tree, TreeItem item); extern void Tree_RemoveFromSelection(TreeCtrl *tree, TreeItem item); extern void Tree_PreserveItems(TreeCtrl *tree); extern void Tree_ReleaseItems(TreeCtrl *tree); #define STATE_OP_ON 0 #define STATE_OP_OFF 1 #define STATE_OP_TOGGLE 2 #define SFO_NOT_OFF 0x0001 #define SFO_NOT_TOGGLE 0x0002 #define SFO_NOT_STATIC 0x0004 extern int Tree_StateFromObj(TreeCtrl *tree, Tcl_Obj *obj, int states[3], int *indexPtr, int flags); extern int Tree_StateFromListObj(TreeCtrl *tree, Tcl_Obj *obj, int states[3], int flags); #define Tree_BorderLeft(tree) \ tree->inset #define Tree_BorderTop(tree) \ tree->inset #define Tree_BorderRight(tree) \ (Tk_Width(tree->tkwin) - tree->inset) #define Tree_BorderBottom(tree) \ (Tk_Height(tree->tkwin) - tree->inset) #define Tree_HeaderLeft(tree) \ Tree_BorderLeft(tree) #define Tree_HeaderTop(tree) \ Tree_BorderTop(tree) #define Tree_HeaderRight(tree) \ Tree_BorderRight(tree) #define Tree_HeaderBottom(tree) \ (Tree_BorderTop(tree) + Tree_HeaderHeight(tree)) #define Tree_HeaderWidth(tree) \ (Tree_HeaderRight(tree) - Tree_HeaderLeft(tree)) #define Tree_ContentLeft(tree) \ (Tree_BorderLeft(tree) + Tree_WidthOfLeftColumns(tree)) #define Tree_ContentTop(tree) \ (Tree_BorderTop(tree) + Tree_HeaderHeight(tree)) #define Tree_ContentRight(tree) \ (Tree_BorderRight(tree) - Tree_WidthOfRightColumns(tree)) #define Tree_ContentBottom(tree) \ Tree_BorderBottom(tree) #define Tree_ContentWidth(tree) \ (Tree_ContentRight(tree) - Tree_ContentLeft(tree)) #define Tree_ContentHeight(tree) \ (Tree_ContentBottom(tree) - Tree_ContentTop(tree)) /* tkTreeItem.c */ #define ITEM_ALL ((TreeItem) -1) #define IFO_NOT_MANY 0x0001 /* ItemFromObj flag: > 1 item is not ok */ #define IFO_NOT_NULL 0x0002 /* ItemFromObj flag: can't be NULL */ #define IFO_NOT_ROOT 0x0004 /* ItemFromObj flag: "root" is forbidden */ #define IFO_NOT_ORPHAN 0x0008 /* ItemFromObj flag: item must have a parent */ #define IFO_LIST_ALL 0x0010 /* ItemFromObj flag: return "all" as list */ extern int TreeItemList_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeItemList *items, int flags); extern int TreeItem_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeItem *itemPtr, int flags); typedef struct ItemForEach ItemForEach; struct ItemForEach { TreeCtrl *tree; int error; int all; Tcl_HashSearch search; TreeItem last; TreeItem item; TreeItemList *items; int index; }; extern TreeItem ItemForEach_Start(TreeItemList *items, TreeItemList *item2s, ItemForEach *iter); extern TreeItem ItemForEach_Next(ItemForEach *iter); #define ITEM_FOR_EACH(item, items, item2s, iter) \ for (item = ItemForEach_Start(items, item2s, iter); \ item != NULL; \ item = ItemForEach_Next(iter)) extern void FormatResult(Tcl_Interp *interp, char *fmt, ...); extern void DStringAppendf(Tcl_DString *dString, char *fmt, ...); extern void Tree_Debug(TreeCtrl *tree); extern int TreeItem_Init(TreeCtrl *tree); extern int TreeItem_Debug(TreeCtrl *tree, TreeItem item); extern void TreeItem_OpenClose(TreeCtrl *tree, TreeItem item, int mode); extern void TreeItem_Delete(TreeCtrl *tree, TreeItem item); extern int TreeItem_Deleted(TreeCtrl *tree, TreeItem item); #define STATE_OPEN 0x0001 #define STATE_SELECTED 0x0002 #define STATE_ENABLED 0x0004 #define STATE_ACTIVE 0x0008 #define STATE_FOCUS 0x0010 #define STATE_USER 6 /* first user bit */ extern int TreeItem_GetState(TreeCtrl *tree, TreeItem item_); #define CS_DISPLAY 0x01 #define CS_LAYOUT 0x02 extern int TreeItem_ChangeState(TreeCtrl *tree, TreeItem item_, int stateOff, int stateOn); extern void TreeItem_UndefineState(TreeCtrl *tree, TreeItem item_, int state); extern int TreeItem_GetButton(TreeCtrl *tree, TreeItem item_); extern int TreeItem_GetDepth(TreeCtrl *tree, TreeItem item_); extern int TreeItem_GetID(TreeCtrl *tree, TreeItem item_); extern int TreeItem_SetID(TreeCtrl *tree, TreeItem item_, int id); extern int TreeItem_GetEnabled(TreeCtrl *tree, TreeItem item_); extern int TreeItem_GetSelected(TreeCtrl *tree, TreeItem item_); extern TreeItem TreeItem_GetParent(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_GetNextSibling(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_NextSiblingVisible(TreeCtrl *tree, TreeItem item); extern void TreeItem_SetDInfo(TreeCtrl *tree, TreeItem item, TreeItemDInfo dInfo); extern TreeItemDInfo TreeItem_GetDInfo(TreeCtrl *tree, TreeItem item); extern void TreeItem_SetRInfo(TreeCtrl *tree, TreeItem item, TreeItemRInfo rInfo); extern TreeItemRInfo TreeItem_GetRInfo(TreeCtrl *tree, TreeItem item); extern void TreeItem_AppendChild(TreeCtrl *tree, TreeItem self, TreeItem child); extern void TreeItem_RemoveFromParent(TreeCtrl *tree, TreeItem self); extern int TreeItem_FirstAndLast(TreeCtrl *tree, TreeItem *first, TreeItem *last); extern void TreeItem_ListDescendants(TreeCtrl *tree, TreeItem item_, TreeItemList *items); extern int TreeItem_Height(TreeCtrl *tree, TreeItem self); extern int TreeItem_TotalHeight(TreeCtrl *tree, TreeItem self); extern void TreeItem_InvalidateHeight(TreeCtrl *tree, TreeItem self); extern void TreeItem_SpansInvalidate(TreeCtrl *tree, TreeItem item_); extern int *TreeItem_GetSpans(TreeCtrl *tree, TreeItem item_); extern void TreeItem_Draw(TreeCtrl *tree, TreeItem self, int lock, int x, int y, int width, int height, Drawable drawable, int minX, int maxX, int index); extern void TreeItem_DrawLines(TreeCtrl *tree, TreeItem self, int x, int y, int width, int height, Drawable drawable); extern void TreeItem_DrawButton(TreeCtrl *tree, TreeItem self, int x, int y, int width, int height, Drawable drawable); extern int TreeItem_ReallyVisible(TreeCtrl *tree, TreeItem self); extern void TreeItem_FreeResources(TreeCtrl *tree, TreeItem self); extern void TreeItem_Release(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_RootAncestor(TreeCtrl *tree, TreeItem item_); extern int TreeItem_IsAncestor(TreeCtrl *tree, TreeItem item1, TreeItem item2); extern Tcl_Obj *TreeItem_ToObj(TreeCtrl *tree, TreeItem item); extern void TreeItem_ToIndex(TreeCtrl *tree, TreeItem item, int *absolute, int *visible); extern TreeItem TreeItem_Next(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_NextVisible(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_Prev(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_PrevVisible(TreeCtrl *tree, TreeItem item); extern void TreeItem_Identify(TreeCtrl *tree, TreeItem item_, int lock, int x, int y, char *buf); extern void TreeItem_Identify2(TreeCtrl *tree, TreeItem item_, int x1, int y1, int x2, int y2, Tcl_Obj *listObj); extern int TreeItem_GetRects(TreeCtrl *tree, TreeItem item_, TreeColumn treeColumn, int objc, Tcl_Obj *CONST objv[], XRectangle rects[]); extern int TreeItem_Indent(TreeCtrl *tree, TreeItem item_); extern void Tree_UpdateItemIndex(TreeCtrl *tree); extern void Tree_DeselectHidden(TreeCtrl *tree); extern int TreeItemCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern void TreeItem_UpdateWindowPositions(TreeCtrl *tree, TreeItem item_, int lock, int x, int y, int width, int height); extern void TreeItem_OnScreen(TreeCtrl *tree, TreeItem item_, int onScreen); extern TreeItemColumn TreeItem_GetFirstColumn(TreeCtrl *tree, TreeItem item); extern TreeItemColumn TreeItemColumn_GetNext(TreeCtrl *tree, TreeItemColumn column); extern void TreeItemColumn_InvalidateSize(TreeCtrl *tree, TreeItemColumn column); extern TreeStyle TreeItemColumn_GetStyle(TreeCtrl *tree, TreeItemColumn column); extern int TreeItemColumn_Index(TreeCtrl *tree, TreeItem item_, TreeItemColumn column_); extern void TreeItemColumn_ForgetStyle(TreeCtrl *tree, TreeItemColumn column_); extern int TreeItemColumn_NeededWidth(TreeCtrl *tree, TreeItem item_, TreeItemColumn column_); extern TreeItemColumn TreeItem_FindColumn(TreeCtrl *tree, TreeItem item, int columnIndex); extern int TreeItem_ColumnFromObj(TreeCtrl *tree, TreeItem item, Tcl_Obj *obj, TreeItemColumn *columnPtr, int *indexPtr); extern void TreeItem_RemoveColumns(TreeCtrl *tree, TreeItem item_, int first, int last); extern void TreeItem_RemoveAllColumns(TreeCtrl *tree, TreeItem item_); extern void TreeItem_MoveColumn(TreeCtrl *tree, TreeItem item_, int columnIndex, int beforeIndex); /* tkTreeElem.c */ extern int TreeElement_Init(Tcl_Interp *interp); extern int TreeStateFromObj(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn); extern int StringTableCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, CONST char **tablePtr); typedef struct StyleDrawArgs StyleDrawArgs; struct StyleDrawArgs { TreeCtrl *tree; TreeStyle style; int indent; int x; int y; int width; int height; Drawable drawable; int state; /* STATE_xxx */ Tk_Justify justify; int bounds[4]; }; /* tkTreeStyle.c */ extern int TreeStyle_Init(TreeCtrl *tree); extern int TreeStyle_NeededWidth(TreeCtrl *tree, TreeStyle style_, int state); extern int TreeStyle_NeededHeight(TreeCtrl *tree, TreeStyle style_, int state); extern int TreeStyle_UseHeight(StyleDrawArgs *drawArgs); extern void TreeStyle_Draw(StyleDrawArgs *args); extern void TreeStyle_FreeResources(TreeCtrl *tree, TreeStyle style_); extern void TreeStyle_Free(TreeCtrl *tree); extern int TreeElement_FromObj(TreeCtrl *tree, Tcl_Obj *obj, TreeElement *elemPtr); extern int TreeElement_IsType(TreeCtrl *tree, TreeElement elem_, CONST char *type); extern int TreeStyle_FromObj(TreeCtrl *tree, Tcl_Obj *obj, TreeStyle *stylePtr); extern Tcl_Obj *TreeStyle_ToObj(TreeStyle style_); extern Tcl_Obj *TreeStyle_GetImage(TreeCtrl *tree, TreeStyle style_); extern Tcl_Obj *TreeStyle_GetText(TreeCtrl *tree, TreeStyle style_); extern int TreeStyle_SetImage(TreeCtrl *tree, TreeItem item, TreeItemColumn column, TreeStyle style_, Tcl_Obj *textObj); extern int TreeStyle_SetText(TreeCtrl *tree, TreeItem item, TreeItemColumn column, TreeStyle style_, Tcl_Obj *textObj); extern int TreeStyle_FindElement(TreeCtrl *tree, TreeStyle style_, TreeElement elem_, int *index); extern TreeStyle TreeStyle_NewInstance(TreeCtrl *tree, TreeStyle master); extern int TreeStyle_ElementActual(TreeCtrl *tree, TreeStyle style_, int state, Tcl_Obj *elemObj, Tcl_Obj *obj); extern int TreeStyle_ElementCget(TreeCtrl *tree, TreeItem item, TreeItemColumn column, TreeStyle style_, Tcl_Obj *elemObj, Tcl_Obj *obj); extern int TreeStyle_ElementConfigure(TreeCtrl *tree, TreeItem item, TreeItemColumn column, TreeStyle style_, Tcl_Obj *elemObj, int objc, Tcl_Obj **objv, int *eMask); extern void TreeStyle_ListElements(TreeCtrl *tree, TreeStyle style_); extern TreeStyle TreeStyle_GetMaster(TreeCtrl *tree, TreeStyle style_); extern char *TreeStyle_Identify(StyleDrawArgs *drawArgs, int x, int y); extern void TreeStyle_Identify2(StyleDrawArgs *drawArgs, int x1, int y1, int x2, int y2, Tcl_Obj *listObj); extern int TreeStyle_Remap(TreeCtrl *tree, TreeStyle styleFrom_, TreeStyle styleTo_, int objc, Tcl_Obj *CONST objv[]); extern void TreeStyle_TreeChanged(TreeCtrl *tree, int flagT); #define SORT_ASCII 0 #define SORT_DICT 1 #define SORT_DOUBLE 2 #define SORT_LONG 3 #define SORT_COMMAND 4 extern int TreeStyle_GetSortData(TreeCtrl *tree, TreeStyle style_, int elemIndex, int type, long *lv, double *dv, char **sv); #if 0 extern int TreeStyle_ValidateElements(TreeCtrl *tree, TreeStyle style_, int objc, Tcl_Obj *CONST objv[]); #endif extern int TreeStyle_GetElemRects(StyleDrawArgs *drawArgs, int objc, Tcl_Obj *CONST objv[], XRectangle rects[]); extern int TreeElementCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern int TreeStyleCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern int TreeStyle_ChangeState(TreeCtrl *tree, TreeStyle style_, int state1, int state2); extern void Tree_UndefineState(TreeCtrl *tree, int state); extern int TreeStyle_NumElements(TreeCtrl *tree, TreeStyle style_); extern void TreeStyle_UpdateWindowPositions(StyleDrawArgs *drawArgs); extern void TreeStyle_OnScreen(TreeCtrl *tree, TreeStyle style_, int onScreen); extern int ButtonMaxWidth(TreeCtrl *tree); extern int ButtonHeight(TreeCtrl *tree, int state); /* tkTreeNotify.c */ extern int TreeNotify_Init(TreeCtrl *tree); extern void TreeNotify_OpenClose(TreeCtrl *tree, TreeItem item, int isOpen, int before); extern void TreeNotify_Selection(TreeCtrl *tree, TreeItemList *select, TreeItemList *deselect); extern int TreeNotifyCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern void TreeNotify_ActiveItem(TreeCtrl *tree, TreeItem itemOld, TreeItem itemNew); extern void TreeNotify_Scroll(TreeCtrl *tree, double fractions[2], int vertical); extern void TreeNotify_ItemDeleted(TreeCtrl *tree, TreeItemList *items); extern void TreeNotify_ItemVisibility(TreeCtrl *tree, TreeItemList *v, TreeItemList *h); /* tkTreeColumn.c */ extern int TreeColumn_InitInterp(Tcl_Interp *interp); extern void Tree_InitColumns(TreeCtrl *tree); extern TreeColumn Tree_FindColumn(TreeCtrl *tree, int columnIndex); #define COLUMN_ALL ((TreeColumn) -1) /* Every column. */ #define COLUMN_NTAIL ((TreeColumn) -2) /* Every column but the tail. */ #define CFO_NOT_MANY 0x01 #define CFO_NOT_NULL 0x02 #define CFO_NOT_TAIL 0x04 #define CFO_LIST_ALL 0x08 extern int TreeColumnList_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeColumnList *columns, int flags); extern int TreeColumn_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeColumn *columnPtr, int flags); typedef struct ColumnForEach ColumnForEach; struct ColumnForEach { TreeCtrl *tree; int error; int all; int ntail; TreeColumn current; TreeColumn next; TreeColumn last; TreeColumnList *list; int index; }; extern TreeColumn ColumnForEach_Start(TreeColumnList *columns, TreeColumnList *column2s, ColumnForEach *iter); extern TreeColumn ColumnForEach_Next(ColumnForEach *iter); #define COLUMN_FOR_EACH(column, columns, column2s, iter) \ for (column = ColumnForEach_Start(columns, column2s, iter); \ column != NULL; \ column = ColumnForEach_Next(iter)) extern Tcl_Obj *TreeColumn_ToObj(TreeCtrl *tree, TreeColumn column_); extern int TreeColumnCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern int TreeColumn_GetID(TreeColumn column_); extern int TreeColumn_Index(TreeColumn column_); extern TreeColumn TreeColumn_Next(TreeColumn column_); extern TreeColumn TreeColumn_Prev(TreeColumn column_); extern int TreeColumn_FixedWidth(TreeColumn column_); extern int TreeColumn_MinWidth(TreeColumn column_); extern int TreeColumn_MaxWidth(TreeColumn column_); extern int TreeColumn_NeededWidth(TreeColumn column_); extern int TreeColumn_UseWidth(TreeColumn column_); extern int TreeColumn_Offset(TreeColumn column_); extern Tk_Justify TreeColumn_Justify(TreeColumn column_); #ifdef DEPRECATED extern int TreeColumn_WidthHack(TreeColumn column_); extern int TreeColumn_StepWidth(TreeColumn column_); #endif extern TreeStyle TreeColumn_ItemStyle(TreeColumn column_); extern void TreeColumn_StyleDeleted(TreeColumn column_, TreeStyle style); extern int TreeColumn_Visible(TreeColumn column_); extern int TreeColumn_Squeeze(TreeColumn column_); extern int TreeColumn_BackgroundCount(TreeColumn column_); extern GC TreeColumn_BackgroundGC(TreeColumn column_, int which); extern void Tree_DrawHeader(TreeCtrl *tree, Drawable drawable, int x, int y); extern int TreeColumn_WidthOfItems(TreeColumn column_); extern void TreeColumn_InvalidateWidth(TreeColumn column_); extern void TreeColumn_Init(TreeCtrl *tree); extern void Tree_FreeColumns(TreeCtrl *tree); extern void Tree_InvalidateColumnWidth(TreeCtrl *tree, TreeColumn column); extern void Tree_InvalidateColumnHeight(TreeCtrl *tree, TreeColumn column); extern int Tree_HeaderHeight(TreeCtrl *tree); extern int TreeColumn_Bbox(TreeColumn column, int *x, int *y, int *w, int *h); extern TreeColumn Tree_HeaderUnderPoint(TreeCtrl *tree, int *x_, int *y_, int *w, int *h, int nearest); extern int TreeColumn_Lock(TreeColumn column_); extern int Tree_WidthOfColumns(TreeCtrl *tree); extern int Tree_WidthOfLeftColumns(TreeCtrl *tree); extern int Tree_WidthOfRightColumns(TreeCtrl *tree); extern void TreeColumn_TreeChanged(TreeCtrl *tree, int flagT); /* tkTreeDrag.c */ extern int TreeDragImage_Init(TreeCtrl *tree); extern void TreeDragImage_Free(TreeDragImage dragImage_); extern void TreeDragImage_Display(TreeDragImage dragImage_); extern void TreeDragImage_Undisplay(TreeDragImage dragImage_); extern void TreeDragImage_Draw(TreeDragImage dragImage_, Drawable drawable, int x, int y); extern int DragImageCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* tkTreeMarquee.c */ extern int TreeMarquee_Init(TreeCtrl *tree); extern void TreeMarquee_Free(TreeMarquee marquee_); extern void TreeMarquee_Draw(TreeMarquee marquee_, Drawable drawable, int x, int y); extern void TreeMarquee_Display(TreeMarquee marquee_); extern void TreeMarquee_Undisplay(TreeMarquee marquee_); extern int TreeMarqueeCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* tkTreeDisplay.c */ extern int Tree_TotalWidth(TreeCtrl *tree); extern int Tree_TotalHeight(TreeCtrl *tree); extern TreeItem Tree_ItemUnderPoint(TreeCtrl *tree, int *x, int *y, int nearest); extern void Tree_FreeItemRInfo(TreeCtrl *tree, TreeItem item); extern int Tree_ItemBbox(TreeCtrl *tree, TreeItem item, int lock, int *x, int *y, int *w, int *h); extern TreeItem Tree_ItemAbove(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemBelow(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemLeft(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemRight(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemTop(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemBottom(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemLeftMost(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemRightMost(TreeCtrl *tree, TreeItem item); extern int Tree_ItemToRNC(TreeCtrl *tree, TreeItem item, int *row, int *col); extern TreeItem Tree_RNCToItem(TreeCtrl *tree, int row, int col); extern int Tree_AreaBbox(TreeCtrl *tree, int area, int *x1_, int *y1_, int *x2_, int *y2_); enum { TREE_AREA_NONE = 0, TREE_AREA_HEADER, TREE_AREA_CONTENT, TREE_AREA_LEFT, TREE_AREA_RIGHT }; extern int Tree_HitTest(TreeCtrl *tree, int x, int y); extern void TreeDInfo_Init(TreeCtrl *tree); extern void TreeDInfo_Free(TreeCtrl *tree); extern void Tree_EventuallyRedraw(TreeCtrl *tree); extern void Tree_GetScrollFractionsX(TreeCtrl *tree, double fractions[2]); extern void Tree_GetScrollFractionsY(TreeCtrl *tree, double fractions[2]); extern int Increment_FindX(TreeCtrl *tree, int offset); extern int Increment_FindY(TreeCtrl *tree, int offset); extern int Increment_ToOffsetX(TreeCtrl *tree, int index); extern int Increment_ToOffsetY(TreeCtrl *tree, int index); extern int B_XviewCmd(TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); extern int B_YviewCmd(TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); extern void Tree_SetOriginX(TreeCtrl *tree, int xOrigin); extern void Tree_SetOriginY(TreeCtrl *tree, int yOrigin); extern void Tree_RelayoutWindow(TreeCtrl *tree); extern void Tree_FreeItemDInfo(TreeCtrl *tree, TreeItem item1, TreeItem item2); extern void Tree_InvalidateItemDInfo(TreeCtrl *tree, TreeColumn column, TreeItem item1, TreeItem item2); extern void TreeDisplay_ItemDeleted(TreeCtrl *tree, TreeItem item); extern void TreeDisplay_ColumnDeleted(TreeCtrl *tree, TreeColumn column); extern void TreeDisplay_GetReadyForTrouble(TreeCtrl *tree, int *requestsPtr); extern int TreeDisplay_WasThereTrouble(TreeCtrl *tree, int requests); extern void Tree_InvalidateArea(TreeCtrl *tree, int x1, int y1, int x2, int y2); extern void Tree_InvalidateItemArea(TreeCtrl *tree, int x1, int y1, int x2, int y2); extern void Tree_InvalidateRegion(TreeCtrl *tree, TkRegion region); extern void Tree_RedrawArea(TreeCtrl *tree, int x1, int y1, int x2, int y2); extern void Tree_FocusChanged(TreeCtrl *tree, int gotFocus); extern void Tree_Activate(TreeCtrl *tree, int isActive); extern void Tree_ItemsInArea(TreeCtrl *tree, TreeItemList *items, int minX, int minY, int maxX, int maxY); extern void TreeColumnProxy_Undisplay(TreeCtrl *tree); extern void TreeColumnProxy_Display(TreeCtrl *tree); extern void TreeRowProxy_Undisplay(TreeCtrl *tree); extern void TreeRowProxy_Display(TreeCtrl *tree); extern void Tree_DrawTiledImage(TreeCtrl *tree, Drawable drawable, Tk_Image image, int x1, int y1, int x2, int y2, int xOffset, int yOffset); #define DINFO_OUT_OF_DATE 0x0001 #define DINFO_CHECK_COLUMN_WIDTH 0x0002 #define DINFO_DRAW_HEADER 0x0004 #define DINFO_SET_ORIGIN_X 0x0008 #define DINFO_UPDATE_SCROLLBAR_X 0x0010 #define DINFO_REDRAW_PENDING 0x00020 #define DINFO_INVALIDATE 0x0040 #define DINFO_DRAW_HIGHLIGHT 0x0080 #define DINFO_DRAW_BORDER 0x0100 #define DINFO_REDO_RANGES 0x0200 #define DINFO_SET_ORIGIN_Y 0x0400 #define DINFO_UPDATE_SCROLLBAR_Y 0x0800 #define DINFO_REDO_INCREMENTS 0x1000 #define DINFO_REDO_COLUMN_WIDTH 0x2000 #define DINFO_REDO_SELECTION 0x4000 #define DINFO_DRAW_WHITESPACE 0x8000 extern void Tree_DInfoChanged(TreeCtrl *tree, int flags); extern void Tree_TheWorldHasChanged(Tcl_Interp *interp); /* tkTreeTheme.c */ extern int TreeTheme_InitInterp(Tcl_Interp *interp); extern void TreeTheme_ThemeChanged(TreeCtrl *tree); extern int TreeTheme_Init(TreeCtrl *tree); extern int TreeTheme_Free(TreeCtrl *tree); extern int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height); extern int TreeTheme_GetHeaderFixedHeight(TreeCtrl *tree, int *heightPtr); extern int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]); extern int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height); extern int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height); extern int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr); extern int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr); /* tkTreeUtils.c */ #ifdef TREECTRL_DEBUG #define WIPE(p,s) memset((char *) p, 0xAA, s) #else #define WIPE(p,s) #endif #define CWIPE(p,t,c) WIPE(p, sizeof(t) * (c)) #define WIPEFREE(p,s) { WIPE(p, s); ckfree((char *) p); } #define WFREE(p,t) WIPEFREE(p, sizeof(t)) #define WCFREE(p,t,c) WIPEFREE(p, sizeof(t) * (c)) extern int Ellipsis(Tk_Font tkfont, char *string, int numBytes, int *maxPixels, char *ellipsis, int force); extern void HDotLine(TreeCtrl *tree, Drawable drawable, GC gc, int x1, int y1, int x2); extern void VDotLine(TreeCtrl *tree, Drawable drawable, GC gc, int x1, int y1, int y2); extern void DotRect(TreeCtrl *tree, Drawable drawable, int x, int y, int width, int height); extern void DrawActiveOutline(TreeCtrl *tree, Drawable drawable, int x, int y, int width, int height, int open); typedef struct DotState { int stuff[10]; } DotState; extern void DotRect_Setup(TreeCtrl *tree, Drawable drawable, DotState *dotState); extern void DotRect_Draw(DotState *dotState, int x, int y, int width, int height); extern void DotRect_Restore(DotState *dotState); typedef struct TextLayout_ *TextLayout; extern TextLayout TextLayout_Compute(Tk_Font tkfont, CONST char *string, int numChars, int wrapLength, Tk_Justify justify, int maxLines, int flags); extern void TextLayout_Free(TextLayout textLayout); extern void TextLayout_Size(TextLayout textLayout, int *widthPtr, int *heightPtr); extern int TextLayout_TotalWidth(TextLayout textLayout); extern void TextLayout_Draw(Display *display, Drawable drawable, GC gc, TextLayout layout, int x, int y, int firstChar, int lastChar, int underline); #ifdef MAC_OSX_TK extern void DrawXORLine(Display *display, Drawable drawable, int x1, int y1, int x2, int y2); #endif extern void Tree_DrawBitmapWithGC(TreeCtrl *tree, Pixmap bitmap, Drawable drawable, GC gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y); extern void Tree_DrawBitmap(TreeCtrl *tree, Pixmap bitmap, Drawable drawable, XColor *fg, XColor *bg, int src_x, int src_y, int width, int height, int dest_x, int dest_y); extern void Tk_FillRegion(Display *display, Drawable drawable, GC gc, TkRegion rgn); extern void Tk_OffsetRegion(TkRegion region, int xOffset, int yOffset); extern int Tree_ScrollWindow(TreeCtrl *tree, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn); extern void UnsetClipMask(TreeCtrl *tree, Drawable drawable, GC gc); extern void XImage2Photo(Tcl_Interp *interp, Tk_PhotoHandle photoH, XImage *ximage, int alpha); #define PAD_TOP_LEFT 0 #define PAD_BOTTOM_RIGHT 1 extern Tk_ObjCustomOption PadAmountOption; extern int TreeCtrl_GetPadAmountFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *padObj, int *topLeftPtr, int *bottomRightPtr); extern Tcl_Obj * TreeCtrl_NewPadAmountObj(int *padAmounts); /*****/ extern int ObjectIsEmpty(Tcl_Obj *obj); extern PerStateType pstBitmap; extern PerStateType pstBoolean; extern PerStateType pstBorder; extern PerStateType pstColor; extern PerStateType pstFont; extern PerStateType pstImage; extern PerStateType pstRelief; #define MATCH_NONE 0 #define MATCH_ANY 1 #define MATCH_PARTIAL 2 #define MATCH_EXACT 3 extern void PerStateInfo_Free(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo); typedef int (*StateFromObjProc)(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn); extern int PerStateInfo_FromObj(TreeCtrl *tree, StateFromObjProc proc, PerStateType *typePtr, PerStateInfo *pInfo); extern PerStateData *PerStateInfo_ForState(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state, int *match); extern Tcl_Obj *PerStateInfo_ObjForState(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state, int *match); extern int PerStateInfo_Undefine(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state); struct PerStateGC { unsigned long mask; XGCValues gcValues; GC gc; struct PerStateGC *next; }; extern void PerStateGC_Free(TreeCtrl *tree, struct PerStateGC **pGCPtr); extern GC PerStateGC_Get(TreeCtrl *tree, struct PerStateGC **pGCPtr, unsigned long mask, XGCValues *gcValues); extern Pixmap PerStateBitmap_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern void PerStateBitmap_MaxSize(TreeCtrl *tree, PerStateInfo *pInfo, int *widthPtr, int *heightPtr); extern int PerStateBoolean_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern Tk_3DBorder PerStateBorder_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern XColor *PerStateColor_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern Tk_Font PerStateFont_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern Tk_Image PerStateImage_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern void PerStateImage_MaxSize(TreeCtrl *tree, PerStateInfo *pInfo, int *widthPtr, int *heightPtr); extern int PerStateRelief_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern void PSTSave(PerStateInfo *pInfo, PerStateInfo *pSave); extern void PSTRestore(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, PerStateInfo *pSave); #ifdef ALLOC_HAX extern ClientData AllocHax_Init(void); extern void AllocHax_Finalize(ClientData data); extern char *AllocHax_Alloc(ClientData data, Tk_Uid id, int size); extern char *AllocHax_CAlloc(ClientData data, Tk_Uid id, int size, int count, int roundUp); extern char *AllocHax_Realloc(ClientData data, Tk_Uid id, char *ptr, int size1, int size2); extern void AllocHax_Free(ClientData data, Tk_Uid id, char *ptr, int size); extern void AllocHax_CFree(ClientData data, Tk_Uid id, char *ptr, int size, int count, int roundUp); extern void AllocHax_Stats(Tcl_Interp *interp, ClientData data); #endif /*****/ extern void TreePtrList_Init(TreeCtrl *tree, TreePtrList *tilPtr, int count); extern ClientData *TreePtrList_Append(TreePtrList *tilPtr, ClientData ptr); extern ClientData *TreePtrList_Concat(TreePtrList *tilPtr, TreePtrList *til2Ptr); extern void TreePtrList_Free(TreePtrList *tilPtr); #define TreeItemList_Init TreePtrList_Init #define TreeItemList_Append TreePtrList_Append #define TreeItemList_Concat TreePtrList_Concat #define TreeItemList_Free TreePtrList_Free #define TreeItemList_Items(L) ((TreeItem *) (L)->pointers) #define TreeItemList_Nth(L,n) ((TreeItem) (L)->pointers[n]) #define TreeItemList_Count(L) ((L)->count) extern void TreeItemList_Sort(TreeItemList *items); #define TreeColumnList_Init TreePtrList_Init #define TreeColumnList_Append TreePtrList_Append #define TreeColumnList_Concat TreePtrList_Concat #define TreeColumnList_Free TreePtrList_Free #define TreeColumnList_Nth(L,n) ((TreeColumn) (L)->pointers[n]) #define TreeColumnList_Count(L) ((L)->count) /*****/ /* * This structure holds a list of tags. */ typedef struct TagInfo TagInfo; struct TagInfo { int numTags; /* Number of tag slots actually used * at tagPtr. */ int tagSpace; /* Total amount of tag space available * at tagPtr. */ #define TREE_TAG_SPACE 3 Tk_Uid tagPtr[TREE_TAG_SPACE]; /* Array of tags. The actual size will * be tagSpace. THIS FIELD MUST BE THE * LAST IN THE STRUCTURE. */ }; extern TagInfo *TagInfo_Add(TreeCtrl *tree, TagInfo *tagInfo, Tk_Uid tags[], int numTags); extern TagInfo *TagInfo_Remove(TreeCtrl *tree, TagInfo *tagInfo, Tk_Uid tags[], int numTags); extern Tk_Uid *TagInfo_Names(TreeCtrl *tree, TagInfo *tagInfo, Tk_Uid *tags, int *numTagsPtr, int *tagSpacePtr); extern TagInfo *TagInfo_Copy(TreeCtrl *tree, TagInfo *tagInfo); extern void TagInfo_Free(TreeCtrl *tree, TagInfo *tagInfo); extern int TagInfo_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TagInfo **tagInfoPtr); extern Tk_ObjCustomOption TagInfoCO; /* * This struct holds information about a tag expression. */ typedef struct TagExpr { TreeCtrl *tree; Tk_Uid *uids; /* expresion compiled to an array of uids */ Tk_Uid staticUids[15]; int allocated; /* available space for array of uids */ int length; /* number of uids */ int index; /* current position in expression evaluation */ int simple; /* TRUE if expr is single tag */ Tk_Uid uid; /* single tag if 'simple' is TRUE */ char *string; /* tag expression string */ int stringIndex; /* current position in string scan */ int stringLength; /* length of tag expression string */ char *rewritebuffer; /* tag string (after removing escapes) */ char staticRWB[100]; } TagExpr; extern int TagExpr_Init(TreeCtrl *tree, Tcl_Obj *exprObj, TagExpr *expr); extern int TagExpr_Scan(TagExpr *expr); extern int TagExpr_Eval(TagExpr *expr, TagInfo *tags); extern void TagExpr_Free(TagExpr *expr); extern Tk_OptionSpec *OptionSpec_Find(Tk_OptionSpec *optionTable, CONST char *optionName); extern Tk_ObjCustomOption *PerStateCO_Alloc(CONST char *optionName, PerStateType *typePtr, StateFromObjProc proc); extern int PerStateCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, PerStateType *typePtr, StateFromObjProc proc); /*****/ typedef struct DynamicOptionSpec DynamicOptionSpec; typedef struct DynamicOption DynamicOption; struct DynamicOption { int id; /* Unique id. */ DynamicOption *next; /* Linked list. */ char data[1]; /* Actual size will be > 1 */ }; typedef void (DynamicOptionInitProc)(char *data); extern DynamicOption *DynamicOption_AllocIfNeeded(TreeCtrl *tree, DynamicOption **firstPtr, int id, int size, DynamicOptionInitProc *init); extern char *DynamicOption_FindData(DynamicOption *first, int id); extern void DynamicOption_Free(TreeCtrl *tree, DynamicOption *first, Tk_OptionSpec *optionTable); extern void DynamicOption_Free1(TreeCtrl *tree, DynamicOption **firstPtr, int id, int size); extern int DynamicCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, int id, int size, int objOffset, int internalOffset, Tk_ObjCustomOption *custom, DynamicOptionInitProc *init); extern int BooleanFlagCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, int theFlag); extern Tk_ObjCustomOption pixelsCO; extern Tk_ObjCustomOption stringCO; extern Tk_ObjCustomOption styleCO; /*****/ #define STATIC_SIZE 20 #define STATIC_ALLOC(P,T,C) \ if (C > STATIC_SIZE) \ P = (T *) ckalloc(sizeof(T) * (C)) #define STATIC_FREE(P,T,C) \ CWIPE(P, T, C); \ if (C > STATIC_SIZE) \ ckfree((char *) P) #define STATIC_FREE2(P,P2) \ if (P != P2) \ ckfree((char *) P) kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeElem.c0000644000175000017500000035737511044115431024716 0ustar domibeldomibel/* * tkTreeElem.c -- * * This module implements elements for treectrl widgets. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: tkTreeElem.c,v 1.7 2008-07-30 16:47:21 barre Exp $ */ #include "tkTreeCtrl.h" #include "tkTreeElem.h" /* *---------------------------------------------------------------------- * * DO_BooleanForState -- * DO_ColorForState -- * DO_FontForState -- * * Returns the value of a per-state option for an element. * * Results: * If the element has the dynamic option allocated, then the * per-state info is checked for a match. If an exact match for * the given state is not found, and if the element is an instance * (not a master), then the master element is checked. * * Side effects: * None. * *---------------------------------------------------------------------- */ int DO_BooleanForState( TreeCtrl *tree, /* Widget info. */ Element *elem, /* Element to examine. */ int id, /* Unique id of dynamic option. */ int state /* STATE_xxx flags. */ ) { int result = -1; PerStateInfo *psi; int match = MATCH_NONE; psi = (PerStateInfo *) DynamicOption_FindData(elem->options, id); if (psi != NULL) result = PerStateBoolean_ForState(tree, psi, state, &match); if ((match != MATCH_EXACT) && (elem->master != NULL)) { PerStateInfo *psi = (PerStateInfo *) DynamicOption_FindData( elem->master->options, id); if (psi != NULL) { int matchM; int resultM = PerStateBoolean_ForState(tree, psi, state, &matchM); if (matchM > match) result = resultM; } } return result; } XColor * DO_ColorForState( TreeCtrl *tree, Element *elem, int id, int state ) { XColor *result = NULL; PerStateInfo *psi; int match = MATCH_NONE; psi = (PerStateInfo *) DynamicOption_FindData(elem->options, id); if (psi != NULL) result = PerStateColor_ForState(tree, psi, state, &match); if ((match != MATCH_EXACT) && (elem->master != NULL)) { PerStateInfo *psi = (PerStateInfo *) DynamicOption_FindData( elem->master->options, id); if (psi != NULL) { int matchM; XColor *resultM = PerStateColor_ForState(tree, psi, state, &matchM); if (matchM > match) result = resultM; } } return result; } Tk_Font DO_FontForState( TreeCtrl *tree, Element *elem, int id, int state ) { Tk_Font result = NULL; PerStateInfo *psi; int match = MATCH_NONE; psi = (PerStateInfo *) DynamicOption_FindData(elem->options, id); if (psi != NULL) result = PerStateFont_ForState(tree, psi, state, &match); if ((match != MATCH_EXACT) && (elem->master != NULL)) { PerStateInfo *psi = (PerStateInfo *) DynamicOption_FindData( elem->master->options, id); if (psi != NULL) { int matchM; Tk_Font resultM = PerStateFont_ForState(tree, psi, state, &matchM); if (matchM > match) result = resultM; } } return result; } /* *---------------------------------------------------------------------- * * DO_ObjectForState -- * * Returns the object representation of a per-state option * for an element. * * Results: * If the element has the dynamic option allocated, then the * per-state info is checked for a match. If an exact match for * the given state is not found, and if the element is an instance * (not a master), then the master element is checked. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * DO_ObjectForState( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ Element *elem, /* Element to examine. */ int id, /* Unique id of dynamic option. */ int state /* STATE_xxx flags. */ ) { Tcl_Obj *result = NULL; PerStateInfo *psi; int match = MATCH_NONE; psi = (PerStateInfo *) DynamicOption_FindData(elem->options, id); if (psi != NULL) result = PerStateInfo_ObjForState(tree, typePtr, psi, state, &match); if ((match != MATCH_EXACT) && (elem->master != NULL)) { PerStateInfo *psi = (PerStateInfo *) DynamicOption_FindData( elem->master->options, id); if (psi != NULL) { int matchM; Tcl_Obj *resultM = PerStateInfo_ObjForState(tree, typePtr, psi, state, &matchM); if (matchM > match) result = resultM; } } return result; } /* BEGIN custom "boolean" option */ /* Just like TK_OPTION_BOOLEAN but supports TK_OPTION_NULL_OK */ /* Internal value is -1 for no-such-value */ static int BooleanSet( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags) { int objEmpty; int new, *internalPtr; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (Tcl_GetBooleanFromObj(interp, (*value), &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { if ((*value) == NULL) new = -1; *((int *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj *BooleanGet( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset) { int value = *(int *) (recordPtr + internalOffset); if (value == -1) return NULL; return Tcl_NewBooleanObj(value); } static void BooleanRestore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr) { *(int *) internalPtr = *(int *) saveInternalPtr; } static Tk_ObjCustomOption booleanCO = { "boolean", BooleanSet, BooleanGet, BooleanRestore, NULL, (ClientData) NULL }; /* END custom "boolean" option */ /* BEGIN custom "integer" option */ /* Just like TK_OPTION_INT but supports TK_OPTION_NULL_OK and bounds checking */ typedef struct IntegerClientData { int min; int max; int empty; /* internal form if empty */ int flags; /* 0x01 - use min, 0x02 - use max */ } IntegerClientData; static int IntegerSet( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags) { IntegerClientData *info = (IntegerClientData *) clientData; int objEmpty; int new, *internalPtr; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (Tcl_GetIntFromObj(interp, (*value), &new) != TCL_OK) return TCL_ERROR; if ((info->flags & 0x01) && (new < info->min)) { FormatResult(interp, "bad integer value \"%d\": must be >= %d", new, info->min); return TCL_ERROR; } if ((info->flags & 0x02) && (new > info->max)) { FormatResult(interp, "bad integer value \"%d\": must be <= %d", new, info->max); return TCL_ERROR; } } if (internalPtr != NULL) { if ((*value) == NULL) new = info->empty; *((int *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj *IntegerGet( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset) { IntegerClientData *info = (IntegerClientData *) clientData; int value = *(int *) (recordPtr + internalOffset); if (value == info->empty) return NULL; return Tcl_NewIntObj(value); } static void IntegerRestore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr) { *(int *) internalPtr = *(int *) saveInternalPtr; } /* END custom "integer" option */ /*****/ /* BEGIN custom "stringtable" option */ /* Just like TK_OPTION_STRING_TABLE but supports TK_OPTION_NULL_OK */ /* The integer rep is -1 if empty string specified */ typedef struct StringTableClientData { CONST char **tablePtr; /* NULL-termintated list of strings */ CONST char *msg; /* Tcl_GetIndexFromObj() message */ } StringTableClientData; static int StringTableSet( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags) { StringTableClientData *info = (StringTableClientData *) clientData; int objEmpty; int new, *internalPtr; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (Tcl_GetIndexFromObj(interp, (*value), (CONST84 char **)info->tablePtr, info->msg, 0, &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { if ((*value) == NULL) new = -1; *((int *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj *StringTableGet( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset) { StringTableClientData *info = (StringTableClientData *) clientData; int index = *(int *) (recordPtr + internalOffset); if (index == -1) return NULL; return Tcl_NewStringObj(info->tablePtr[index], -1); } static void StringTableRestore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr) { *(int *) internalPtr = *(int *) saveInternalPtr; } /* END custom "stringtable" option */ int BooleanCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName) { Tk_OptionSpec *specPtr; specPtr = OptionSpec_Find(optionTable, optionName); specPtr->clientData = &booleanCO; return TCL_OK; } Tk_ObjCustomOption * IntegerCO_Alloc( CONST char *optionName, int min, int max, int empty, int flags ) { IntegerClientData *cd; Tk_ObjCustomOption *co; /* ClientData for the Tk custom option record */ cd = (IntegerClientData *) ckalloc(sizeof(IntegerClientData)); cd->min = min; cd->max = max; cd->empty = empty; cd->flags = flags; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = (char *) optionName + 1; co->setProc = IntegerSet; co->getProc = IntegerGet; co->restoreProc = IntegerRestore; co->freeProc = NULL; co->clientData = (ClientData) cd; return co; } int IntegerCO_Init( Tk_OptionSpec *optionTable, CONST char *optionName, int min, int max, int empty, int flags ) { Tk_OptionSpec *specPtr; specPtr = OptionSpec_Find(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("IntegerCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; specPtr->clientData = IntegerCO_Alloc(optionName, min, max, empty, flags); return TCL_OK; } Tk_ObjCustomOption * StringTableCO_Alloc( CONST char *optionName, CONST char **tablePtr ) { StringTableClientData *cd; Tk_ObjCustomOption *co; /* ClientData for the Tk custom option record */ cd = (StringTableClientData *) ckalloc(sizeof(StringTableClientData)); cd->tablePtr = tablePtr; cd->msg = optionName + 1; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = (char *) optionName + 1; co->setProc = StringTableSet; co->getProc = StringTableGet; co->restoreProc = StringTableRestore; co->freeProc = NULL; co->clientData = (ClientData) cd; return co; } int StringTableCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, CONST char **tablePtr) { Tk_OptionSpec *specPtr; specPtr = OptionSpec_Find(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("StringTableCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; specPtr->clientData = StringTableCO_Alloc(optionName, tablePtr); return TCL_OK; } /*****/ int TreeStateFromObj(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn) { int states[3]; states[STATE_OP_ON] = states[STATE_OP_OFF] = states[STATE_OP_TOGGLE] = 0; if (Tree_StateFromObj(tree, obj, states, NULL, SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; (*stateOn) |= states[STATE_OP_ON]; (*stateOff) |= states[STATE_OP_OFF]; return TCL_OK; } static void AdjustForSticky(int sticky, int cavityWidth, int cavityHeight, int expandX, int expandY, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr) { int dx = 0; int dy = 0; if (cavityWidth > *widthPtr) { dx = cavityWidth - *widthPtr; } if (cavityHeight > *heightPtr) { dy = cavityHeight - *heightPtr; } if ((sticky & STICKY_W) && (sticky & STICKY_E)) { if (expandX) *widthPtr += dx; else sticky &= ~(STICKY_W | STICKY_E); } if ((sticky & STICKY_N) && (sticky & STICKY_S)) { if (expandY) *heightPtr += dy; else sticky &= ~(STICKY_N | STICKY_S); } if (!(sticky & STICKY_W)) { *xPtr += (sticky & STICKY_E) ? dx : dx / 2; } if (!(sticky & STICKY_N)) { *yPtr += (sticky & STICKY_S) ? dy : dy / 2; } } /* This macro gets the value of a per-state option for an element, then * looks for a better match from the master element if it exists */ #define OPTION_FOR_STATE(xFUNC,xTYPE,xVAR,xFIELD,xSTATE) \ xVAR = xFUNC(tree, &elemX->xFIELD, xSTATE, &match); \ if ((match != MATCH_EXACT) && (masterX != NULL)) { \ xTYPE varM = xFUNC(tree, &masterX->xFIELD, xSTATE, &match2); \ if (match2 > match) \ xVAR = varM; \ } #define BITMAP_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateBitmap_ForState,Pixmap,xVAR,xFIELD,xSTATE) #define BOOLEAN_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateBoolean_ForState,int,xVAR,xFIELD,xSTATE) #define BORDER_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateBorder_ForState,Tk_3DBorder,xVAR,xFIELD,xSTATE) #define COLOR_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateColor_ForState,XColor*,xVAR,xFIELD,xSTATE) #define FONT_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateFont_ForState,Tk_Font,xVAR,xFIELD,xSTATE) #define IMAGE_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateImage_ForState,Tk_Image,xVAR,xFIELD,xSTATE) #define RELIEF_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateRelief_ForState,int,xVAR,xFIELD,xSTATE) /* This macro gets the object for a per-state option for an element, then * looks for a better match from the master element if it exists */ #define OBJECT_FOR_STATE(xVAR,xTYPE,xFIELD,xSTATE) \ xVAR = PerStateInfo_ObjForState(tree, &xTYPE, &elemX->xFIELD, xSTATE, &match); \ if ((match != MATCH_EXACT) && (masterX != NULL)) { \ Tcl_Obj *objM = PerStateInfo_ObjForState(tree, &xTYPE, &masterX->xFIELD, xSTATE, &matchM); \ if (matchM > match) \ xVAR = objM; \ } /*****/ typedef struct ElementBitmap ElementBitmap; struct ElementBitmap { Element header; PerStateInfo draw; PerStateInfo bitmap; PerStateInfo fg; PerStateInfo bg; }; #define BITMAP_CONF_BITMAP 0x0001 #define BITMAP_CONF_FG 0x0002 #define BITMAP_CONF_BG 0x0004 #define BITMAP_CONF_DRAW 0x0008 static Tk_OptionSpec bitmapOptionSpecs[] = { {TK_OPTION_CUSTOM, "-background", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBitmap, bg.obj), Tk_Offset(ElementBitmap, bg), TK_OPTION_NULL_OK, (ClientData) NULL, BITMAP_CONF_BG}, {TK_OPTION_CUSTOM, "-bitmap", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBitmap, bitmap.obj), Tk_Offset(ElementBitmap, bitmap), TK_OPTION_NULL_OK, (ClientData) NULL, BITMAP_CONF_BITMAP}, {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBitmap, draw.obj), Tk_Offset(ElementBitmap, draw), TK_OPTION_NULL_OK, (ClientData) NULL, BITMAP_CONF_DRAW}, {TK_OPTION_CUSTOM, "-foreground", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBitmap, fg.obj), Tk_Offset(ElementBitmap, fg), TK_OPTION_NULL_OK, (ClientData) NULL, BITMAP_CONF_FG}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcBitmap(ElementArgs *args) { /* TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem;*/ } static int WorldChangedProcBitmap(ElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & BITMAP_CONF_BITMAP) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & (BITMAP_CONF_DRAW | BITMAP_CONF_FG | BITMAP_CONF_BG)) mask |= CS_DISPLAY; return mask; } static int ConfigProcBitmap(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcBitmap(ElementArgs *args) { return TCL_OK; } static void DisplayProcBitmap(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; ElementBitmap *masterX = (ElementBitmap *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width, height; int match, match2; int draw; Pixmap bitmap; XColor *fg, *bg; int imgW, imgH; BOOLEAN_FOR_STATE(draw, draw, state) if (!draw) return; BITMAP_FOR_STATE(bitmap, bitmap, state) if (bitmap == None) return; COLOR_FOR_STATE(fg, fg, state) COLOR_FOR_STATE(bg, bg, state) Tk_SizeOfBitmap(tree->display, bitmap, &imgW, &imgH); width = imgW, height = imgH; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); if (imgW > args->display.width) imgW = args->display.width; if (imgH > args->display.height) imgH = args->display.height; Tree_DrawBitmap(tree, bitmap, args->display.drawable, fg, bg, 0, 0, (unsigned int) imgW, (unsigned int) imgH, x, y); } static void NeededProcBitmap(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; ElementBitmap *masterX = (ElementBitmap *) elem->master; int state = args->state; int width = 0, height = 0; int match, match2; Pixmap bitmap; BITMAP_FOR_STATE(bitmap, bitmap, state) if (bitmap != None) Tk_SizeOfBitmap(tree->display, bitmap, &width, &height); args->needed.width = width; args->needed.height = height; } static int StateProcBitmap(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; ElementBitmap *masterX = (ElementBitmap *) elem->master; int match, match2; int draw1, draw2; Pixmap bitmap1, bitmap2; XColor *fg1, *fg2; XColor *bg1, *bg2; int mask = 0; BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) if (draw1 == -1) draw1 = 1; BITMAP_FOR_STATE(bitmap1, bitmap, args->states.state1) COLOR_FOR_STATE(fg1, fg, args->states.state1) COLOR_FOR_STATE(bg1, bg, args->states.state1) BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if (draw2 == -1) draw2 = 1; BITMAP_FOR_STATE(bitmap2, bitmap, args->states.state2) COLOR_FOR_STATE(fg2, fg, args->states.state2) COLOR_FOR_STATE(bg2, bg, args->states.state2) if ((draw1 != draw2) || (fg1 != fg2) || (bg1 != bg2) || (bitmap1 != bitmap2)) mask |= CS_DISPLAY; if (bitmap1 != bitmap2) { if ((bitmap1 != None) && (bitmap2 != None)) { int w1, h1, w2, h2; Tk_SizeOfBitmap(tree->display, bitmap1, &w1, &h1); Tk_SizeOfBitmap(tree->display, bitmap2, &w2, &h2); if ((w1 != w2) || (h1 != h2)) mask |= CS_LAYOUT; } else mask |= CS_LAYOUT; } return mask; } static int UndefProcBitmap(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementBitmap *elemX = (ElementBitmap *) args->elem; int modified = 0; modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); modified |= PerStateInfo_Undefine(tree, &pstColor, &elemX->fg, args->state); modified |= PerStateInfo_Undefine(tree, &pstColor, &elemX->bg, args->state); modified |= PerStateInfo_Undefine(tree, &pstBitmap, &elemX->bitmap, args->state); return modified; } static int ActualProcBitmap(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementBitmap *elemX = (ElementBitmap *) args->elem; ElementBitmap *masterX = (ElementBitmap *) args->elem->master; static CONST84 char *optionName[] = { "-background", "-bitmap", "-draw", "-foreground", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstColor, bg, args->state) break; } case 1: { OBJECT_FOR_STATE(obj, pstBitmap, bitmap, args->state) break; } case 2: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } case 3: { OBJECT_FOR_STATE(obj, pstColor, fg, args->state) break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } ElementType elemTypeBitmap = { "bitmap", sizeof(ElementBitmap), bitmapOptionSpecs, NULL, CreateProcBitmap, DeleteProcBitmap, ConfigProcBitmap, DisplayProcBitmap, NeededProcBitmap, NULL, /* heightProc */ WorldChangedProcBitmap, StateProcBitmap, UndefProcBitmap, ActualProcBitmap, NULL /* onScreenProc */ }; /*****/ typedef struct ElementBorder ElementBorder; struct ElementBorder { Element header; /* Must be first */ PerStateInfo draw; PerStateInfo border; PerStateInfo relief; int thickness; Tcl_Obj *thicknessObj; int width; Tcl_Obj *widthObj; int height; Tcl_Obj *heightObj; int filled; }; #define BORDER_CONF_BG 0x0001 #define BORDER_CONF_RELIEF 0x0002 #define BORDER_CONF_SIZE 0x0004 #define BORDER_CONF_THICKNESS 0x0008 #define BORDER_CONF_FILLED 0x0010 #define BORDER_CONF_DRAW 0x0020 static Tk_OptionSpec borderOptionSpecs[] = { {TK_OPTION_CUSTOM, "-background", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, border.obj), Tk_Offset(ElementBorder, border), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_BG}, {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, draw.obj), Tk_Offset(ElementBorder, draw), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_DRAW}, {TK_OPTION_CUSTOM, "-filled", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementBorder, filled), TK_OPTION_NULL_OK, (ClientData) &booleanCO, BORDER_CONF_FILLED}, {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, heightObj), Tk_Offset(ElementBorder, height), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_SIZE}, {TK_OPTION_CUSTOM, "-relief", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, relief.obj), Tk_Offset(ElementBorder, relief), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_RELIEF}, {TK_OPTION_PIXELS, "-thickness", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, thicknessObj), Tk_Offset(ElementBorder, thickness), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_THICKNESS}, {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, widthObj), Tk_Offset(ElementBorder, width), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_SIZE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcBorder(ElementArgs *args) { /* TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem;*/ } static int WorldChangedProcBorder(ElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & BORDER_CONF_SIZE) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & (BORDER_CONF_DRAW | BORDER_CONF_BG | BORDER_CONF_RELIEF | BORDER_CONF_THICKNESS | BORDER_CONF_FILLED)) mask |= CS_DISPLAY; return mask; } static int ConfigProcBorder(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcBorder(ElementArgs *args) { Element *elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; elemX->filled = -1; return TCL_OK; } static void DisplayProcBorder(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; ElementBorder *masterX = (ElementBorder *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width = args->display.width, height = args->display.height; int match, match2; int draw; Tk_3DBorder border; int relief, filled = FALSE; int thickness = 0; BOOLEAN_FOR_STATE(draw, draw, state) if (!draw) return; BORDER_FOR_STATE(border, border, state) if (border == NULL) return; RELIEF_FOR_STATE(relief, relief, state) if (relief == TK_RELIEF_NULL) relief = TK_RELIEF_FLAT; if (elemX->thicknessObj) thickness = elemX->thickness; else if ((masterX != NULL) && (masterX->thicknessObj != NULL)) thickness = masterX->thickness; if (elemX->filled != -1) filled = elemX->filled; else if ((masterX != NULL) && (masterX->filled != -1)) filled = masterX->filled; if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, TRUE, TRUE, &x, &y, &width, &height); if (filled) { Tk_Fill3DRectangle(tree->tkwin, args->display.drawable, border, x, y, width, height, thickness, relief); } else if (thickness > 0) { Tk_Draw3DRectangle(tree->tkwin, args->display.drawable, border, x, y, width, height, thickness, relief); } } static void NeededProcBorder(ElementArgs *args) { Element *elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; ElementBorder *masterX = (ElementBorder *) elem->master; int width = 0, height = 0; if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; args->needed.width = width; args->needed.height = height; } static int StateProcBorder(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; ElementBorder *masterX = (ElementBorder *) elem->master; int match, match2; int draw1, draw2; Tk_3DBorder border1, border2; int relief1, relief2; int mask = 0; BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) if (draw1 == -1) draw1 = 1; BORDER_FOR_STATE(border1, border, args->states.state1) RELIEF_FOR_STATE(relief1, relief, args->states.state1) BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if (draw2 == -1) draw2 = 1; BORDER_FOR_STATE(border2, border, args->states.state2) RELIEF_FOR_STATE(relief2, relief, args->states.state2) if ((draw1 != draw2) || (border1 != border2) || (relief1 != relief2)) mask |= CS_DISPLAY; return mask; } static int UndefProcBorder(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementBorder *elemX = (ElementBorder *) args->elem; int modified = 0; modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); modified |= PerStateInfo_Undefine(tree, &pstBorder, &elemX->border, args->state); modified |= PerStateInfo_Undefine(tree, &pstRelief, &elemX->relief, args->state); return modified; } static int ActualProcBorder(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementBorder *elemX = (ElementBorder *) args->elem; ElementBorder *masterX = (ElementBorder *) args->elem->master; static CONST84 char *optionName[] = { "-background", "-draw", "-relief", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstBorder, border, args->state) break; } case 1: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } case 2: { OBJECT_FOR_STATE(obj, pstRelief, relief, args->state) break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } ElementType elemTypeBorder = { "border", sizeof(ElementBorder), borderOptionSpecs, NULL, CreateProcBorder, DeleteProcBorder, ConfigProcBorder, DisplayProcBorder, NeededProcBorder, NULL, /* heightProc */ WorldChangedProcBorder, StateProcBorder, UndefProcBorder, ActualProcBorder, NULL /* onScreenProc */ }; /*****/ #if 0 static CONST84 char *chkbutStateST[] = { "checked", "mixed", "normal", "active", "pressed", "disabled", (char *) NULL }; typedef struct ElementCheckButton ElementCheckButton; struct ElementCheckButton { Element header; PerStateInfo image; int state; }; #define CHKBUT_CONF_IMAGE 0x0001 #define CHKBUT_CONF_STATE 0x0002 static Tk_OptionSpec chkbutOptionSpecs[] = { {TK_OPTION_STRING, "-image", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementCheckButton, image.obj), -1, TK_OPTION_NULL_OK, (ClientData) NULL, CHKBUT_CONF_IMAGE}, {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL, "normal", -1, Tk_Offset(ElementCheckButton, state), 0, (ClientData) chkbutStateST, CHKBUT_CONF_STATE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcCheckButton(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; PerStateInfo_Free(tree, &pstImage, &elemX->image); } static int WorldChangedProcCheckButton(ElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & (CHKBUT_CONF_IMAGE | CHKBUT_CONF_STATE)) mask |= CS_DISPLAY | CS_LAYOUT; return mask; } static int ChkButStateFromObj(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn) { Tcl_Interp *interp = tree->interp; int i, op = STATE_OP_ON, op2, op3, length, state = 0; char ch0, *string; int states[3]; states[STATE_OP_ON] = 0; states[STATE_OP_OFF] = 0; states[STATE_OP_TOGGLE] = 0; string = Tcl_GetStringFromObj(obj, &length); if (length == 0) goto unknown; ch0 = string[0]; if (ch0 == '!') { op = STATE_OP_OFF; ++string; ch0 = string[0]; } else if (ch0 == '~') { if (1) { FormatResult(interp, "can't specify '~' for this command"); return TCL_ERROR; } op = STATE_OP_TOGGLE; ++string; ch0 = string[0]; } for (i = 0; chkbutStateST[i] != NULL; i++) { if ((ch0 == chkbutStateST[i][0]) && !strcmp(string, chkbutStateST[i])) { state = 1L << i; break; } } if (state == 0) goto unknown; if (op == STATE_OP_ON) { op2 = STATE_OP_OFF; op3 = STATE_OP_TOGGLE; } else if (op == STATE_OP_OFF) { op2 = STATE_OP_ON; op3 = STATE_OP_TOGGLE; } else { op2 = STATE_OP_ON; op3 = STATE_OP_OFF; } states[op2] &= ~state; states[op3] &= ~state; states[op] |= state; *stateOn |= states[STATE_OP_ON]; *stateOff |= states[STATE_OP_OFF]; return TCL_OK; unknown: FormatResult(interp, "unknown state \"%s\"", string); return TCL_ERROR; } static int ConfigProcCheckButton(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; ElementCheckButton savedX; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } if (args->config.flagSelf & CHKBUT_CONF_IMAGE) PSTSave(&elemX->image, &savedX.image); if (args->config.flagSelf & CHKBUT_CONF_IMAGE) { if (PerStateInfo_FromObj(tree, ChkButStateFromObj, &pstImage, &elemX->image) != TCL_OK) continue; } if (args->config.flagSelf & CHKBUT_CONF_IMAGE) PerStateInfo_Free(tree, &pstImage, &savedX.image); Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); if (args->config.flagSelf & CHKBUT_CONF_IMAGE) PSTRestore(tree, &pstImage, &elemX->image, &savedX.image); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcCheckButton(ElementArgs *args) { return TCL_OK; } static void DisplayProcCheckButton(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; ElementCheckButton *masterX = (ElementCheckButton *) elem->master; int state = args->state; int match, matchM; Tk_Image image; int imgW, imgH; int dx = 0, dy = 0; image = PerStateImage_ForState(tree, &elemX->image, state, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { Tk_Image imageM = PerStateImage_ForState(tree, &masterX->image, state, &matchM); if (matchM > match) image = imageM; } if (image != NULL) { Tk_SizeOfImage(image, &imgW, &imgH); if (imgW < args->display.width) dx = (args->display.width - imgW) / 2; else if (imgW > args->display.width) imgW = args->display.width; if (imgH < args->display.height) dy = (args->display.height - imgH) / 2; else if (imgH > args->display.height) imgH = args->display.height; Tk_RedrawImage(image, 0, 0, imgW, imgH, args->display.drawable, args->display.x + dx, args->display.y + dy); } } static void NeededProcCheckButton(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; ElementCheckButton *masterX = (ElementCheckButton *) elem->master; int state = args->state; int match, match2; Tk_Image image; int width = 0, height = 0; image = PerStateImage_ForState(tree, &elemX->image, state, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { Tk_Image image2 = PerStateImage_ForState(tree, &masterX->image, state, &match2); if (match2 > match) image = image2; } if (image != NULL) Tk_SizeOfImage(image, &width, &height); args->layout.width = width; args->layout.height = height; } static int StateProcCheckButton(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; ElementCheckButton *masterX = (ElementCheckButton *) elem->master; int match, match2; Tk_Image image1, image2; int mask = 0; image1 = PerStateImage_ForState(tree, &elemX->image, args->states.state1, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { Tk_Image image = PerStateImage_ForState(tree, &masterX->image, args->states.state1, &match2); if (match2 > match) image1 = image; } image2 = PerStateImage_ForState(tree, &elemX->image, args->states.state2, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { Tk_Image image = PerStateImage_ForState(tree, &masterX->image, args->states.state2, &match2); if (match2 > match) image2 = image; } if (image1 != image2) { mask |= CS_DISPLAY; if ((image1 != NULL) && (image2 != NULL)) { int w1, h1, w2, h2; Tk_SizeOfImage(image1, &w1, &h1); Tk_SizeOfImage(image2, &w2, &h2); if ((w1 != w2) || (h1 != h2)) mask |= CS_LAYOUT; } else mask |= CS_LAYOUT; } return mask; } static int UndefProcCheckButton(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementCheckButton *elemX = (ElementCheckButton *) args->elem; return PerStateInfo_Undefine(tree, &pstImage, &elemX->image, args->state); } static int ActualProcCheckButton(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementCheckButton *elemX = (ElementCheckButton *) args->elem; ElementCheckButton *masterX = (ElementCheckButton *) args->elem->master; static CONST84 char *optionName[] = { "-image", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { obj = PerStateInfo_ObjForState(tree, &pstImage, &elemX->image, args->state, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { objM = PerStateInfo_ObjForState(tree, &pstImage, &masterX->image, args->state, &matchM); if (matchM > match) obj = objM; } break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } ElementType elemTypeCheckButton = { "checkbutton", sizeof(ElementCheckButton), chkbutOptionSpecs, NULL, CreateProcCheckButton, DeleteProcCheckButton, ConfigProcCheckButton, DisplayProcCheckButton, NeededProcCheckButton, NULL, /* heightProc */ WorldChangedProcCheckButton, StateProcCheckButton, UndefProcCheckButton, ActualProcCheckButton, NULL /* onScreenProc */ }; #endif /*****/ typedef struct ElementImage ElementImage; struct ElementImage { Element header; PerStateInfo draw; PerStateInfo image; int width; Tcl_Obj *widthObj; int height; Tcl_Obj *heightObj; int tiled; }; #define IMAGE_CONF_IMAGE 0x0001 #define IMAGE_CONF_SIZE 0x0002 #define IMAGE_CONF_DRAW 0x0004 #define IMAGE_CONF_DISPLAY 0x0008 static Tk_OptionSpec imageOptionSpecs[] = { {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementImage, draw.obj), Tk_Offset(ElementImage, draw), TK_OPTION_NULL_OK, (ClientData) NULL, IMAGE_CONF_DRAW}, {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementImage, heightObj), Tk_Offset(ElementImage, height), TK_OPTION_NULL_OK, (ClientData) NULL, IMAGE_CONF_SIZE}, {TK_OPTION_CUSTOM, "-image", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementImage, image.obj), Tk_Offset(ElementImage, image), TK_OPTION_NULL_OK, (ClientData) NULL, IMAGE_CONF_IMAGE}, {TK_OPTION_CUSTOM, "-tiled", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementImage, tiled), TK_OPTION_NULL_OK, (ClientData) &booleanCO, IMAGE_CONF_DISPLAY}, {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementImage, widthObj), Tk_Offset(ElementImage, width), TK_OPTION_NULL_OK, (ClientData) NULL, IMAGE_CONF_SIZE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcImage(ElementArgs *args) { /* TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementImage *elemX = (ElementImage *) elem;*/ } static int WorldChangedProcImage(ElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & (IMAGE_CONF_DRAW | IMAGE_CONF_IMAGE | IMAGE_CONF_SIZE)) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & IMAGE_CONF_DISPLAY) mask |= CS_DISPLAY; return mask; } static int ConfigProcImage(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementImage *elemX = (ElementImage *) elem; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcImage(ElementArgs *args) { ElementImage *elemX = (ElementImage *) args->elem; elemX->tiled = -1; return TCL_OK; } static void DisplayProcImage(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementImage *elemX = (ElementImage *) elem; ElementImage *masterX = (ElementImage *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width, height; int match, match2; int draw; Tk_Image image; int imgW, imgH; int tiled = 0; BOOLEAN_FOR_STATE(draw, draw, state) if (!draw) return; IMAGE_FOR_STATE(image, image, state) if (image == NULL) return; if (elemX->tiled != -1) tiled = elemX->tiled; else if ((masterX != NULL) && (masterX->tiled != -1)) tiled = masterX->tiled; if (tiled) { Tree_DrawTiledImage(tree, args->display.drawable, image, x, y, x + args->display.width, y + args->display.height, -x, -y); return; } Tk_SizeOfImage(image, &imgW, &imgH); width = imgW, height = imgH; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); if (imgW > args->display.width) imgW = args->display.width; if (imgH > args->display.height) imgH = args->display.height; Tk_RedrawImage(image, 0, 0, imgW, imgH, args->display.drawable, x, y); } static void NeededProcImage(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementImage *elemX = (ElementImage *) elem; ElementImage *masterX = (ElementImage *) elem->master; int state = args->state; int width = 0, height = 0; int match, match2; Tk_Image image; IMAGE_FOR_STATE(image, image, state) if (image != NULL) Tk_SizeOfImage(image, &width, &height); if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; args->needed.width = width; args->needed.height = height; } static int StateProcImage(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementImage *elemX = (ElementImage *) elem; ElementImage *masterX = (ElementImage *) elem->master; int match, match2; int draw1, draw2; Tk_Image image1, image2; int mask = 0; BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) if (draw1 == -1) draw1 = 1; IMAGE_FOR_STATE(image1, image, args->states.state1) BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if (draw2 == -1) draw2 = 1; IMAGE_FOR_STATE(image2, image, args->states.state2) if (image1 != image2) { mask |= CS_DISPLAY; if ((image1 != NULL) && (image2 != NULL)) { int w1, h1, w2, h2; Tk_SizeOfImage(image1, &w1, &h1); Tk_SizeOfImage(image2, &w2, &h2); if ((w1 != w2) || (h1 != h2)) mask |= CS_LAYOUT; } else mask |= CS_LAYOUT; } else if (draw1 != draw2) mask |= CS_DISPLAY; return mask; } static int UndefProcImage(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementImage *elemX = (ElementImage *) args->elem; int modified = 0; modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); modified |= PerStateInfo_Undefine(tree, &pstImage, &elemX->image, args->state); return modified; } static int ActualProcImage(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementImage *elemX = (ElementImage *) args->elem; ElementImage *masterX = (ElementImage *) args->elem->master; static CONST84 char *optionName[] = { "-draw", "-image", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } case 1: { OBJECT_FOR_STATE(obj, pstImage, image, args->state) break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } ElementType elemTypeImage = { "image", sizeof(ElementImage), imageOptionSpecs, NULL, CreateProcImage, DeleteProcImage, ConfigProcImage, DisplayProcImage, NeededProcImage, NULL, /* heightProc */ WorldChangedProcImage, StateProcImage, UndefProcImage, ActualProcImage, NULL /* onScreenProc */ }; /*****/ typedef struct ElementRect ElementRect; struct ElementRect { Element header; PerStateInfo draw; int width; Tcl_Obj *widthObj; int height; Tcl_Obj *heightObj; PerStateInfo fill; PerStateInfo outline; int outlineWidth; Tcl_Obj *outlineWidthObj; int open; char *openString; int showFocus; }; #define RECT_CONF_FILL 0x0001 #define RECT_CONF_OUTLINE 0x0002 #define RECT_CONF_OUTWIDTH 0x0004 #define RECT_CONF_OPEN 0x0008 #define RECT_CONF_SIZE 0x0010 #define RECT_CONF_FOCUS 0x0020 #define RECT_CONF_DRAW 0x0040 static Tk_OptionSpec rectOptionSpecs[] = { {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, draw.obj), Tk_Offset(ElementRect, draw), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_DRAW}, {TK_OPTION_CUSTOM, "-fill", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, fill.obj), Tk_Offset(ElementRect, fill), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_FILL}, {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, heightObj), Tk_Offset(ElementRect, height), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_SIZE}, {TK_OPTION_STRING, "-open", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementRect, openString), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_OPEN}, {TK_OPTION_CUSTOM, "-outline", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, outline.obj), Tk_Offset(ElementRect, outline), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_OUTLINE}, {TK_OPTION_PIXELS, "-outlinewidth", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, outlineWidthObj), Tk_Offset(ElementRect, outlineWidth), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_OUTWIDTH}, {TK_OPTION_CUSTOM, "-showfocus", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementRect, showFocus), TK_OPTION_NULL_OK, (ClientData) &booleanCO, RECT_CONF_FOCUS}, {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, widthObj), Tk_Offset(ElementRect, width), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_SIZE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcRect(ElementArgs *args) { /* TreeCtrl *tree = args->tree; ElementRect *elemX = (ElementRect *) args->elem;*/ } static int WorldChangedProcRect(ElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & (RECT_CONF_SIZE | RECT_CONF_OUTWIDTH)) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & (RECT_CONF_DRAW | RECT_CONF_FILL | RECT_CONF_OUTLINE | RECT_CONF_OPEN | RECT_CONF_FOCUS)) mask |= CS_DISPLAY; return mask; } static int ConfigProcRect(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementRect *elemX = (ElementRect *) elem; ElementRect savedX; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int i; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } if (args->config.flagSelf & RECT_CONF_OPEN) savedX.open = elemX->open; if (args->config.flagSelf & RECT_CONF_OPEN) { elemX->open = 0; if (elemX->openString != NULL) { int badChar = 0; for (i = 0; elemX->openString[i]; i++) { switch (elemX->openString[i]) { case 'w': case 'W': elemX->open |= 0x01; break; case 'n': case 'N': elemX->open |= 0x02; break; case 'e': case 'E': elemX->open |= 0x04; break; case 's': case 'S': elemX->open |= 0x08; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad open value \"", elemX->openString, "\": must be a string ", "containing zero or more of n, e, s, and w", (char *) NULL); badChar = 1; break; } } if (badChar) break; } if (badChar) continue; } } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); if (args->config.flagSelf & RECT_CONF_OPEN) elemX->open = savedX.open; Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcRect(ElementArgs *args) { ElementRect *elemX = (ElementRect *) args->elem; elemX->showFocus = -1; return TCL_OK; } static void DisplayProcRect(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementRect *elemX = (ElementRect *) elem; ElementRect *masterX = (ElementRect *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width = args->display.width, height = args->display.height; int match, match2; int draw; XColor *color; int open = 0; int outlineWidth = 0; int showFocus = 0; BOOLEAN_FOR_STATE(draw, draw, state) if (!draw) return; if (elemX->outlineWidthObj != NULL) outlineWidth = elemX->outlineWidth; else if ((masterX != NULL) && (masterX->outlineWidthObj != NULL)) outlineWidth = masterX->outlineWidth; if (elemX->openString != NULL) open = elemX->open; else if ((masterX != NULL) && (masterX->openString != NULL)) open = masterX->open; if (elemX->showFocus != -1) showFocus = elemX->showFocus; else if ((masterX != NULL) && (masterX->showFocus != -1)) showFocus = masterX->showFocus; if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, TRUE, TRUE, &x, &y, &width, &height); COLOR_FOR_STATE(color, fill, state) if (color != NULL) { GC gc = Tk_GCForColor(color, Tk_WindowId(tree->tkwin)); XFillRectangle(tree->display, args->display.drawable, gc, x, y, width, height); } COLOR_FOR_STATE(color, outline, state) if ((color != NULL) && (outlineWidth > 0)) { GC gc = Tk_GCForColor(color, Tk_WindowId(tree->tkwin)); if (!(open & 0x01)) XFillRectangle(tree->display, args->display.drawable, gc, x, y, outlineWidth, height); if (!(open & 0x02)) XFillRectangle(tree->display, args->display.drawable, gc, x, y, width, outlineWidth); if (!(open & 0x04)) XFillRectangle(tree->display, args->display.drawable, gc, x + width - outlineWidth, y, outlineWidth, height); if (!(open & 0x08)) XFillRectangle(tree->display, args->display.drawable, gc, x, y + height - outlineWidth, width, outlineWidth); } if (showFocus && (state & STATE_FOCUS) && (state & STATE_ACTIVE)) { DrawActiveOutline(tree, args->display.drawable, args->display.x, args->display.y, args->display.width, args->display.height, open); } } static void NeededProcRect(ElementArgs *args) { Element *elem = args->elem; ElementRect *elemX = (ElementRect *) elem; ElementRect *masterX = (ElementRect *) elem->master; int width = 0, height = 0; int outlineWidth = 0; if (elemX->outlineWidthObj != NULL) outlineWidth = elemX->outlineWidth; else if ((masterX != NULL) && (masterX->outlineWidthObj != NULL)) outlineWidth = masterX->outlineWidth; if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; args->needed.width = MAX(width, outlineWidth * 2); args->needed.height = MAX(height, outlineWidth * 2); } static int StateProcRect(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementRect *elemX = (ElementRect *) elem; ElementRect *masterX = (ElementRect *) elem->master; int match, match2; int draw1, draw2; XColor *f1, *f2; XColor *o1, *o2; int s1, s2; int showFocus = 0; int mask = 0; if (elemX->showFocus != -1) showFocus = elemX->showFocus; else if ((masterX != NULL) && (masterX->showFocus != -1)) showFocus = masterX->showFocus; BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) if (draw1 == -1) draw1 = 1; COLOR_FOR_STATE(f1, fill, args->states.state1) COLOR_FOR_STATE(o1, outline, args->states.state1) s1 = showFocus && (args->states.state1 & STATE_FOCUS) && (args->states.state1 & STATE_ACTIVE); BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if (draw2 == -1) draw2 = 1; COLOR_FOR_STATE(f2, fill, args->states.state2) COLOR_FOR_STATE(o2, outline, args->states.state2) s2 = showFocus && (args->states.state2 & STATE_FOCUS) && (args->states.state2 & STATE_ACTIVE); if ((draw1 != draw2) || (f1 != f2) || (o1 != o2) || (s1 != s2)) mask |= CS_DISPLAY; return mask; } static int UndefProcRect(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementRect *elemX = (ElementRect *) args->elem; int modified = 0; modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); modified |= PerStateInfo_Undefine(tree, &pstColor, &elemX->fill, args->state); modified |= PerStateInfo_Undefine(tree, &pstColor, &elemX->outline, args->state); return modified; } static int ActualProcRect(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementRect *elemX = (ElementRect *) args->elem; ElementRect *masterX = (ElementRect *) args->elem->master; static CONST84 char *optionName[] = { "-draw", "-fill", "-outline", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } case 1: { OBJECT_FOR_STATE(obj, pstColor, fill, args->state) break; } case 2: { OBJECT_FOR_STATE(obj, pstColor, outline, args->state) break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } ElementType elemTypeRect = { "rect", sizeof(ElementRect), rectOptionSpecs, NULL, CreateProcRect, DeleteProcRect, ConfigProcRect, DisplayProcRect, NeededProcRect, NULL, /* heightProc */ WorldChangedProcRect, StateProcRect, UndefProcRect, ActualProcRect, NULL /* onScreenProc */ }; /*****/ typedef struct ElementText ElementText; struct ElementText { Element header; Tcl_Obj *textObj; /* -text */ char *text; int textLen; int stringRepInvalid; struct PerStateGC *gc; }; #define TEXTVAR /* for Tk_SetOptions() */ #define TEXT_CONF_LAYOUT 0x0001 #define TEXT_CONF_DISPLAY 0x0002 #define TEXT_CONF_STRINGREP 0x0040 #ifdef TEXTVAR #define TEXT_CONF_TEXTVAR 0x0080 #endif typedef struct ElementTextData { Tcl_Obj *dataObj; /* -data */ #define TDT_NULL -1 #define TDT_DOUBLE 0 #define TDT_INTEGER 1 #define TDT_LONG 2 #define TDT_STRING 3 #define TDT_TIME 4 int dataType; /* -datatype */ Tcl_Obj *formatObj; /* -format */ } ElementTextData; typedef struct ElementTextLayout { #define TK_JUSTIFY_NULL -1 int justify; /* -justify */ int lines; /* -lines */ Tcl_Obj *widthObj; /* -width */ int width; /* -width */ #define TEXT_WRAP_NULL -1 #define TEXT_WRAP_CHAR 0 #define TEXT_WRAP_NONE 1 #define TEXT_WRAP_WORD 2 int wrap; /* -wrap */ } ElementTextLayout; /* This structure doesn't hold any option values, but it is managed by * the dynamic-option code. */ typedef struct ElementTextLayout2 { TextLayout layout; int layoutWidth; int neededWidth; int totalWidth; } ElementTextLayout2; #define TEXT_STYLE #ifdef TEXT_STYLE typedef struct ElementTextStyle { int underline; /* -underline */ } ElementTextStyle; /* Called by the dynamic-option code when an ElementTextData is allocated. */ static void ElementTextStyleInit( char *data ) { ElementTextStyle *ets = (ElementTextStyle *) data; #define TEXT_UNDERLINE_EMPTYVAL -100000 ets->underline = TEXT_UNDERLINE_EMPTYVAL; } #endif #ifdef TEXTVAR typedef struct ElementTextVar { Tcl_Obj *varNameObj; /* -textvariable */ TreeCtrl *tree; /* needed to redisplay */ TreeItem item; /* needed to redisplay */ TreeItemColumn column; /* needed to redisplay */ } ElementTextVar; #endif /* Called by the dynamic-option code when an ElementTextData is allocated. */ static void ElementTextDataInit( char *data ) { ElementTextData *etd = (ElementTextData *) data; etd->dataType = TDT_NULL; } /* Called by the dynamic-option code when an ElementTextLayout is allocated. */ static void ElementTextLayoutInit( char *data ) { ElementTextLayout *etl = (ElementTextLayout *) data; etl->justify = TK_JUSTIFY_NULL; etl->lines = -1; etl->wrap = TEXT_WRAP_NULL; } static CONST84 char *textDataTypeST[] = { "double", "integer", "long", "string", "time", (char *) NULL }; static CONST84 char *textJustifyST[] = { "left", "right", "center", (char *) NULL }; static CONST84 char *textWrapST[] = { "char", "none", "word", (char *) NULL }; static Tk_OptionSpec textOptionSpecs[] = { {TK_OPTION_CUSTOM, "-data", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP}, {TK_OPTION_CUSTOM, "-datatype", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP}, {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-fill", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-font", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_CUSTOM, "-format", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP}, {TK_OPTION_CUSTOM, "-justify", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_CUSTOM, "-lines", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_STRING, "-text", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementText, textObj), Tk_Offset(ElementText, text), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP}, #ifdef TEXTVAR {TK_OPTION_CUSTOM, "-textvariable", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP | TEXT_CONF_TEXTVAR}, #endif #ifdef TEXT_STYLE {TK_OPTION_CUSTOM, "-underline", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_DISPLAY}, #endif {TK_OPTION_CUSTOM, "-width", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_CUSTOM, "-wrap", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(Element, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; static int WorldChangedProcText(ElementArgs *args) { /* TreeCtrl *tree = args->tree;*/ Element *elem = args->elem; ElementText *elemX = (ElementText *) elem; /* ElementText *masterX = (ElementText *) elem->master;*/ int flagT = args->change.flagTree; int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & TEXT_CONF_STRINGREP) { elemX->stringRepInvalid = TRUE; } if (elemX->stringRepInvalid || ((flagS | flagM) & TEXT_CONF_LAYOUT) || /* Not always needed */ (flagT & TREE_CONF_FONT)) { mask |= CS_DISPLAY | CS_LAYOUT; } if ((flagS | flagM) & TEXT_CONF_DISPLAY) mask |= CS_DISPLAY; return mask; } static void TextUpdateStringRep(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; Tcl_Obj *dataObj, *formatObj, *textObj; ElementTextData *etd, *etdM = NULL; #ifdef TEXTVAR ElementTextVar *etv; Tcl_Obj *varNameObj; #endif int dataType; if ((elemX->textObj == NULL) && (elemX->text != NULL)) { ckfree(elemX->text); elemX->text = NULL; } /* If -text is specified, -data, -datatype and -format are ignored */ textObj = elemX->textObj; if ((textObj == NULL) && (masterX != NULL)) textObj = masterX->textObj; if (textObj != NULL) { if (elemX->textObj != NULL) (void) Tcl_GetStringFromObj(elemX->textObj, &elemX->textLen); return; } #ifdef TEXTVAR etv = (ElementTextVar *) DynamicOption_FindData(elem->options, 1001); varNameObj = etv ? etv->varNameObj : NULL; if (varNameObj != NULL) { Tcl_Obj *valueObj = Tcl_ObjGetVar2(tree->interp, varNameObj, NULL, TCL_GLOBAL_ONLY); if (valueObj == NULL) { /* not possible I think */ } else { char *string = Tcl_GetStringFromObj(valueObj, &elemX->textLen); elemX->text = ckalloc(elemX->textLen); memcpy(elemX->text, string, elemX->textLen); } return; } #endif etd = (ElementTextData *) DynamicOption_FindData(elem->options, 1006); if (masterX != NULL) etdM = (ElementTextData *) DynamicOption_FindData(elem->master->options, 1006); dataObj = etd ? etd->dataObj : NULL; if ((dataObj == NULL) && (etdM != NULL)) dataObj = etdM->dataObj; dataType = etd ? etd->dataType : TDT_NULL; if ((dataType == TDT_NULL) && (etdM != NULL)) dataType = etdM->dataType; formatObj = etd ? etd->formatObj : NULL; if ((formatObj == NULL) && (etdM != NULL)) formatObj = etdM->formatObj; /* Only create a string rep if elemX (not masterX) has dataObj, dataType or formatObj. */ if ((dataObj != NULL) && (dataType != TDT_NULL) && ((etd != NULL) && ((etd->dataObj != NULL) || (etd->dataType != TDT_NULL) || (etd->formatObj != NULL)))) { int i, objc = 0; Tcl_Obj *objv[5], *resultObj = NULL; static Tcl_Obj *staticObj[3] = { NULL }; static Tcl_Obj *staticFormat[4] = { NULL }; Tcl_ObjCmdProc *clockObjCmd = NULL, *formatObjCmd = NULL; ClientData clockClientData = NULL, formatClientData = NULL; Tcl_CmdInfo cmdInfo; if (staticFormat[0] == NULL) { staticFormat[0] = Tcl_NewStringObj("%g", -1); staticFormat[1] = Tcl_NewStringObj("%d", -1); staticFormat[2] = Tcl_NewStringObj("%ld", -1); staticFormat[3] = Tcl_NewStringObj("%s", -1); for (i = 0; i < 4; i++) Tcl_IncrRefCount(staticFormat[i]); } if (staticObj[0] == NULL) { staticObj[0] = Tcl_NewStringObj("clock", -1); staticObj[1] = Tcl_NewStringObj("format", -1); staticObj[2] = Tcl_NewStringObj("-format", -1); for (i = 0; i < 3; i++) Tcl_IncrRefCount(staticObj[i]); } if (Tcl_GetCommandInfo(tree->interp, "::clock", &cmdInfo) == 1) { clockObjCmd = cmdInfo.objProc; clockClientData = cmdInfo.objClientData; } if (Tcl_GetCommandInfo(tree->interp, "::format", &cmdInfo) == 1) { formatObjCmd = cmdInfo.objProc; formatClientData = cmdInfo.objClientData; } /* Important to remove any shared result object, otherwise * calls like Tcl_SetStringObj(Tcl_GetObjResult()) fail. */ Tcl_ResetResult(tree->interp); switch (dataType) { case TDT_DOUBLE: if (formatObjCmd == NULL) break; if (formatObj == NULL) formatObj = staticFormat[0]; objv[objc++] = staticObj[1]; /* format */ objv[objc++] = formatObj; objv[objc++] = dataObj; if (formatObjCmd(formatClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; case TDT_INTEGER: if (formatObjCmd == NULL) break; if (formatObj == NULL) formatObj = staticFormat[1]; objv[objc++] = staticObj[1]; /* format */ objv[objc++] = formatObj; objv[objc++] = dataObj; if (formatObjCmd(formatClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; case TDT_LONG: if (formatObjCmd == NULL) break; if (formatObj == NULL) formatObj = staticFormat[2]; objv[objc++] = staticObj[1]; /* format */ objv[objc++] = formatObj; objv[objc++] = dataObj; if (formatObjCmd(formatClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; case TDT_STRING: if (formatObjCmd == NULL) break; if (formatObj == NULL) formatObj = staticFormat[3]; objv[objc++] = staticObj[1]; /* format */ objv[objc++] = formatObj; objv[objc++] = dataObj; if (formatObjCmd(formatClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; case TDT_TIME: if (clockObjCmd == NULL) break; objv[objc++] = staticObj[0]; objv[objc++] = staticObj[1]; objv[objc++] = dataObj; if (formatObj != NULL) { objv[objc++] = staticObj[2]; objv[objc++] = formatObj; } if (clockObjCmd(clockClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; default: panic("unknown ElementText dataType"); break; } if (resultObj != NULL) { char *string = Tcl_GetStringFromObj(resultObj, &elemX->textLen); elemX->text = ckalloc(elemX->textLen); memcpy(elemX->text, string, elemX->textLen); } } } static ElementTextLayout2 * TextUpdateLayout( char *func, ElementArgs *args, int fixedWidth, int maxWidth ) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; int state = args->state; Tk_Font tkfont; char *text = NULL; int textLen = 0; int justify = TK_JUSTIFY_LEFT; int lines = 0; int wrap = TEXT_WRAP_WORD; int width = 0; int flags = 0; int i, multiLine = FALSE; int textWidth; ElementTextLayout *etl, *etlM = NULL; ElementTextLayout2 *etl2; DynamicOption *opt; if (tree->debug.enable && tree->debug.textLayout) dbwin("TextUpdateLayout: %s %p (%s) %s\n", Tk_PathName(tree->tkwin), elemX, masterX ? "instance" : "master", func); etl2 = (ElementTextLayout2 *) DynamicOption_FindData(elem->options, 1007); if (etl2 != NULL && etl2->layout != NULL) { if (tree->debug.enable && tree->debug.textLayout) dbwin(" FREE\n"); TextLayout_Free(etl2->layout); etl2->layout = NULL; } if (elemX->text != NULL) { text = elemX->text; textLen = elemX->textLen; } else if ((masterX != NULL) && (masterX->text != NULL)) { text = masterX->text; textLen = masterX->textLen; } if ((text == NULL) || (textLen == 0)) return etl2; etl = (ElementTextLayout *) DynamicOption_FindData(elem->options, 1005); if (masterX != NULL) etlM = (ElementTextLayout *) DynamicOption_FindData(elem->master->options, 1005); if (etl != NULL && etl->lines != -1) lines = etl->lines; else if (etlM != NULL && etlM->lines != -1) lines = etlM->lines; if (lines == 1) return etl2; tkfont = DO_FontForState(tree, elem, 1004, state); if (tkfont == NULL) tkfont = tree->tkfont; if (etl != NULL && etl->wrap != TEXT_WRAP_NULL) wrap = etl->wrap; else if (etlM != NULL && etlM->wrap != TEXT_WRAP_NULL) wrap = etlM->wrap; if (wrap != TEXT_WRAP_NONE) { if (fixedWidth >= 0) width = fixedWidth; else if (maxWidth >= 0) width = maxWidth; if (etl != NULL && etl->widthObj != NULL) { if (!width || (etl->width < width)) width = etl->width; } else if ((etlM != NULL) && (etlM->widthObj != NULL)) { if (!width || (etlM->width < width)) width = etlM->width; } } for (i = 0; i < textLen; i++) { if ((text[i] == '\n') || (text[i] == '\r')) { multiLine = TRUE; break; } } if (tree->debug.enable && tree->debug.textLayout) dbwin(" lines %d multiLine %d width %d wrap %s\n", lines, multiLine, width, textWrapST[wrap]); if (!multiLine) { if (width == 0) return etl2; textWidth = Tk_TextWidth(tkfont, text, textLen); if (tree->debug.enable && tree->debug.textLayout) dbwin(" textWidth %d\n", textWidth); if (width >= textWidth) return etl2; } if (etl != NULL && etl->justify != TK_JUSTIFY_NULL) justify = etl->justify; else if (etlM != NULL && etlM->justify != TK_JUSTIFY_NULL) justify = etlM->justify; if (wrap == TEXT_WRAP_WORD) flags |= TK_WHOLE_WORDS; opt = (DynamicOption *) DynamicOption_AllocIfNeeded(tree, &elem->options, 1007, sizeof(ElementTextLayout2), NULL); etl2 = (ElementTextLayout2 *) opt->data; etl2->layout = TextLayout_Compute(tkfont, text, Tcl_NumUtfChars(text, textLen), width, justify, lines, flags); if (tree->debug.enable && tree->debug.textLayout) dbwin(" ALLOC\n"); return etl2; } #ifdef TEXTVAR /* static Tcl_VarTraceProc VarTraceProc_Text; */ static void TextTraceUnset(Tcl_Interp *interp, ElementText *elemX); static void TextTraceSet(Tcl_Interp *interp, ElementText *elemX); static char *VarTraceProc_Text(ClientData clientData, Tcl_Interp *interp, CONST char *name1, CONST char *name2, int flags) { ElementText *elemX = (ElementText *) clientData; ElementText *masterX = (ElementText *) elemX->header.master; ElementTextVar *etv = (ElementTextVar *) DynamicOption_FindData(elemX->header.options, 1001); Tcl_Obj *varNameObj = etv ? etv->varNameObj : NULL; Tcl_Obj *valueObj; /* * If the variable is unset, then immediately recreate it unless * the whole interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { char *text = elemX->text; int textLen = elemX->textLen; if ((text == NULL) && (masterX != NULL)) { text = masterX->text; textLen = masterX->textLen; } if (text != NULL) { valueObj = Tcl_NewStringObj(text, textLen); } else { valueObj = Tcl_NewStringObj("", 0); } Tcl_IncrRefCount(valueObj); Tcl_ObjSetVar2(interp, varNameObj, NULL, valueObj, TCL_GLOBAL_ONLY); Tcl_DecrRefCount(valueObj); TextTraceSet(interp, elemX); } return (char *) NULL; } elemX->stringRepInvalid = TRUE; Tree_ElementChangedItself(etv->tree, etv->item, etv->column, (Element *) elemX, TEXT_CONF_TEXTVAR, CS_LAYOUT | CS_DISPLAY); return (char *) NULL; } static void TextTraceSet(Tcl_Interp *interp, ElementText *elemX) { ElementTextVar *etv = (ElementTextVar *) DynamicOption_FindData(elemX->header.options, 1001); Tcl_Obj *varNameObj = etv ? etv->varNameObj : NULL; if (varNameObj != NULL) { Tcl_TraceVar2(interp, Tcl_GetString(varNameObj), NULL, TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS, (Tcl_VarTraceProc*)VarTraceProc_Text, (ClientData) elemX); } } static void TextTraceUnset(Tcl_Interp *interp, ElementText *elemX) { ElementTextVar *etv = (ElementTextVar *) DynamicOption_FindData(elemX->header.options, 1001); Tcl_Obj *varNameObj = etv ? etv->varNameObj : NULL; if (varNameObj != NULL) { Tcl_UntraceVar2(interp, Tcl_GetString(varNameObj), NULL, TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS, (Tcl_VarTraceProc*)VarTraceProc_Text, (ClientData) elemX); } } #endif /* TEXTVAR */ static void DeleteProcText(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementTextLayout2 *etl2; if (elemX->gc != NULL) PerStateGC_Free(tree, &elemX->gc); if ((elemX->textObj == NULL) && (elemX->text != NULL)) { ckfree(elemX->text); elemX->text = NULL; } etl2 = (ElementTextLayout2 *) DynamicOption_FindData(elem->options, 1007); if (etl2 != NULL && etl2->layout != NULL) TextLayout_Free(etl2->layout); DynamicOption_Free1(tree, &elem->options, 1007, sizeof(ElementTextLayout2)); #ifdef TEXTVAR TextTraceUnset(tree->interp, elemX); #endif } static int ConfigProcText(ElementArgs *args) { TreeCtrl *tree = args->tree; Tcl_Interp *interp = tree->interp; Element *elem = args->elem; ElementText *elemX = (ElementText *) elem; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; #ifdef TEXTVAR ElementTextVar *etv; Tcl_Obj *varNameObj; #endif #ifdef TEXTVAR TextTraceUnset(interp, elemX); #endif for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } #ifdef TEXTVAR etv = (ElementTextVar *) DynamicOption_FindData(elem->options, 1001); if (etv != NULL) { etv->tree = tree; etv->item = args->config.item; etv->column = args->config.column; varNameObj = etv->varNameObj; } else varNameObj = NULL; if (varNameObj != NULL) { Tcl_Obj *valueObj; valueObj = Tcl_ObjGetVar2(interp, varNameObj, NULL, TCL_GLOBAL_ONLY); if (valueObj == NULL) { ElementText *masterX = (ElementText *) elem->master; char *text = elemX->text; int textLen = elemX->textLen; if ((text == NULL) && (masterX != NULL)) { text = masterX->text; textLen = masterX->textLen; } /* This may not be the current string rep */ if (text != NULL) { valueObj = Tcl_NewStringObj(text, textLen); } else { valueObj = Tcl_NewStringObj("", 0); } Tcl_IncrRefCount(valueObj); /* This validates the variable name. We get an error * if it is the name of an array */ if (Tcl_ObjSetVar2(interp, varNameObj, NULL, valueObj, TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) { Tcl_DecrRefCount(valueObj); continue; } Tcl_DecrRefCount(valueObj); } } #endif Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); } } #ifdef TEXTVAR TextTraceSet(interp, elemX); #endif if (error) { Tcl_SetObjResult(interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } return TCL_OK; } static int CreateProcText(ElementArgs *args) { /* ElementText *elemX = (ElementText *) args->elem;*/ return TCL_OK; } static ElementTextLayout2 * TextRedoLayoutIfNeeded( char *func, ElementArgs *args, int fixedWidth ) { Element *elem = args->elem; /* ElementText *elemX = (ElementText *) elem;*/ ElementText *masterX = (ElementText *) elem->master; int doLayout = 0; int wrap = TEXT_WRAP_WORD; ElementTextLayout *etl, *etlM = NULL; ElementTextLayout2 *etl2; etl = (ElementTextLayout *) DynamicOption_FindData(elem->options, 1005); if (masterX != NULL) etlM = (ElementTextLayout *) DynamicOption_FindData(elem->master->options, 1005); etl2 = (ElementTextLayout2 *) DynamicOption_FindData(elem->options, 1007); /* If text wrapping is disabled, the layout doesn't change */ if (etl != NULL && etl->wrap != TEXT_WRAP_NULL) wrap = etl->wrap; else if ((etlM != NULL) && (etlM->wrap != TEXT_WRAP_NULL)) wrap = etlM->wrap; if (wrap == TEXT_WRAP_NONE) return etl2; if (etl2 != NULL && etl2->layout != NULL) { /* See comment in NeededProc about totalWidth */ if ((etl2->neededWidth != -1) && (fixedWidth >= etl2->neededWidth)) fixedWidth = etl2->totalWidth; /* Already layed out at this width */ if (fixedWidth == etl2->layoutWidth) return etl2; } /* May switch from layout -> no layout or vice versa */ if (etl2 == NULL || etl2->layout == NULL) doLayout = 1; /* Width was constrained and we have more space now */ else if ((etl2->layoutWidth != -1) && (fixedWidth > etl2->layoutWidth)) doLayout = 1; /* Width was unconstrained or we have less space now */ else { int width; TextLayout_Size(etl2->layout, &width, NULL); /* Redo if we are narrower than the layout */ if (fixedWidth < width) doLayout = 1; } if (doLayout) etl2 = TextUpdateLayout(func, args, fixedWidth, -1); if (etl2 != NULL) etl2->layoutWidth = (etl2->layout != NULL) ? fixedWidth : -1; return etl2; } static void DisplayProcText(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width, height; int draw; XColor *color; char *text = elemX->text; int textLen = elemX->textLen; Tk_Font tkfont; TextLayout layout = NULL; Tk_FontMetrics fm; GC gc; int bytesThatFit, pixelsForText; char *ellipsis = "..."; TkRegion clipRgn = NULL; ElementTextLayout2 *etl2; #ifdef TEXT_STYLE ElementTextStyle *ets, *etsM = NULL; int underline = TEXT_UNDERLINE_EMPTYVAL; #endif draw = DO_BooleanForState(tree, elem, 1002, state); if (!draw) return; if ((text == NULL) && (masterX != NULL)) { text = masterX->text; textLen = masterX->textLen; } if (text == NULL) /* always false (or layout sets height/width to zero) */ return; color = DO_ColorForState(tree, elem, 1003, state); tkfont = DO_FontForState(tree, elem, 1004, state); /* FIXME: -font {"" {state...}}*/ if ((color != NULL) || (tkfont != NULL)) { XGCValues gcValues; unsigned long gcMask = 0; if (color == NULL) color = tree->fgColorPtr; gcValues.foreground = color->pixel; gcMask |= GCForeground; if (tkfont == NULL) tkfont = tree->tkfont; gcValues.font = Tk_FontId(tkfont); gcMask |= GCFont; gcValues.graphics_exposures = False; gcMask |= GCGraphicsExposures; gc = PerStateGC_Get(tree, (masterX != NULL) ? &masterX->gc : &elemX->gc, gcMask, &gcValues); } else { tkfont = tree->tkfont; gc = tree->textGC; } #ifdef TEXT_STYLE ets = (ElementTextStyle *) DynamicOption_FindData(elem->options, 1008); if (ets != NULL && ets->underline != TEXT_UNDERLINE_EMPTYVAL) underline = ets->underline; else if (masterX != NULL) { etsM = (ElementTextStyle *) DynamicOption_FindData(elem->master->options, 1008); if (etsM != NULL && etsM->underline != TEXT_UNDERLINE_EMPTYVAL) underline = etsM->underline; } #endif etl2 = TextRedoLayoutIfNeeded("DisplayProcText", args, args->display.width); if (etl2 != NULL && etl2->layout != NULL) layout = etl2->layout; if (layout != NULL) { TextLayout_Size(layout, &width, &height); /* Hack -- The actual size of the text may be slightly smaller than * the available space when squeezed. If so we don't want to center * the text horizontally */ if ((etl2->neededWidth == -1) || (etl2->neededWidth > width)) width = args->display.width; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); /* Use clipping if text is taller than display height */ if (height > args->display.height) { XRectangle rect; clipRgn = TkCreateRegion(); rect.x = x; rect.y = y; rect.width = args->display.width; rect.height = args->display.height; TkUnionRectWithRegion(&rect, clipRgn, clipRgn); TkSetRegion(tree->display, gc, clipRgn); } TextLayout_Draw(tree->display, args->display.drawable, gc, layout, x, y, 0, -1, underline); if (clipRgn != NULL) { UnsetClipMask(tree, args->display.drawable, gc); TkDestroyRegion(clipRgn); } return; } Tk_GetFontMetrics(tkfont, &fm); pixelsForText = args->display.width; bytesThatFit = Ellipsis(tkfont, text, textLen, &pixelsForText, ellipsis, FALSE); width = pixelsForText, height = fm.linespace; /* Hack -- The actual size of the text may be slightly smaller than * the available space when squeezed. If so we don't want to center * the text horizontally */ if (bytesThatFit != textLen) width = args->display.width; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); /* Use clipping if text is taller than display height */ if (height > args->display.height) { XRectangle rect; clipRgn = TkCreateRegion(); rect.x = x; rect.y = y; rect.width = args->display.width; rect.height = args->display.height; TkUnionRectWithRegion(&rect, clipRgn, clipRgn); TkSetRegion(tree->display, gc, clipRgn); } if (bytesThatFit != textLen) { char staticStr[256], *buf = staticStr; int bufLen = abs(bytesThatFit); int ellipsisLen = (int)strlen(ellipsis); if (bufLen + ellipsisLen > sizeof(staticStr)) buf = ckalloc(bufLen + ellipsisLen); memcpy(buf, text, bufLen); if (bytesThatFit > 0) { memcpy(buf + bufLen, ellipsis, ellipsisLen); bufLen += ellipsisLen; } Tk_DrawChars(tree->display, args->display.drawable, gc, tkfont, buf, bufLen, x, y + fm.ascent); #ifdef TEXT_STYLE if (underline >= 0 && underline < Tcl_NumUtfChars(buf, abs(bytesThatFit))) { CONST char *fstBytePtr = Tcl_UtfAtIndex(buf, underline); CONST char *sndBytePtr = Tcl_UtfNext(fstBytePtr); Tk_UnderlineChars(tree->display, args->display.drawable, gc, tkfont, buf, x, y + fm.ascent, (int)(fstBytePtr - buf), (int)(sndBytePtr - buf)); } #endif if (buf != staticStr) ckfree(buf); } else { Tk_DrawChars(tree->display, args->display.drawable, gc, tkfont, text, textLen, x, y + fm.ascent); #ifdef TEXT_STYLE if (underline >= 0 && underline < Tcl_NumUtfChars(text, textLen)) { CONST char *fstBytePtr = Tcl_UtfAtIndex(text, underline); CONST char *sndBytePtr = Tcl_UtfNext(fstBytePtr); Tk_UnderlineChars(tree->display, args->display.drawable, gc, tkfont, text, x, y + fm.ascent, (int)(fstBytePtr - text), (int)(sndBytePtr - text)); } #endif } if (clipRgn != NULL) { UnsetClipMask(tree, args->display.drawable, gc); TkDestroyRegion(clipRgn); } } static void NeededProcText(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; int state = args->state; char *text = NULL; int textLen = 0; Tk_Font tkfont; Tk_FontMetrics fm; int width = 0, height = 0; ElementTextLayout *etl, *etlM = NULL; ElementTextLayout2 *etl2; etl = (ElementTextLayout *) DynamicOption_FindData(args->elem->options, 1005); if (masterX != NULL) etlM = (ElementTextLayout *) DynamicOption_FindData(args->elem->master->options, 1005); if ((masterX != NULL) && masterX->stringRepInvalid) { args->elem = (Element *) masterX; TextUpdateStringRep(args); args->elem = elem; masterX->stringRepInvalid = FALSE; } if (elemX->stringRepInvalid) { TextUpdateStringRep(args); elemX->stringRepInvalid = FALSE; } etl2 = TextUpdateLayout("NeededProcText", args, args->needed.fixedWidth, args->needed.maxWidth); if (etl2 != NULL) { etl2->layoutWidth = -1; etl2->neededWidth = -1; } if (etl2 != NULL && etl2->layout != NULL) { TextLayout_Size(etl2->layout, &width, &height); if (args->needed.fixedWidth >= 0) etl2->layoutWidth = args->needed.fixedWidth; else if (args->needed.maxWidth >= 0) etl2->layoutWidth = args->needed.maxWidth; etl2->neededWidth = width; /* * Hack -- If we call TextLayout_Compute() with the same width * returned by TextLayout_Size(), we may get a different layout. * I think this has to do with whitespace at the end of lines. * So if HeightProc or DisplayProc is given neededWidth, I do the * layout at totalWidth, not neededWidth. */ etl2->totalWidth = TextLayout_TotalWidth(etl2->layout); } else { if (elemX->text != NULL) { text = elemX->text; textLen = elemX->textLen; } else if ((masterX != NULL) && (masterX->text != NULL)) { text = masterX->text; textLen = masterX->textLen; } if (text != NULL) { int maxWidth = -1; tkfont = DO_FontForState(tree, elem, 1004, state); if (tkfont == NULL) tkfont = tree->tkfont; width = Tk_TextWidth(tkfont, text, textLen); if (etl != NULL && etl->widthObj != NULL) maxWidth = etl->width; else if ((etlM != NULL) && (etlM->widthObj != NULL)) maxWidth = etlM->width; if ((maxWidth >= 0) && (maxWidth < width)) width = maxWidth; Tk_GetFontMetrics(tkfont, &fm); height = fm.linespace; } } args->needed.width = width; args->needed.height = height; } static void HeightProcText(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; int state = args->state; int height = 0; char *text = NULL; Tk_Font tkfont; Tk_FontMetrics fm; ElementTextLayout2 *etl2; etl2 = TextRedoLayoutIfNeeded("HeightProcText", args, args->height.fixedWidth); if (etl2 != NULL && etl2->layout != NULL) { TextLayout_Size(etl2->layout, NULL, &height); } else { if (elemX->text != NULL) { text = elemX->text; } else if ((masterX != NULL) && (masterX->text != NULL)) { text = masterX->text; } if (text != NULL) { tkfont = DO_FontForState(tree, elem, 1004, state); if (tkfont == NULL) tkfont = tree->tkfont; Tk_GetFontMetrics(tkfont, &fm); height = fm.linespace; } } args->height.height = height; } int Element_GetSortData(TreeCtrl *tree, Element *elem, int type, long *lv, double *dv, char **sv) { ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; ElementTextData *etd, *etdM = NULL; Tcl_Obj *dataObj = NULL; int dataType = TDT_NULL; Tcl_Obj *obj; etd = (ElementTextData *) DynamicOption_FindData(elem->options, 1006); if (etd != NULL) { dataObj = etd->dataObj; dataType = etd->dataType; } if (dataType == TDT_NULL && masterX != NULL) { etdM = (ElementTextData *) DynamicOption_FindData(elem->master->options, 1006); /* FIXME: get dataObj from master? */ if (etdM != NULL) dataType = etdM->dataType; } switch (type) { case SORT_ASCII: case SORT_DICT: if (dataObj != NULL && dataType != TDT_NULL) (*sv) = Tcl_GetString(dataObj); else (*sv) = elemX->text; break; case SORT_DOUBLE: if (dataObj != NULL && dataType == TDT_DOUBLE) obj = dataObj; else obj = elemX->textObj; if (obj == NULL) return TCL_ERROR; if (Tcl_GetDoubleFromObj(tree->interp, obj, dv) != TCL_OK) return TCL_ERROR; break; case SORT_LONG: if (dataObj != NULL && dataType != TDT_NULL) { if (dataType == TDT_LONG || dataType == TDT_TIME) { if (Tcl_GetLongFromObj(tree->interp, dataObj, lv) != TCL_OK) return TCL_ERROR; break; } if (dataType == TDT_INTEGER) { int iv; if (Tcl_GetIntFromObj(tree->interp, dataObj, &iv) != TCL_OK) return TCL_ERROR; (*lv) = iv; break; } } if (elemX->textObj != NULL) if (Tcl_GetLongFromObj(tree->interp, elemX->textObj, lv) != TCL_OK) return TCL_ERROR; break; } return TCL_OK; } static int StateProcText(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; /* ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master;*/ int draw1, draw2; XColor *f1, *f2; Tk_Font tkfont1, tkfont2; int mask = 0; draw1 = DO_BooleanForState(tree, elem, 1002, args->states.state1); if (draw1 == -1) draw1 = 1; f1 = DO_ColorForState(tree, elem, 1003, args->states.state1); tkfont1 = DO_FontForState(tree, elem, 1004, args->states.state1); draw2 = DO_BooleanForState(tree, elem, 1002, args->states.state2); if (draw2 == -1) draw2 = 1; f2 = DO_ColorForState(tree, elem, 1003, args->states.state2); tkfont2 = DO_FontForState(tree, elem, 1004, args->states.state2); if (tkfont1 != tkfont2) mask |= CS_DISPLAY | CS_LAYOUT; if ((draw1 != draw2) || (f1 != f2)) mask |= CS_DISPLAY; return mask; } static int UndefProcText(ElementArgs *args) { TreeCtrl *tree = args->tree; /* ElementText *elemX = (ElementText *) args->elem;*/ int modified = 0; PerStateInfo *psi; if ((psi = (PerStateInfo *) DynamicOption_FindData(args->elem->options, 1002)) != NULL) modified |= PerStateInfo_Undefine(tree, &pstBoolean, psi, args->state); if ((psi = (PerStateInfo *) DynamicOption_FindData(args->elem->options, 1003)) != NULL) modified |= PerStateInfo_Undefine(tree, &pstColor, psi, args->state); if ((psi = (PerStateInfo *) DynamicOption_FindData(args->elem->options, 1004)) != NULL) modified |= PerStateInfo_Undefine(tree, &pstFont, psi, args->state); return modified; } static int ActualProcText(ElementArgs *args) { TreeCtrl *tree = args->tree; /* ElementText *elemX = (ElementText *) args->elem; ElementText *masterX = (ElementText *) args->elem->master;*/ static CONST84 char *optionName[] = { "-draw", "-fill", "-font", (char *) NULL }; int index; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { obj = DO_ObjectForState(tree, &pstBoolean, args->elem, 1002, args->state); break; } case 1: { obj = DO_ObjectForState(tree, &pstColor, args->elem, 1003, args->state); break; } case 2: { obj = DO_ObjectForState(tree, &pstFont, args->elem, 1004, args->state); break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } ElementType elemTypeText = { "text", sizeof(ElementText), textOptionSpecs, NULL, CreateProcText, DeleteProcText, ConfigProcText, DisplayProcText, NeededProcText, HeightProcText, WorldChangedProcText, StateProcText, UndefProcText, ActualProcText, NULL /* onScreenProc */ }; /*****/ typedef struct ElementWindow ElementWindow; struct ElementWindow { Element header; PerStateInfo draw; /* -draw */ TreeCtrl *tree; TreeItem item; /* Needed if window changes size */ TreeItemColumn column; /* Needed if window changes size */ Tk_Window tkwin; /* Window associated with item. NULL means * window has been destroyed. */ int destroy; /* Destroy window when element * is deleted */ #define CLIP_WINDOW 1 #ifdef CLIP_WINDOW int clip; /* TRUE if tkwin is a borderless frame * widget whose first child is the actual * window we want displayed. */ Tk_Window child; /* The first child of tkwin. tkwin is resized * so that it is never out-of-bounds, and * the child is positioned within tkwin to * provide clipping of the child. */ #endif }; #define EWIN_CONF_WINDOW 0x0001 #define EWIN_CONF_DRAW 0x0002 static Tk_OptionSpec windowOptionSpecs[] = { #ifdef CLIP_WINDOW {TK_OPTION_CUSTOM, "-clip", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementWindow, clip), TK_OPTION_NULL_OK, (ClientData) &booleanCO, 0}, #endif {TK_OPTION_CUSTOM, "-destroy", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementWindow, destroy), TK_OPTION_NULL_OK, (ClientData) &booleanCO, 0}, {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementWindow, draw.obj), Tk_Offset(ElementWindow, draw), TK_OPTION_NULL_OK, (ClientData) NULL, EWIN_CONF_DRAW}, {TK_OPTION_WINDOW, "-window", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementWindow, tkwin), TK_OPTION_NULL_OK, (ClientData) NULL, EWIN_CONF_WINDOW}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void WinItemStructureProc(clientData, eventPtr) ClientData clientData; /* Pointer to record describing window elem. */ XEvent *eventPtr; /* Describes what just happened. */ { ElementWindow *elemX = (ElementWindow *) clientData; if (eventPtr->type == DestroyNotify) { elemX->tkwin = elemX->child = NULL; Tree_ElementChangedItself(elemX->tree, elemX->item, elemX->column, (Element *) elemX, EWIN_CONF_WINDOW, CS_LAYOUT | CS_DISPLAY); } } static void WinItemRequestProc(clientData, tkwin) ClientData clientData; /* Pointer to record for window item. */ Tk_Window tkwin; /* Window that changed its desired * size. */ { ElementWindow *elemX = (ElementWindow *) clientData; #ifdef CLIP_WINDOW /* We don't care about size changes for the clip window. */ if (elemX->child != NULL && tkwin != elemX->child) return; #endif Tree_ElementChangedItself(elemX->tree, elemX->item, elemX->column, (Element *) elemX, EWIN_CONF_WINDOW, CS_LAYOUT | CS_DISPLAY); } static void WinItemLostSlaveProc(clientData, tkwin) ClientData clientData; /* WindowItem structure for slave window that * was stolen away. */ Tk_Window tkwin; /* Tk's handle for the slave window. */ { ElementWindow *elemX = (ElementWindow *) clientData; TreeCtrl *tree = elemX->tree; #ifdef CLIP_WINDOW /* If either window is lost to another geometry manager, forget * about both windows. */ if (elemX->child != NULL) { Tk_DeleteEventHandler(elemX->child, StructureNotifyMask, (Tk_EventProc*)WinItemStructureProc, (ClientData) elemX); if (tkwin != elemX->child) { Tk_ManageGeometry(elemX->child, (Tk_GeomMgr *) NULL, (ClientData) NULL); Tk_UnmapWindow(elemX->child); } elemX->child = NULL; } if (elemX->tkwin != NULL) { Tk_DeleteEventHandler(elemX->tkwin, StructureNotifyMask, (Tk_EventProc*)WinItemStructureProc, (ClientData) elemX); if (tkwin != elemX->tkwin) { Tk_ManageGeometry(elemX->tkwin, (Tk_GeomMgr *) NULL, (ClientData) NULL); if (tree->tkwin != Tk_Parent(elemX->tkwin)) { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } Tk_UnmapWindow(elemX->tkwin); } elemX->tkwin = NULL; } #else Tk_DeleteEventHandler(elemX->tkwin, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); if (tree->tkwin != Tk_Parent(elemX->tkwin)) { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } Tk_UnmapWindow(elemX->tkwin); elemX->tkwin = NULL; #endif Tree_ElementChangedItself(elemX->tree, elemX->item, elemX->column, (Element *) elemX, EWIN_CONF_WINDOW, CS_LAYOUT | CS_DISPLAY); } static Tk_GeomMgr winElemGeomType = { "treectrl", /* name */ (Tk_GeomRequestProc*)WinItemRequestProc, /* requestProc */ (Tk_GeomLostSlaveProc*)WinItemLostSlaveProc, /* lostSlaveProc */ }; static void DeleteProcWindow(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; ElementWindow *masterX = (ElementWindow *) elem->master; if (elemX->tkwin != NULL) { #ifdef CLIP_WINDOW if (elemX->child != NULL) { Tk_DeleteEventHandler(elemX->child, StructureNotifyMask, (Tk_EventProc*)WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->child, (Tk_GeomMgr *) NULL, (ClientData) NULL); Tk_UnmapWindow(elemX->child); elemX->child = NULL; } #endif Tk_DeleteEventHandler(elemX->tkwin, StructureNotifyMask, (Tk_EventProc*)WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->tkwin, (Tk_GeomMgr *) NULL, (ClientData) NULL); if (tree->tkwin != Tk_Parent(elemX->tkwin)) { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } Tk_UnmapWindow(elemX->tkwin); if ((elemX->destroy == 1) || ((masterX != NULL) && (masterX->destroy == 1))) { Tk_DestroyWindow(elemX->tkwin); } elemX->tkwin = NULL; } } static int WorldChangedProcWindow(ElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & (EWIN_CONF_DRAW)) mask |= CS_DISPLAY; if ((flagS | flagM) & (EWIN_CONF_WINDOW)) mask |= CS_DISPLAY | CS_LAYOUT; return mask; } static int ConfigProcWindow(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; ElementWindow *masterX = (ElementWindow *) elem->master; ElementWindow savedX; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; savedX.tkwin = elemX->tkwin; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } if (args->config.flagSelf & EWIN_CONF_WINDOW) { if ((elem->master == NULL) && (elemX->tkwin != NULL)){ FormatResult(tree->interp, "can't specify -window for a master element"); continue; } } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } if (savedX.tkwin != elemX->tkwin) { if (savedX.tkwin != NULL) { #ifdef CLIP_WINDOW if (elemX->child != NULL) { Tk_DeleteEventHandler(elemX->child, StructureNotifyMask, (Tk_EventProc*)WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->child, (Tk_GeomMgr *) NULL, (ClientData) NULL); Tk_UnmapWindow(elemX->child); elemX->child = NULL; } #endif Tk_DeleteEventHandler(savedX.tkwin, StructureNotifyMask, (Tk_EventProc*)WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(savedX.tkwin, (Tk_GeomMgr *) NULL, (ClientData) NULL); Tk_UnmaintainGeometry(savedX.tkwin, tree->tkwin); Tk_UnmapWindow(savedX.tkwin); } if (elemX->tkwin != NULL) { Tk_Window ancestor, parent; /* * Make sure that the treectrl is either the parent of the * window associated with the element or a descendant of that * parent. Also, don't allow a top-of-hierarchy window to be * managed inside a treectrl. */ parent = Tk_Parent(elemX->tkwin); for (ancestor = tree->tkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { break; } if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_HIERARCHY) { badWindow: FormatResult(tree->interp, "can't use %s in a window element of %s", Tk_PathName(elemX->tkwin), Tk_PathName(tree->tkwin)); elemX->tkwin = NULL; return TCL_ERROR; } } if (((Tk_FakeWin *) (elemX->tkwin))->flags & TK_TOP_HIERARCHY) { goto badWindow; } if (elemX->tkwin == tree->tkwin) { goto badWindow; } #ifdef CLIP_WINDOW if ((elemX->clip == 1) || ((masterX != NULL) && (masterX->clip == 1))) { elemX->child = (Tk_Window) ((TkWindow *) elemX->tkwin)->childList; if (elemX->child != NULL) { Tk_CreateEventHandler(elemX->child, StructureNotifyMask, (Tk_EventProc*)WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->child, &winElemGeomType, (ClientData) elemX); } } #endif Tk_CreateEventHandler(elemX->tkwin, StructureNotifyMask, (Tk_EventProc*)WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->tkwin, &winElemGeomType, (ClientData) elemX); } } #if 0 if ((elemX->tkwin != NULL) && (itemPtr->state == TK_STATE_HIDDEN)) { if (tree->tkwin == Tk_Parent(elemX->tkwin)) { Tk_UnmapWindow(elemX->tkwin); } else { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } } #endif return TCL_OK; } static int CreateProcWindow(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; elemX->tree = tree; elemX->item = args->create.item; elemX->column = args->create.column; elemX->destroy = -1; #ifdef CLIP_WINDOW elemX->clip = -1; #endif return TCL_OK; } static void DisplayProcWindow(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; ElementWindow *masterX = (ElementWindow *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int minX, maxX, minY, maxY; int width, height; int match, match2; int draw; int requests; BOOLEAN_FOR_STATE(draw, draw, state); if (!draw) goto hideIt; if (elemX->tkwin == NULL) return; #ifdef CLIP_WINDOW if (elemX->child != NULL) { width = Tk_ReqWidth(elemX->child); height = Tk_ReqHeight(elemX->child); } else { width = Tk_ReqWidth(elemX->tkwin); height = Tk_ReqHeight(elemX->tkwin); } if (width < 1 || height < 1) goto hideIt; #else width = Tk_ReqWidth(elemX->tkwin); height = Tk_ReqHeight(elemX->tkwin); #endif AdjustForSticky(args->display.sticky, args->display.width, args->display.height, TRUE, TRUE, &x, &y, &width, &height); x += tree->drawableXOrigin - tree->xOrigin; y += tree->drawableYOrigin - tree->yOrigin; /* -squeeze layout may give the element less space than requested. */ if (width > args->display.width) width = args->display.width; if (height > args->display.height) height = args->display.height; minX = args->display.bounds[0]; minY = args->display.bounds[1]; maxX = args->display.bounds[2]; maxY = args->display.bounds[3]; /* * If the window is completely out of the visible area of the treectrl * then unmap it. The window could suddenly reappear if the treectrl * window gets resized. */ if (((x + width) <= minX) || ((y + height) <= minY) || (x >= maxX) || (y >= maxY)) { hideIt: if (tree->tkwin == Tk_Parent(elemX->tkwin)) { Tk_UnmapWindow(elemX->tkwin); } else { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } return; } TreeDisplay_GetReadyForTrouble(tree, &requests); #ifdef CLIP_WINDOW if (elemX->child != NULL) { int cx = x, cy = y, cw = width, ch = height; /* clip win coords */ if (cx < minX) { cw -= minX - cx; cx = minX; } if (cy < minY) { ch -= minY - cy; cy = minY; } if (cx + cw > maxX) cw = maxX - cx; if (cy + ch > maxY) ch = maxY - cy; /* * Reposition and map the window (but in different ways depending * on whether the treectrl is the window's parent). */ if (tree->tkwin == Tk_Parent(elemX->tkwin)) { if ((cx != Tk_X(elemX->tkwin)) || (cy != Tk_Y(elemX->tkwin)) || (cw != Tk_Width(elemX->tkwin)) || (ch != Tk_Height(elemX->tkwin))) { Tk_MoveResizeWindow(elemX->tkwin, cx, cy, cw, ch); if (TreeDisplay_WasThereTrouble(tree, requests)) return; } Tk_MapWindow(elemX->tkwin); } else { Tk_MaintainGeometry(elemX->tkwin, tree->tkwin, cx, cy, cw, ch); } if (TreeDisplay_WasThereTrouble(tree, requests)) return; /* * Position the child window within the clip window. */ x -= cx; y -= cy; if ((x != Tk_X(elemX->child)) || (y != Tk_Y(elemX->child)) || (width != Tk_Width(elemX->child)) || (height != Tk_Height(elemX->child))) { Tk_MoveResizeWindow(elemX->child, x, y, width, height); if (TreeDisplay_WasThereTrouble(tree, requests)) return; } Tk_MapWindow(elemX->child); return; } #endif /* CLIP_WINDOW */ /* * Reposition and map the window (but in different ways depending * on whether the treectrl is the window's parent). */ if (tree->tkwin == Tk_Parent(elemX->tkwin)) { if ((x != Tk_X(elemX->tkwin)) || (y != Tk_Y(elemX->tkwin)) || (width != Tk_Width(elemX->tkwin)) || (height != Tk_Height(elemX->tkwin))) { Tk_MoveResizeWindow(elemX->tkwin, x, y, width, height); if (TreeDisplay_WasThereTrouble(tree, requests)) return; } Tk_MapWindow(elemX->tkwin); } else { Tk_MaintainGeometry(elemX->tkwin, tree->tkwin, x, y, width, height); } } static void NeededProcWindow(ElementArgs *args) { /* TreeCtrl *tree = args->tree;*/ Element *elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; /* ElementWindow *masterX = (ElementWindow *) elem->master; int state = args->state;*/ int width = 0, height = 0; #ifdef CLIP_WINDOW if (elemX->child != NULL) { width = Tk_ReqWidth(elemX->child); if (width <= 0) { width = 1; } height = Tk_ReqHeight(elemX->child); if (height <= 0) { height = 1; } } else #endif if (elemX->tkwin) { width = Tk_ReqWidth(elemX->tkwin); if (width <= 0) { width = 1; } height = Tk_ReqHeight(elemX->tkwin); if (height <= 0) { height = 1; } } args->needed.width = width; args->needed.height = height; } static int StateProcWindow(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; ElementBitmap *masterX = (ElementBitmap *) elem->master; int match, match2; int draw1, draw2; int mask = 0; BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) if (draw1 == -1) draw1 = 1; BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if (draw2 == -1) draw2 = 1; if (draw1 != draw2) mask |= CS_DISPLAY; return mask; } static int UndefProcWindow(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; return PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); } static int ActualProcWindow(ElementArgs *args) { TreeCtrl *tree = args->tree; ElementWindow *elemX = (ElementWindow *) args->elem; ElementWindow *masterX = (ElementWindow *) args->elem->master; static CONST84 char *optionName[] = { "-draw", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } static void OnScreenProcWindow(ElementArgs *args) { TreeCtrl *tree = args->tree; Element *elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; if (!args->screen.visible && (elemX->tkwin != NULL)) { if (tree->tkwin == Tk_Parent(elemX->tkwin)) { Tk_UnmapWindow(elemX->tkwin); } else { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } } } ElementType elemTypeWindow = { "window", sizeof(ElementWindow), windowOptionSpecs, NULL, CreateProcWindow, DeleteProcWindow, ConfigProcWindow, DisplayProcWindow, NeededProcWindow, NULL, /* heightProc */ WorldChangedProcWindow, StateProcWindow, UndefProcWindow, ActualProcWindow, OnScreenProcWindow }; /*****/ typedef struct ElementAssocData ElementAssocData; struct ElementAssocData { ElementType *typeList; }; int TreeElement_TypeFromObj(TreeCtrl *tree, Tcl_Obj *objPtr, ElementType **typePtrPtr) { Tcl_Interp *interp = tree->interp; ElementAssocData *assocData; char *typeStr; int length; ElementType *typeList; ElementType *typePtr, *matchPtr = NULL; assocData = Tcl_GetAssocData(interp, "TreeCtrlElementTypes", NULL); typeList = assocData->typeList; typeStr = Tcl_GetStringFromObj(objPtr, &length); if (!length) { FormatResult(interp, "invalid element type \"\""); return TCL_ERROR; } for (typePtr = typeList; typePtr != NULL; typePtr = typePtr->next) { if ((typeStr[0] == typePtr->name[0]) && !strncmp(typeStr, typePtr->name, length)) { if (matchPtr != NULL) { FormatResult(interp, "ambiguous element type \"%s\"", typeStr); return TCL_ERROR; } matchPtr = typePtr; } } if (matchPtr == NULL) { FormatResult(interp, "unknown element type \"%s\"", typeStr); return TCL_ERROR; } *typePtrPtr = matchPtr; return TCL_OK; } int TreeCtrl_RegisterElementType(Tcl_Interp *interp, ElementType *newTypePtr) { ElementAssocData *assocData; ElementType *typeList; ElementType *prevPtr, *typePtr, *nextPtr; assocData = Tcl_GetAssocData(interp, "TreeCtrlElementTypes", NULL); typeList = assocData->typeList; for (typePtr = typeList, prevPtr = NULL; typePtr != NULL; prevPtr = typePtr, typePtr = nextPtr) { nextPtr = typePtr->next; /* Remove duplicate type */ if (!strcmp(typePtr->name, newTypePtr->name)) { if (prevPtr == NULL) typeList = typePtr->next; else prevPtr->next = typePtr->next; ckfree((char *) typePtr); } } typePtr = (ElementType *) ckalloc(sizeof(ElementType)); memcpy(typePtr, newTypePtr, sizeof(ElementType)); typePtr->next = typeList; typeList = typePtr; typePtr->optionTable = Tk_CreateOptionTable(interp, newTypePtr->optionSpecs); assocData->typeList = typeList; return TCL_OK; } TreeCtrlStubs stubs = { TreeCtrl_RegisterElementType, Tree_RedrawElement, Tree_ElementIterateBegin, Tree_ElementIterateNext, Tree_ElementIterateGet, Tree_ElementIterateChanged, PerStateInfo_Free, PerStateInfo_FromObj, PerStateInfo_ForState, PerStateInfo_ObjForState, PerStateInfo_Undefine, &pstBoolean, PerStateBoolean_ForState, PSTSave, PSTRestore, TreeStateFromObj, BooleanCO_Init, StringTableCO_Init }; static void FreeAssocData(ClientData clientData, Tcl_Interp *interp) { ElementAssocData *assocData = (ElementAssocData *) clientData; ElementType *typeList = assocData->typeList; ElementType *next; while (typeList != NULL) { next = typeList->next; /* The ElementType.optionTables are freed when the interp is deleted */ ckfree((char *) typeList); typeList = next; } ckfree((char *) assocData); } int TreeElement_Init(Tcl_Interp *interp) { ElementAssocData *assocData; /* FIXME: memory leak with dynamically-allocated ClientData. */ PerStateCO_Init(elemTypeBitmap.optionSpecs, "-background", &pstColor, TreeStateFromObj); PerStateCO_Init(elemTypeBitmap.optionSpecs, "-bitmap", &pstBitmap, TreeStateFromObj); PerStateCO_Init(elemTypeBitmap.optionSpecs, "-draw", &pstBoolean, TreeStateFromObj); PerStateCO_Init(elemTypeBitmap.optionSpecs, "-foreground", &pstColor, TreeStateFromObj); PerStateCO_Init(elemTypeBorder.optionSpecs, "-draw", &pstBoolean, TreeStateFromObj); PerStateCO_Init(elemTypeBorder.optionSpecs, "-background", &pstBorder, TreeStateFromObj); PerStateCO_Init(elemTypeBorder.optionSpecs, "-relief", &pstRelief, TreeStateFromObj); PerStateCO_Init(elemTypeImage.optionSpecs, "-draw", &pstBoolean, TreeStateFromObj); PerStateCO_Init(elemTypeImage.optionSpecs, "-image", &pstImage, TreeStateFromObj); PerStateCO_Init(elemTypeRect.optionSpecs, "-draw", &pstBoolean, TreeStateFromObj); PerStateCO_Init(elemTypeRect.optionSpecs, "-fill", &pstColor, TreeStateFromObj); PerStateCO_Init(elemTypeRect.optionSpecs, "-outline", &pstColor, TreeStateFromObj); /* 3 options in the same structure. */ DynamicCO_Init(elemTypeText.optionSpecs, "-data", 1006, sizeof(ElementTextData), Tk_Offset(ElementTextData, dataObj), -1, &stringCO, ElementTextDataInit); DynamicCO_Init(elemTypeText.optionSpecs, "-datatype", 1006, sizeof(ElementTextData), -1, Tk_Offset(ElementTextData, dataType), StringTableCO_Alloc("-datatype", (CONST char **)textDataTypeST), ElementTextDataInit); DynamicCO_Init(elemTypeText.optionSpecs, "-format", 1006, sizeof(ElementTextData), Tk_Offset(ElementTextData, formatObj), -1, &stringCO, ElementTextDataInit); /* 4 options in the same structure. */ DynamicCO_Init(elemTypeText.optionSpecs, "-justify", 1005, sizeof(ElementTextLayout), -1, Tk_Offset(ElementTextLayout, justify), StringTableCO_Alloc("-justify", (CONST char **)textJustifyST), ElementTextLayoutInit); DynamicCO_Init(elemTypeText.optionSpecs, "-lines", 1005, sizeof(ElementTextLayout), -1, Tk_Offset(ElementTextLayout, lines), IntegerCO_Alloc("-lines", 0, /* min */ 0, /* max (ignored) */ -1, /* empty */ 0x01), /* flags: min */ ElementTextLayoutInit); DynamicCO_Init(elemTypeText.optionSpecs, "-width", 1005, sizeof(ElementTextLayout), Tk_Offset(ElementTextLayout, widthObj), Tk_Offset(ElementTextLayout, width), &pixelsCO, ElementTextLayoutInit); DynamicCO_Init(elemTypeText.optionSpecs, "-wrap", 1005, sizeof(ElementTextLayout), -1, Tk_Offset(ElementTextLayout, wrap), StringTableCO_Alloc("-wrap", (CONST char **)textWrapST), ElementTextLayoutInit); DynamicCO_Init(elemTypeText.optionSpecs, "-draw", 1002, sizeof(PerStateInfo), Tk_Offset(struct PerStateInfo, obj), 0, PerStateCO_Alloc("-draw", &pstBoolean, TreeStateFromObj), (DynamicOptionInitProc *) NULL); DynamicCO_Init(elemTypeText.optionSpecs, "-fill", 1003, sizeof(PerStateInfo), Tk_Offset(struct PerStateInfo, obj), 0, PerStateCO_Alloc("-fill", &pstColor, TreeStateFromObj), (DynamicOptionInitProc *) NULL); DynamicCO_Init(elemTypeText.optionSpecs, "-font", 1004, sizeof(PerStateInfo), Tk_Offset(struct PerStateInfo, obj), 0, PerStateCO_Alloc("-font", &pstFont, TreeStateFromObj), (DynamicOptionInitProc *) NULL); DynamicCO_Init(elemTypeText.optionSpecs, "-textvariable", 1001, sizeof(ElementTextVar), Tk_Offset(struct ElementTextVar, varNameObj), -1, &stringCO, (DynamicOptionInitProc *) NULL); #ifdef TEXT_STYLE DynamicCO_Init(elemTypeText.optionSpecs, "-underline", 1008, sizeof(ElementTextStyle), -1, Tk_Offset(ElementTextStyle, underline), IntegerCO_Alloc("-underline", 0, /* min (ignored) */ 0, /* max (ignored) */ TEXT_UNDERLINE_EMPTYVAL, /* empty */ 0x00), /* flags */ ElementTextStyleInit); #endif PerStateCO_Init(elemTypeWindow.optionSpecs, "-draw", &pstBoolean, TreeStateFromObj); assocData = (ElementAssocData *) ckalloc(sizeof(ElementAssocData)); assocData->typeList = NULL; Tcl_SetAssocData(interp, "TreeCtrlElementTypes", FreeAssocData, assocData); TreeCtrl_RegisterElementType(interp, &elemTypeBitmap); TreeCtrl_RegisterElementType(interp, &elemTypeBorder); /* TreeCtrl_RegisterElementType(interp, &elemTypeCheckButton);*/ TreeCtrl_RegisterElementType(interp, &elemTypeImage); TreeCtrl_RegisterElementType(interp, &elemTypeRect); TreeCtrl_RegisterElementType(interp, &elemTypeText); TreeCtrl_RegisterElementType(interp, &elemTypeWindow); Tcl_SetAssocData(interp, "TreeCtrlStubs", NULL, &stubs); return TCL_OK; } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeItem.c0000644000175000017500000066757110674273023024746 0ustar domibeldomibel/* * tkTreeItem.c -- * * This module implements items for treectrl widgets. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: tkTreeItem.c,v 1.2 2007-09-19 19:18:43 barre Exp $ */ #include "tkTreeCtrl.h" typedef struct TreeItem_ TreeItem_; typedef struct Column Column; /* * A data structure of the following type is kept for a single column in a * single item. */ struct Column { int cstate; /* STATE_xxx flags manipulated with the * [item state forcolumn] command */ int span; /* Number of tree-columns this column covers */ TreeStyle style; /* Instance style. */ Column *next; /* Column to the right of this one */ }; /* * A data structure of the following type is kept for each item. */ struct TreeItem_ { int id; /* unique id */ int depth; /* tree depth (-1 for the unique root item) */ int fixedHeight; /* -height: desired height of this item (0 for * no-such-value) */ int numChildren; int index; /* "row" in flattened tree */ int indexVis; /* visible "row" in flattened tree, -1 if hidden */ int state; /* STATE_xxx flags */ TreeItem parent; TreeItem firstChild; TreeItem lastChild; TreeItem prevSibling; TreeItem nextSibling; TreeItemDInfo dInfo; /* display info, or NULL */ TreeItemRInfo rInfo; /* range info, or NULL */ Column *columns; int *spans; /* 1 per tree-column. spans[N] is the column index of * the item-column displayed in column N. If this * item's columns all have a span of 1, this field * is NULL (unless it was previously allocated * because some spans were > 1). */ int spanAlloc; /* Size of spans[]. */ #define ITEM_FLAG_DELETED 0x0001 /* Item is being deleted */ #define ITEM_FLAG_SPANS_SIMPLE 0x0002 /* All spans are 1 */ #define ITEM_FLAG_SPANS_VALID 0x0004 /* Some spans are > 1, but we don't * need to redo them. Also indicates * we have an entry in * TreeCtrl.itemSpansHash. */ #define ITEM_FLAG_BUTTON 0x0008 /* -button */ #define ITEM_FLAG_VISIBLE 0x0010 /* -visible */ int flags; TagInfo *tagInfo; /* Tags. May be NULL. */ }; static CONST84 char *ItemUid = "Item", *ItemColumnUid = "ItemColumn"; /* * Macro to test whether an item is the unique root item */ #define IS_ROOT(i) ((i)->depth == -1) #define IS_ALL(i) ((i) == ITEM_ALL) #define IS_DELETED(i) (((i)->flags & ITEM_FLAG_DELETED) != 0) #define HAS_BUTTON(i) (((i)->flags & ITEM_FLAG_BUTTON) != 0) #define IS_VISIBLE(i) (((i)->flags & ITEM_FLAG_VISIBLE) != 0) /* * Flags returned by Tk_SetOptions() (see itemOptionSpecs below). */ #define ITEM_CONF_BUTTON 0x0001 #define ITEM_CONF_SIZE 0x0002 #define ITEM_CONF_VISIBLE 0x0004 /* * Information used for Item objv parsing. */ static Tk_OptionSpec itemOptionSpecs[] = { {TK_OPTION_CUSTOM, "-button", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeItem_, flags), 0, (ClientData) NULL, ITEM_CONF_BUTTON}, {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeItem_, fixedHeight), TK_OPTION_NULL_OK, (ClientData) NULL, ITEM_CONF_SIZE}, {TK_OPTION_CUSTOM, "-tags", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeItem_, tagInfo), TK_OPTION_NULL_OK, (ClientData) &TagInfoCO, 0}, {TK_OPTION_CUSTOM, "-visible", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeItem_, flags), 0, (ClientData) NULL, ITEM_CONF_VISIBLE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; /* *---------------------------------------------------------------------- * * Column_Alloc -- * * Allocate and initialize a new Column record. * * Results: * Pointer to allocated Column. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static Column * Column_Alloc( TreeCtrl *tree /* Widget info. */ ) { #ifdef ALLOC_HAX Column *column = (Column *) AllocHax_Alloc(tree->allocData, ItemColumnUid, sizeof(Column)); #else Column *column = (Column *) ckalloc(sizeof(Column)); #endif memset(column, '\0', sizeof(Column)); column->span = 1; return column; } /* *---------------------------------------------------------------------- * * TreeItemColumn_InvalidateSize -- * * Marks the needed height and width of the column as out-of-date. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItemColumn_InvalidateSize( TreeCtrl *tree, /* Widget info. */ TreeItemColumn column_ /* Column token. */ ) { } /* *---------------------------------------------------------------------- * * TreeItemColumn_NeededWidth -- * * Returns the requested width of a Column. * * Results: * If the Column has a style, the requested width of the style * is returned (a positive pixel value). Otherwise 0 is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItemColumn_NeededWidth( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemColumn column_ /* Column token. */ ) { Column *self = (Column *) column_; if (self->style != NULL) return TreeStyle_NeededWidth(tree, self->style, item->state | self->cstate); return 0; } #ifdef EXPENSIVE_SPAN_WIDTH /* NOT USED */ /* * When a style spans 2 or more columns, all of the requested width goes * to the first column in the span. Ideally the width needed by the style * would be distributed over each column in the span. To be done properly, * the visibility and fixed-width of each column needs to be considered. * * This routine does an okay job of calculating the requested width of a * column in an item when spans are involved; however there is a lot of * processing involved, and this routine is called for each column in * a span separately (it would be better to calculate the width of all * the columns in a span at the same time). */ int TreeItem_NeededWidthOfColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int _columnIndex /* Column index. */ ) { TreeColumn treeColumn = tree->columns; Column *column = item->columns; int columnIndex = 0, itemColumnIndex = 0, span = 1; int selfIndex = _columnIndex, fixedWidth = 0, width = 0; int spanStart, spanEnd; struct span { Column *itemColumn; int itemColumnIndex; int fixedWidth; int spanWidth; int visible; } staticSpans[STATIC_SIZE], *spans = staticSpans; STATIC_ALLOC(spans, struct span, tree->columnCount); while (treeColumn != NULL) { spans[columnIndex].visible = TreeColumn_Visible(treeColumn); if (--span == 0) { if (spans[columnIndex].visible) span = column ? column->span : 1; else span = 1; itemColumnIndex = columnIndex; } spans[columnIndex].itemColumn = column; spans[columnIndex].itemColumnIndex = itemColumnIndex; spans[columnIndex].spanWidth = 0; spans[columnIndex].fixedWidth = TreeColumn_FixedWidth(treeColumn); ++columnIndex; treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } span = 0; columnIndex = spanStart = spanEnd = spans[selfIndex].itemColumnIndex; while (spans[columnIndex].itemColumnIndex == spanStart) { if (spans[columnIndex].visible) { if (spans[columnIndex].fixedWidth >= 0) { fixedWidth += spans[columnIndex].fixedWidth; spans[columnIndex].spanWidth = spans[columnIndex].fixedWidth; } else ++span; /* number of visible columns in the span with no * fixed width */ } spanEnd = columnIndex; ++columnIndex; if (columnIndex == tree->columnCount) break; } column = spans[spanStart].itemColumn; if (column != NULL && column->style != NULL) { width = TreeStyle_NeededWidth(tree, column->style, item->state | column->cstate); if (width > fixedWidth && span > 0) { width -= fixedWidth; while (width > 0) { int each = (width > span) ? width / span : 1; columnIndex = spanStart; while (columnIndex <= spanEnd) { if (spans[columnIndex].visible) { if (spans[columnIndex].fixedWidth < 0) { spans[columnIndex].spanWidth += each; width -= each; if (width <= 0) break; } } ++columnIndex; } } }; } if (0) { int i; for (i = 0; i < tree->columnCount; i++) { dbwin("%d,%d: itemColumn %p itemColumnIndex %d fixedWidth %d spanWidth %d\n", item->id, i, spans[i].itemColumn, spans[i].itemColumnIndex, spans[i].fixedWidth, spans[i].spanWidth); } } width = spans[selfIndex].spanWidth; STATIC_FREE(spans, struct span, tree->columnCount); return width; } #endif /* EXPENSIVE_SPAN_WIDTH */ /* *---------------------------------------------------------------------- * * TreeItemColumn_GetStyle -- * * Returns the style assigned to a Column. * * Results: * Returns the style, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeStyle TreeItemColumn_GetStyle( TreeCtrl *tree, /* Widget info. */ TreeItemColumn column /* Column token. */ ) { return ((Column *) column)->style; } /* *---------------------------------------------------------------------- * * TreeItemColumn_Index -- * * Return the 0-based index of a Column in an Item's linked list of * Columns. * * Results: * Integer index of the Column. * * Side effects: * Tcl_Panic() if the Column isn't found. * *---------------------------------------------------------------------- */ int TreeItemColumn_Index( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemColumn column_ /* Column token. */ ) { Column *column; int i = 0; column = item->columns; while ((column != NULL) && (column != (Column *) column_)) { i++; column = column->next; } if (column == NULL) panic("TreeItemColumn_Index: couldn't find the column\n"); return i; } /* *---------------------------------------------------------------------- * * TreeItemColumn_ForgetStyle -- * * Free the style assigned to a Column. * * Results: * Column has no style assigned anymore. * * Side effects: * Memory is freed. * *---------------------------------------------------------------------- */ void TreeItemColumn_ForgetStyle( TreeCtrl *tree, /* Widget info. */ TreeItemColumn column_ /* Column token. */ ) { Column *self = (Column *) column_; if (self->style != NULL) { TreeStyle_FreeResources(tree, self->style); self->style = NULL; } } /* *---------------------------------------------------------------------- * * TreeItemColumn_GetNext -- * * Return the Column to the right of this one. * * Results: * The next Column in the linked list, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemColumn TreeItemColumn_GetNext( TreeCtrl *tree, /* Widget info. */ TreeItemColumn column /* Column token. */ ) { return (TreeItemColumn) ((Column *) column)->next; } /* *---------------------------------------------------------------------- * * Column_FreeResources -- * * Free the style and memory associated with the given Column. * * Results: * The next Column in the linked list, or NULL. * * Side effects: * Memory is freed. * *---------------------------------------------------------------------- */ Column * Column_FreeResources( TreeCtrl *tree, /* Widget info. */ Column *self /* Column to free. */ ) { Column *next = self->next; if (self->style != NULL) TreeStyle_FreeResources(tree, self->style); #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, ItemColumnUid, (char *) self, sizeof(Column)); #else WFREE(self, Column); #endif return next; } /* *---------------------------------------------------------------------- * * Item_UpdateIndex -- * * Set the Item.depth, Item.index and Item.indexVis fields of the * given Item and all its descendants. * * Results: * None. * * Side effects: * The TreeCtrl.depth field may be updated to track the maximum * depth of all items. * *---------------------------------------------------------------------- */ static void Item_UpdateIndex(TreeCtrl *tree, TreeItem item, /* Item to update. */ int *index, /* New Item.index value for the item. * Value is incremented. */ int *indexVis /* New Item.indexVis value for the item if * the item is ReallyVisible(). * Value is incremented if the item is * ReallyVisible(). */ ) { TreeItem child; int parentVis, parentOpen; /* Also track max depth */ if (item->parent != NULL) item->depth = item->parent->depth + 1; else item->depth = 0; if (item->depth > tree->depth) tree->depth = item->depth; item->index = (*index)++; item->indexVis = -1; if (item->parent != NULL) { parentOpen = (item->parent->state & STATE_OPEN) != 0; parentVis = item->parent->indexVis != -1; if (IS_ROOT(item->parent) && !tree->showRoot) { parentOpen = TRUE; parentVis = IS_VISIBLE(item->parent); } if (parentVis && parentOpen && IS_VISIBLE(item)) item->indexVis = (*indexVis)++; } child = item->firstChild; while (child != NULL) { Item_UpdateIndex(tree, child, index, indexVis); child = child->nextSibling; } } /* *---------------------------------------------------------------------- * * Tree_UpdateItemIndex -- * * Set the Item.depth, Item.index and Item.indexVis fields of the * every Item. Set TreeCtrl.depth to the maximum depth of all * Items. Set TreeCtrl.itemVisCount to the count of all visible * items. * * Because this is slow we try not to do it until necessary. * The tree->updateIndex flags indicates when this is needed. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_UpdateItemIndex( TreeCtrl *tree /* Widget info. */ ) { TreeItem item = tree->root; int index = 1, indexVis = 0; if (!tree->updateIndex) return; if (tree->debug.enable && tree->debug.data) dbwin("Tree_UpdateItemIndex %s\n", Tk_PathName(tree->tkwin)); /* Also track max depth */ tree->depth = -1; item->index = 0; item->indexVis = -1; if (tree->showRoot && IS_VISIBLE(item)) item->indexVis = indexVis++; item = item->firstChild; while (item != NULL) { Item_UpdateIndex(tree, item, &index, &indexVis); item = item->nextSibling; } tree->itemVisCount = indexVis; tree->updateIndex = 0; } /* *---------------------------------------------------------------------- * * Item_Alloc -- * * Allocate an initialize a new Item record. * * Results: * Pointer to the allocated Item record. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static TreeItem Item_Alloc( TreeCtrl *tree /* Widget info. */ ) { #ifdef ALLOC_HAX TreeItem item = (TreeItem) AllocHax_Alloc(tree->allocData, ItemUid, sizeof(TreeItem_)); #else TreeItem item = (TreeItem) ckalloc(sizeof(TreeItem_)); #endif memset(item, '\0', sizeof(TreeItem_)); if (Tk_InitOptions(tree->interp, (char *) item, tree->itemOptionTable, tree->tkwin) != TCL_OK) panic("Tk_InitOptions() failed in Item_Alloc()"); item->state = STATE_OPEN | STATE_ENABLED; if (tree->gotFocus) item->state |= STATE_FOCUS; item->indexVis = -1; /* In the typical case all spans are 1. */ item->flags |= ITEM_FLAG_SPANS_SIMPLE; Tree_AddItem(tree, item); return item; } /* *---------------------------------------------------------------------- * * Item_AllocRoot -- * * Allocate an initialize a new Item record for the root item. * * Results: * Pointer to the allocated Item record. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static TreeItem Item_AllocRoot( TreeCtrl *tree /* Widget info. */ ) { TreeItem item; item = Item_Alloc(tree); item->depth = -1; item->state |= STATE_ACTIVE; return item; } /* *---------------------------------------------------------------------- * * TreeItem_GetFirstColumn -- * * Return the first Column record for an Item. * * Results: * Token for the column, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemColumn TreeItem_GetFirstColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return (TreeItemColumn) item->columns; } /* *---------------------------------------------------------------------- * * TreeItem_GetState -- * * Return the state flags for an Item. * * Results: * Bit mask of STATE_xxx flags. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetState( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->state; } /* *---------------------------------------------------------------------- * * Column_ChangeState -- * * Toggles zero or more STATE_xxx flags for a Column. If the * Column has a style assigned, its state may be changed. * * Results: * Bit mask of CS_LAYOUT and CS_DISPLAY flags, or zero if no * changes occurred. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static int Column_ChangeState( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the column. */ Column *column, /* Column to modify the state of. */ TreeColumn treeColumn, /* Tree column. */ int stateOff, /* STATE_xxx flags to turn off. */ int stateOn /* STATE_xxx flags to turn on. */ ) { int cstate, state; int sMask, iMask = 0; cstate = column->cstate; cstate &= ~stateOff; cstate |= stateOn; if (cstate == column->cstate) return 0; state = item->state | column->cstate; state &= ~stateOff; state |= stateOn; if (column->style != NULL) { sMask = TreeStyle_ChangeState(tree, column->style, item->state | column->cstate, state); if (sMask) { if (sMask & CS_LAYOUT) Tree_InvalidateColumnWidth(tree, treeColumn); iMask |= sMask; } if (iMask & CS_LAYOUT) { TreeItem_InvalidateHeight(tree, item); TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } else if (iMask & CS_DISPLAY) { Tree_InvalidateItemDInfo(tree, treeColumn, item, NULL); } } column->cstate = cstate; return iMask; } /* *---------------------------------------------------------------------- * * TreeItem_ChangeState -- * * Toggles zero or more STATE_xxx flags for an Item. If the * Column has a style assigned, its state may be changed. * * Results: * Bit mask of CS_LAYOUT and CS_DISPLAY flags, or zero if no * changes occurred. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ int TreeItem_ChangeState( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int stateOff, /* STATE_xxx flags to turn off. */ int stateOn /* STATE_xxx flags to turn on. */ ) { Column *column; TreeColumn treeColumn; int columnIndex = 0, state, cstate; int sMask, iMask = 0; state = item->state; state &= ~stateOff; state |= stateOn; if (state == item->state) return 0; treeColumn = tree->columns; column = item->columns; while (column != NULL) { if (column->style != NULL) { cstate = item->state | column->cstate; cstate &= ~stateOff; cstate |= stateOn; sMask = TreeStyle_ChangeState(tree, column->style, item->state | column->cstate, cstate); if (sMask) { if (sMask & CS_LAYOUT) { Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); } else if (sMask & CS_DISPLAY) { Tree_InvalidateItemDInfo(tree, treeColumn, item, NULL); } iMask |= sMask; } } columnIndex++; column = column->next; treeColumn = TreeColumn_Next(treeColumn); } /* This item has a button */ if (HAS_BUTTON(item) && tree->showButtons && (!IS_ROOT(item) || tree->showRootButton)) { Tk_Image image1, image2; Pixmap bitmap1, bitmap2; int butOpen, butClosed; int themeOpen, themeClosed; int w1, h1, w2, h2; void *ptr1 = NULL, *ptr2 = NULL; /* * Compare the image/bitmap/theme/xlib button for the old state * to the image/bitmap/theme/xlib button for the new state. Figure * out if the size or appearance has changed. */ /* image > bitmap > theme > draw */ image1 = PerStateImage_ForState(tree, &tree->buttonImage, item->state, NULL); if (image1 != NULL) { Tk_SizeOfImage(image1, &w1, &h1); ptr1 = image1; } if (ptr1 == NULL) { bitmap1 = PerStateBitmap_ForState(tree, &tree->buttonBitmap, item->state, NULL); if (bitmap1 != None) { Tk_SizeOfBitmap(tree->display, bitmap1, &w1, &h1); ptr1 = (void *) bitmap1; } } if (ptr1 == NULL) { if (tree->useTheme && TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), (item->state & STATE_OPEN) != 0, &w1, &h1) == TCL_OK) { ptr1 = (item->state & STATE_OPEN) ? &themeOpen : &themeClosed; } } if (ptr1 == NULL) { w1 = h1 = tree->buttonSize; ptr1 = (item->state & STATE_OPEN) ? &butOpen : &butClosed; } /* image > bitmap > theme > draw */ image2 = PerStateImage_ForState(tree, &tree->buttonImage, state, NULL); if (image2 != NULL) { Tk_SizeOfImage(image2, &w2, &h2); ptr2 = image2; } if (ptr2 == NULL) { bitmap2 = PerStateBitmap_ForState(tree, &tree->buttonBitmap, state, NULL); if (bitmap2 != None) { Tk_SizeOfBitmap(tree->display, bitmap2, &w2, &h2); ptr2 = (void *) bitmap2; } } if (ptr2 == NULL) { if (tree->useTheme && TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), (state & STATE_OPEN) != 0, &w2, &h2) == TCL_OK) { ptr2 = (state & STATE_OPEN) ? &themeOpen : &themeClosed; } } if (ptr2 == NULL) { w2 = h2 = tree->buttonSize; ptr2 = (state & STATE_OPEN) ? &butOpen : &butClosed; } if ((w1 != w2) || (h1 != h2)) { iMask |= CS_LAYOUT | CS_DISPLAY; } else if (ptr1 != ptr2) { iMask |= CS_DISPLAY; if (tree->columnTree != NULL) Tree_InvalidateItemDInfo(tree, tree->columnTree, item, NULL); } } if (iMask & CS_LAYOUT) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } item->state = state; return iMask; } /* *---------------------------------------------------------------------- * * TreeItem_UndefineState -- * * Clear a STATE_xxx flag in an Item and its Columns. This is * called when a user-defined state is undefined via the * [state undefine] widget command. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_UndefineState( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int state /* STATE_xxx flag that is undefined. */ ) { Column *column = item->columns; while (column != NULL) { column->cstate &= ~state; column = column->next; } item->state &= ~state; } /* *---------------------------------------------------------------------- * * TreeItem_GetButton -- * * Return the value of the -button configuration option for an * Item. * * Results: * Boolean indicating whether the Item could have a button * displayed next to it (-showbuttons must also be set). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetButton( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return HAS_BUTTON(item); } /* *---------------------------------------------------------------------- * * TreeItem_GetDepth -- * * Return the depth of an Item. * * Results: * Integer >= -1. (-1 for the root) * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetDepth( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { #if 0 Tree_UpdateItemIndex(tree); #endif return item->depth; } /* *---------------------------------------------------------------------- * * TreeItem_GetID -- * * Return the unique ID of an Item. * * Results: * Integer >= 0. (0 for the root) * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetID( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->id; } /* *---------------------------------------------------------------------- * * TreeItem_SetID -- * * Set the unique ID of an Item. This is called when the item * is created. * * Results: * The given ID. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_SetID( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int id /* Unique ID for the item. */ ) { return item->id = id; } /* *---------------------------------------------------------------------- * * TreeItem_GetEnabled -- * * Return whether an Item is enabled or not. * * Results: * TRUE if the item is enabled, FALSE otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetEnabled( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return (item->state & STATE_ENABLED) != 0; } /* *---------------------------------------------------------------------- * * TreeItem_GetSelected -- * * Return whether an Item is selected or not. * * Results: * TRUE if the item is part of the selection, FALSE otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetSelected( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return (item->state & STATE_SELECTED) != 0; } /* *---------------------------------------------------------------------- * * TreeItem_GetParent -- * * Return the parent of an Item. * * Results: * Token for parent Item, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_GetParent( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->parent; } /* *---------------------------------------------------------------------- * * TreeItem_GetNextSibling -- * * Return the next sibling of an Item. * * Results: * Token for next sibling Item, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_GetNextSibling( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->nextSibling; } /* *---------------------------------------------------------------------- * * TreeItem_NextSiblingVisible -- * * Find a following sibling that is ReallyVisible(). * * Results: * Token for a sibling Item, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_NextSiblingVisible( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { item = TreeItem_GetNextSibling(tree, item); while (item != NULL) { if (TreeItem_ReallyVisible(tree, item)) return item; item = TreeItem_GetNextSibling(tree, item); } return NULL; } /* *---------------------------------------------------------------------- * * TreeItem_SetDInfo -- * * Store a display-info token in an Item. Called by the display * code. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_SetDInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemDInfo dInfo /* Display-info token. */ ) { item->dInfo = dInfo; } /* *---------------------------------------------------------------------- * * TreeItem_GetDInfo -- * * Return the display-info token of an Item. Called by the display * code. * * Results: * The display-info token or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemDInfo TreeItem_GetDInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->dInfo; } /* *---------------------------------------------------------------------- * * TreeItem_SetRInfo -- * * Store a range-info token in an Item. Called by the display * code. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_SetRInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemRInfo rInfo /* Range-info token */ ) { item->rInfo = rInfo; } /* *---------------------------------------------------------------------- * * TreeItem_GetRInfo -- * * Return the range-info token of an Item. Called by the display * code. * * Results: * The range-info token or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemRInfo TreeItem_GetRInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->rInfo; } /* *---------------------------------------------------------------------- * * TreeItem_Next -- * * Return the Item after the given one. * * Results: * Result will be: * a) the first child, or * b) the next sibling, or * c) the next sibling of an ancestor, or * d) NULL if no item follows this one * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_Next( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { if (item->firstChild != NULL) return item->firstChild; if (item->nextSibling != NULL) return item->nextSibling; while (1) { item = item->parent; if (item == NULL) break; if (item->nextSibling != NULL) return item->nextSibling; } return NULL; } /* *---------------------------------------------------------------------- * * TreeItem_NextVisible -- * * Return the ReallyVisible() Item after the given one. * * Results: * Result will be: * a) the first ReallyVisible() child, or * b) the next ReallyVisible() sibling, or * c) the next ReallyVisible() sibling of an ancestor, or * d) NULL if no ReallyVisible() item follows this one * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_NextVisible( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { item = TreeItem_Next(tree, item); while (item != NULL) { if (TreeItem_ReallyVisible(tree, item)) return item; item = TreeItem_Next(tree, item); } return NULL; } /* *---------------------------------------------------------------------- * * TreeItem_Prev -- * * Return the Item before the given one. * * Results: * Result will be: * a) the last descendant of the previous sibling, or * b) the parent, or * c) NULL if the given Item is the root * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_Prev( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem walk; if (item->parent == NULL) /* root */ return NULL; walk = item->parent; if (item->prevSibling) { walk = item->prevSibling; while (walk->lastChild != NULL) walk = walk->lastChild; } return walk; } /* *---------------------------------------------------------------------- * * TreeItem_PrevVisible -- * * Return the ReallyVisible() Item before the given one. * * Results: * Result will be: * a) the last descendant of the previous sibling, or * b) the parent, or * c) NULL if the given Item is the root * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_PrevVisible( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { item = TreeItem_Prev(tree, item); while (item != NULL) { if (TreeItem_ReallyVisible(tree, item)) return item; item = TreeItem_Prev(tree, item); } return NULL; } /* *---------------------------------------------------------------------- * * TreeItem_ToIndex -- * * Return Item.index and Item.indexVis. * * Results: * The zero-based indexes of the Item. * * Side effects: * Will recalculate the indexes of every item if needed. * *---------------------------------------------------------------------- */ void TreeItem_ToIndex( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int *index, /* Returned Item.index, may be NULL */ int *indexVis /* Returned Item.indexVis, may be NULL */ ) { Tree_UpdateItemIndex(tree); if (index != NULL) (*index) = item->index; if (indexVis != NULL) (*indexVis) = item->indexVis; } typedef struct Qualifiers { TreeCtrl *tree; int visible; /* 1 if the item must be ReallyVisible(), 0 if the item must not be ReallyVisible(), -1 for unspecified. */ int states[3]; /* Item states that must be on or off. */ TagExpr expr; /* Tag expression. */ int exprOK; /* TRUE if expr is valid. */ int depth; /* >= 0 for depth, -1 for unspecified */ } Qualifiers; /* *---------------------------------------------------------------------- * * Qualifiers_Init -- * * Helper routine for TreeItem_FromObj. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Qualifiers_Init( TreeCtrl *tree, /* Widget info. */ Qualifiers *q /* Out: Initialized qualifiers. */ ) { q->tree = tree; q->visible = -1; q->states[0] = q->states[1] = q->states[2] = 0; q->exprOK = FALSE; q->depth = -1; } /* *---------------------------------------------------------------------- * * Qualifiers_Scan -- * * Helper routine for TreeItem_FromObj. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Qualifiers_Scan( Qualifiers *q, /* Must call Qualifiers_Init first, * and Qualifiers_Free if result is TCL_OK. */ int objc, /* Number of arguments. */ Tcl_Obj **objv, /* Argument values. */ int startIndex, /* First objv[] index to look at. */ int *argsUsed /* Out: number of objv[] used. */ ) { TreeCtrl *tree = q->tree; Tcl_Interp *interp = tree->interp; int qual, j = startIndex; static CONST84 char *qualifiers[] = { "depth", "state", "tag", "visible", "!visible", NULL }; enum qualEnum { QUAL_DEPTH, QUAL_STATE, QUAL_TAG, QUAL_VISIBLE, QUAL_NOT_VISIBLE }; /* Number of arguments used by qualifiers[]. */ static int qualArgs[] = { 2, 2, 2, 1, 1 }; *argsUsed = 0; for (; j < objc; ) { if (Tcl_GetIndexFromObj(NULL, objv[j], qualifiers, NULL, 0, &qual) != TCL_OK) break; if (objc - j < qualArgs[qual]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(objv[j]), "\" qualifier", NULL); goto errorExit; } switch ((enum qualEnum) qual) { case QUAL_DEPTH: { if (Tcl_GetIntFromObj(interp, objv[j + 1], &q->depth) != TCL_OK) goto errorExit; break; } case QUAL_STATE: { if (Tree_StateFromListObj(tree, objv[j + 1], q->states, SFO_NOT_TOGGLE) != TCL_OK) goto errorExit; break; } case QUAL_TAG: { if (q->exprOK) TagExpr_Free(&q->expr); if (TagExpr_Init(tree, objv[j + 1], &q->expr) != TCL_OK) return TCL_ERROR; q->exprOK = TRUE; break; } case QUAL_VISIBLE: { q->visible = 1; break; } case QUAL_NOT_VISIBLE: { q->visible = 0; break; } } *argsUsed += qualArgs[qual]; j += qualArgs[qual]; } return TCL_OK; errorExit: if (q->exprOK) TagExpr_Free(&q->expr); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Qualifies -- * * Helper routine for TreeItem_FromObj. * * Results: * Returns TRUE if the item meets the given criteria. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Qualifies( Qualifiers *q, /* Qualifiers to check. */ TreeItem item /* The item to test. May be NULL. */ ) { TreeCtrl *tree = q->tree; /* Note: if the item is NULL it is a "match" because we have run * out of items to check. */ if (item == NULL) return 1; if ((q->visible == 1) && !TreeItem_ReallyVisible(tree, item)) return 0; else if ((q->visible == 0) && TreeItem_ReallyVisible(tree, (TreeItem) item)) return 0; if (q->states[STATE_OP_OFF] & item->state) return 0; if ((q->states[STATE_OP_ON] & item->state) != q->states[STATE_OP_ON]) return 0; if (q->exprOK && !TagExpr_Eval(&q->expr, item->tagInfo)) return 0; if ((q->depth >= 0) && (item->depth + 1 != q->depth)) return 0; return 1; } /* *---------------------------------------------------------------------- * * Qualifiers_Free -- * * Helper routine for TreeItem_FromObj. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Qualifiers_Free( Qualifiers *q /* Out: Initialized qualifiers. */ ) { if (q->exprOK) TagExpr_Free(&q->expr); } /* *---------------------------------------------------------------------- * * TreeItemList_FromObj -- * * Parse a Tcl_Obj item description to get a list of items. * * -- returning a single item -- * "active MODIFIERS" * "anchor MODIFIERS" * "nearest x y MODIFIERS" * "root MODIFIERS" * "first QUALIFIERS MODIFIERS" * "last QUALIFIERS MODIFIERS" * "end QUALIFIERS MODIFIERS" * "rnc row col MODIFIERS" * "ID MODIFIERS" * -- returning multiple items -- * all QUALIFIERS * QUALIFIERS (like "all QUALIFIERS") * list listOfItemDescs * range QUALIFIERS * tag tagExpr QUALIFIERS * "TAG-EXPR QUALFIERS" * * MODIFIERS: * -- returning a single item -- * above * below * left * right * top * bottom * leftmost * rightmost * next QUALIFIERS * prev QUALIFIERS * parent * firstchild QUALIFIERS * lastchild QUALIFIERS * child N QUALIFIERS * nextsibling QUALIFIERS * prevsibling QUALIFIERS * sibling N QUALIFIERS * -- returning multiple items -- * ancestors QUALIFIERS * children QUALIFIERS * descendants QUALIFIERS * * QUALIFIERS: * depth integer * state stateList * tag tagExpr * visible * !visible * * Examples: * $T item id "first visible firstchild" * $T item id "first visible firstchild visible" * $T item id "nearest x y nextsibling visible" * $T item id "last visible state enabled" * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItemList_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, /* Object to parse to a list of items. */ TreeItemList *items, /* Uninitialized item list. Caller must free * it with TreeItemList_Free unless the * result of this function is TCL_ERROR. */ int flags /* IFO_xxx flags */ ) { Tcl_Interp *interp = tree->interp; int i, objc, index, listIndex, id; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_Obj **objv, *elemPtr; TreeItem item = NULL; Qualifiers q; int qualArgsTotal; static CONST84 char *indexName[] = { "active", "all", "anchor", "end", "first", "last", "list", "nearest", "range", "rnc", "root", (char *) NULL }; enum indexEnum { INDEX_ACTIVE, INDEX_ALL, INDEX_ANCHOR, INDEX_END, INDEX_FIRST, INDEX_LAST, INDEX_LIST, INDEX_NEAREST, INDEX_RANGE, INDEX_RNC, INDEX_ROOT }; /* Number of arguments used by indexName[]. */ static int indexArgs[] = { 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 1 }; /* Boolean: can indexName[] be followed by 1 or more qualifiers. */ static int indexQual[] = { 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1 }; static CONST84 char *modifiers[] = { "above", "ancestors", "below", "bottom", "child", "children", "descendants", "firstchild", "lastchild", "left", "leftmost", "next", "nextsibling", "parent", "prev", "prevsibling", "right", "rightmost", "sibling", "top", (char *) NULL }; enum modEnum { TMOD_ABOVE, TMOD_ANCESTORS, TMOD_BELOW, TMOD_BOTTOM, TMOD_CHILD, TMOD_CHILDREN, TMOD_DESCENDANTS, TMOD_FIRSTCHILD, TMOD_LASTCHILD, TMOD_LEFT, TMOD_LEFTMOST, TMOD_NEXT, TMOD_NEXTSIBLING, TMOD_PARENT, TMOD_PREV, TMOD_PREVSIBLING, TMOD_RIGHT, TMOD_RIGHTMOST, TMOD_SIBLING, TMOD_TOP }; /* Number of arguments used by modifiers[]. */ static int modArgs[] = { 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1 }; /* Boolean: can modifiers[] be followed by 1 or more qualifiers. */ static int modQual[] = { 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0 }; TreeItemList_Init(tree, items, 0); Qualifiers_Init(tree, &q); if (Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK) goto baditem; if (objc == 0) goto baditem; listIndex = 0; elemPtr = objv[listIndex]; if (Tcl_GetIndexFromObj(NULL, elemPtr, indexName, NULL, 0, &index) == TCL_OK) { if (objc - listIndex < indexArgs[index]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(elemPtr), "\" keyword", NULL); goto errorExit; } qualArgsTotal = 0; if (indexQual[index]) { if (Qualifiers_Scan(&q, objc, objv, listIndex + indexArgs[index], &qualArgsTotal) != TCL_OK) { goto errorExit; } } switch ((enum indexEnum) index) { case INDEX_ACTIVE: { item = tree->activeItem; break; } case INDEX_ALL: { if (qualArgsTotal) { hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if (Qualifies(&q, item)) { TreeItemList_Append(items, (TreeItem) item); } hPtr = Tcl_NextHashEntry(&search); } item = NULL; } else if (flags & IFO_LIST_ALL) { hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItemList_Append(items, item); hPtr = Tcl_NextHashEntry(&search); } item = NULL; } else { item = ITEM_ALL; } break; } case INDEX_ANCHOR: { item = tree->anchorItem; break; } case INDEX_FIRST: { item = tree->root; while (!Qualifies(&q, item)) item = TreeItem_Next(tree, item); break; } case INDEX_END: case INDEX_LAST: { item = tree->root; while (item->lastChild) { item = item->lastChild; } while (!Qualifies(&q, item)) item = TreeItem_Prev(tree, item); break; } case INDEX_LIST: { int listObjc; Tcl_Obj **listObjv; int count; if (Tcl_ListObjGetElements(interp, objv[listIndex + 1], &listObjc, &listObjv) != TCL_OK) { goto errorExit; } for (i = 0; i < listObjc; i++) { TreeItemList item2s; if (TreeItemList_FromObj(tree, listObjv[i], &item2s, flags) != TCL_OK) goto errorExit; TreeItemList_Concat(items, &item2s); TreeItemList_Free(&item2s); } /* If any of the item descriptions in the list is "all", then * clear the list of items and use "all". */ count = TreeItemList_Count(items); for (i = 0; i < count; i++) { TreeItem item2 = TreeItemList_Nth(items, i); if (IS_ALL(item2)) break; } if (i < count) { TreeItemList_Free(items); item = ITEM_ALL; } else item = NULL; break; } case INDEX_NEAREST: { int x, y; if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[listIndex + 1], &x) != TCL_OK) { goto errorExit; } if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[listIndex + 2], &y) != TCL_OK) { goto errorExit; } item = Tree_ItemUnderPoint(tree, &x, &y, TRUE); break; } case INDEX_RANGE: { TreeItem itemFirst, itemLast; if (TreeItem_FromObj(tree, objv[listIndex + 1], &itemFirst, IFO_NOT_NULL) != TCL_OK) goto errorExit; if (TreeItem_FromObj(tree, objv[listIndex + 2], &itemLast, IFO_NOT_NULL) != TCL_OK) goto errorExit; if (TreeItem_FirstAndLast(tree, &itemFirst, &itemLast) == 0) goto errorExit; while (1) { if (Qualifies(&q, itemFirst)) { TreeItemList_Append(items, itemFirst); } if (itemFirst == itemLast) break; itemFirst = TreeItem_Next(tree, itemFirst); } item = NULL; break; } case INDEX_RNC: { int row, col; if (Tcl_GetIntFromObj(interp, objv[listIndex + 1], &row) != TCL_OK) goto errorExit; if (Tcl_GetIntFromObj(interp, objv[listIndex + 2], &col) != TCL_OK) goto errorExit; item = Tree_RNCToItem(tree, row, col); break; } case INDEX_ROOT: { item = tree->root; break; } } listIndex += indexArgs[index] + qualArgsTotal; /* No indexName[] was found. */ } else { int gotId = FALSE; TagExpr expr; /* Try an itemPrefix + item ID. */ if (tree->itemPrefixLen) { char *end, *t = Tcl_GetString(elemPtr); if (strncmp(t, tree->itemPrefix, tree->itemPrefixLen) == 0) { t += tree->itemPrefixLen; id = strtoul(t, &end, 10); if ((end != t) && (*end == '\0')) gotId = TRUE; } /* Try an item ID. */ } else if (Tcl_GetIntFromObj(NULL, elemPtr, &id) == TCL_OK) { gotId = TRUE; } if (gotId) { hPtr = Tcl_FindHashEntry(&tree->itemHash, (char *) id); if (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); } else { item = NULL; } listIndex++; goto gotFirstPart; } /* Try a list of qualifiers. This has the same effect as * "all QUALIFIERS". */ if (Qualifiers_Scan(&q, objc, objv, listIndex, &qualArgsTotal) != TCL_OK) { goto errorExit; } if (qualArgsTotal) { hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if (Qualifies(&q, item)) { TreeItemList_Append(items, item); } hPtr = Tcl_NextHashEntry(&search); } item = NULL; listIndex += qualArgsTotal; goto gotFirstPart; } /* Try a tag expression. */ if (objc > 1) { if (Qualifiers_Scan(&q, objc, objv, listIndex + 1, &qualArgsTotal) != TCL_OK) { goto errorExit; } } if (TagExpr_Init(tree, elemPtr, &expr) != TCL_OK) goto errorExit; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if (TagExpr_Eval(&expr, item->tagInfo) && Qualifies(&q, item)) { TreeItemList_Append(items, item); } hPtr = Tcl_NextHashEntry(&search); } TagExpr_Free(&expr); item = NULL; listIndex += 1 + qualArgsTotal; } gotFirstPart: /* If 1 item, use it and clear the list. */ if (TreeItemList_Count(items) == 1) { item = TreeItemList_Nth(items, 0); items->count = 0; } /* If "all" but only root exists, use it. */ if (IS_ALL(item) && (tree->itemCount == 1) && !(flags & IFO_NOT_ROOT)) { item = tree->root; } /* If > 1 item, no modifiers may follow. */ if ((TreeItemList_Count(items) > 1) || IS_ALL(item)) { if (listIndex < objc) { Tcl_AppendResult(interp, "unexpected arguments after \"", (char *) NULL); for (i = 0; i < listIndex; i++) { Tcl_AppendResult(interp, Tcl_GetString(objv[i]), (char *) NULL); if (i != listIndex - 1) Tcl_AppendResult(interp, " ", (char *) NULL); } Tcl_AppendResult(interp, "\"", (char *) NULL); goto errorExit; } } /* This means a valid specification was given, but there is no such item */ if ((TreeItemList_Count(items) == 0) && (item == NULL)) { if (flags & IFO_NOT_NULL) goto noitem; /* Empty list returned */ goto goodExit; } /* Process any modifiers following the item we matched above. */ for (; listIndex < objc; /* nothing */) { elemPtr = objv[listIndex]; if (Tcl_GetIndexFromObj(interp, elemPtr, modifiers, "modifier", 0, &index) != TCL_OK) { goto errorExit; } if (objc - listIndex < modArgs[index]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(elemPtr), "\" modifier", NULL); goto errorExit; } qualArgsTotal = 0; if (modQual[index]) { Qualifiers_Free(&q); Qualifiers_Init(tree, &q); if (Qualifiers_Scan(&q, objc, objv, listIndex + modArgs[index], &qualArgsTotal) != TCL_OK) { goto errorExit; } } switch ((enum modEnum) index) { case TMOD_ABOVE: { item = Tree_ItemAbove(tree, item); break; } case TMOD_ANCESTORS: { item = item->parent; while (item != NULL) { if (Qualifies(&q, item)) { TreeItemList_Append(items, item); } item = item->parent; } item = NULL; break; } case TMOD_BELOW: { item = Tree_ItemBelow(tree, item); break; } case TMOD_BOTTOM: { item = Tree_ItemBottom(tree, item); break; } case TMOD_CHILD: { int n; if (Tcl_GetIntFromObj(interp, objv[listIndex + 1], &n) != TCL_OK) { goto errorExit; } item = item->firstChild; while (item != NULL) { if (Qualifies(&q, item)) if (n-- <= 0) break; item = item->nextSibling; } break; } case TMOD_CHILDREN: { item = item->firstChild; while (item != NULL) { if (Qualifies(&q, item)) { TreeItemList_Append(items, item); } item = item->nextSibling; } item = NULL; break; } case TMOD_DESCENDANTS: { TreeItem last = item; while (last->lastChild != NULL) last = last->lastChild; item = item->firstChild; while (item != NULL) { if (Qualifies(&q, item)) { TreeItemList_Append(items, item); } if (item == last) break; item = TreeItem_Next(tree, item); } item = NULL; break; } case TMOD_FIRSTCHILD: { item = item->firstChild; while (!Qualifies(&q, item)) item = item->nextSibling; break; } case TMOD_LASTCHILD: { item = item->lastChild; while (!Qualifies(&q, item)) item = item->prevSibling; break; } case TMOD_LEFT: { item = Tree_ItemLeft(tree, item); break; } case TMOD_LEFTMOST: { item = Tree_ItemLeftMost(tree, item); break; } case TMOD_NEXT: { item = TreeItem_Next(tree, item); while (!Qualifies(&q, item)) item = TreeItem_Next(tree, item); break; } case TMOD_NEXTSIBLING: { item = item->nextSibling; while (!Qualifies(&q, item)) item = item->nextSibling; break; } case TMOD_PARENT: { item = item->parent; break; } case TMOD_PREV: { item = TreeItem_Prev(tree, item); while (!Qualifies(&q, item)) item = TreeItem_Prev(tree, item); break; } case TMOD_PREVSIBLING: { item = item->prevSibling; while (!Qualifies(&q, item)) item = item->prevSibling; break; } case TMOD_RIGHT: { item = Tree_ItemRight(tree, item); break; } case TMOD_RIGHTMOST: { item = Tree_ItemRightMost(tree, item); break; } case TMOD_SIBLING: { int n; if (Tcl_GetIntFromObj(interp, objv[listIndex + 1], &n) != TCL_OK) { goto errorExit; } item = item->parent; if (item == NULL) break; item = item->firstChild; while (item != NULL) { if (Qualifies(&q, item)) if (n-- <= 0) break; item = item->nextSibling; } break; } case TMOD_TOP: { item = Tree_ItemTop(tree, item); break; } } if ((TreeItemList_Count(items) > 1) || IS_ALL(item)) { int end = listIndex + modArgs[index] + qualArgsTotal; if (end < objc) { Tcl_AppendResult(interp, "unexpected arguments after \"", (char *) NULL); for (i = 0; i < end; i++) { Tcl_AppendResult(interp, Tcl_GetString(objv[i]), (char *) NULL); if (i != end - 1) Tcl_AppendResult(interp, " ", (char *) NULL); } Tcl_AppendResult(interp, "\"", (char *) NULL); goto errorExit; } } if ((TreeItemList_Count(items) == 0) && (item == NULL)) { if (flags & IFO_NOT_NULL) goto noitem; /* Empty list returned. */ goto goodExit; } listIndex += modArgs[index] + qualArgsTotal; } if ((flags & IFO_NOT_MANY) && (IS_ALL(item) || (TreeItemList_Count(items) > 1))) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } if (TreeItemList_Count(items)) { if (flags & (IFO_NOT_ROOT | IFO_NOT_ORPHAN)) { int i; for (i = 0; i < TreeItemList_Count(items); i++) { item = TreeItemList_Nth(items, i); if (IS_ROOT(item) && (flags & IFO_NOT_ROOT)) goto notRoot; if ((item->parent == NULL) && (flags & IFO_NOT_ORPHAN)) goto notOrphan; } } } else if (IS_ALL(item)) { TreeItemList_Append(items, ITEM_ALL); } else { if (IS_ROOT(item) && (flags & IFO_NOT_ROOT)) { notRoot: FormatResult(interp, "can't specify \"root\" for this command"); goto errorExit; } if ((item->parent == NULL) && (flags & IFO_NOT_ORPHAN)) { notOrphan: FormatResult(interp, "item \"%s\" has no parent", Tcl_GetString(objPtr)); goto errorExit; } TreeItemList_Append(items, item); } goodExit: Qualifiers_Free(&q); return TCL_OK; baditem: Tcl_AppendResult(interp, "bad item description \"", Tcl_GetString(objPtr), "\"", NULL); goto errorExit; noitem: Tcl_AppendResult(interp, "item \"", Tcl_GetString(objPtr), "\" doesn't exist", NULL); errorExit: Qualifiers_Free(&q); TreeItemList_Free(items); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TreeItem_FromObj -- * * Parse a Tcl_Obj item description to get a single item. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, /* Object to parse to an item. */ TreeItem *itemPtr, /* Returned item. */ int flags /* IFO_xxx flags */ ) { TreeItemList items; if (TreeItemList_FromObj(tree, objPtr, &items, flags | IFO_NOT_MANY) != TCL_OK) return TCL_ERROR; /* May be NULL. */ (*itemPtr) = TreeItemList_Nth(&items, 0); TreeItemList_Free(&items); return TCL_OK; } /* *---------------------------------------------------------------------- * * ItemForEach_Start -- * * Begin iterating over items. A command might accept two item * descriptions for a range of items, or a single item description * which may itself refer to multiple items. Either item * description could be ITEM_ALL. * * Results: * Returns the first item to iterate over. If an error occurs * then ItemForEach.error is set to 1. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem ItemForEach_Start( TreeItemList *items, /* List of items. */ TreeItemList *item2s, /* List of items or NULL. */ ItemForEach *iter /* Returned info, pass to ItemForEach_Next. */ ) { TreeCtrl *tree = items->tree; TreeItem item, item2 = NULL; item = TreeItemList_Nth(items, 0); if (item2s) item2 = TreeItemList_Nth(item2s, 0); iter->tree = tree; iter->all = FALSE; iter->error = 0; iter->items = NULL; if (IS_ALL(item) || IS_ALL(item2)) { Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(&tree->itemHash, &iter->search); iter->all = TRUE; return iter->item = (TreeItem) Tcl_GetHashValue(hPtr); } if (item2 != NULL) { if (TreeItem_FirstAndLast(tree, &item, &item2) == 0) { iter->error = 1; return NULL; } iter->last = item2; return iter->item = item; } iter->items = items; iter->index = 0; return iter->item = item; } /* *---------------------------------------------------------------------- * * ItemForEach_Next -- * * Returns the next item to iterate over. Keep calling this until * the result is NULL. * * Results: * Returns the next item to iterate over or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem ItemForEach_Next( ItemForEach *iter /* Initialized by ItemForEach_Start. */ ) { TreeCtrl *tree = iter->tree; if (iter->all) { Tcl_HashEntry *hPtr = Tcl_NextHashEntry(&iter->search); if (hPtr == NULL) return iter->item = NULL; return iter->item = (TreeItem) Tcl_GetHashValue(hPtr); } if (iter->items != NULL) { if (iter->index >= TreeItemList_Count(iter->items)) return iter->item = NULL; return iter->item = TreeItemList_Nth(iter->items, ++iter->index); } if (iter->item == iter->last) return iter->item = NULL; return iter->item = TreeItem_Next(tree, iter->item); } /* *---------------------------------------------------------------------- * * Item_ToggleOpen -- * * Inverts the STATE_OPEN flag of an Item. * * Results: * Items may be displayed/undisplayed. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Item_ToggleOpen( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ int stateOff, /* STATE_OPEN or 0 */ int stateOn /* STATE_OPEN or 0 */ ) { int mask; mask = TreeItem_ChangeState(tree, item, stateOff, stateOn); if (IS_ROOT(item) && !tree->showRoot) return; #if 0 /* Don't affect display if we weren't visible */ if (!TreeItem_ReallyVisible(tree, item)) return; /* Invalidate display info for this item, so it is redrawn later. */ Tree_InvalidateItemDInfo(tree, item, NULL); #endif if (item->numChildren > 0) { /* indexVis needs updating for all items after this one, if we * have any visible children */ tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES); /* Hiding/showing children may change the width of any column */ Tree_InvalidateColumnWidth(tree, NULL); } /* If this item was previously onscreen, this call is repetitive. */ Tree_EventuallyRedraw(tree); } /* *---------------------------------------------------------------------- * * TreeItem_OpenClose -- * * Inverts the STATE_OPEN flag of an Item. * * Results: * Items may be displayed/undisplayed. * * Side effects: * Display changes. and events may be * generated. * *---------------------------------------------------------------------- */ void TreeItem_OpenClose( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int mode /* -1: toggle * 0: close * 1: open */ ) { int stateOff = 0, stateOn = 0; /* When processing a list of items, any or event * may result in items being deleted. */ if (IS_DELETED(item)) return; if (mode == -1) { if (item->state & STATE_OPEN) stateOff = STATE_OPEN; else stateOn = STATE_OPEN; } else if (!mode && (item->state & STATE_OPEN)) stateOff = STATE_OPEN; else if (mode && !(item->state & STATE_OPEN)) stateOn = STATE_OPEN; if (stateOff != stateOn) { TreeNotify_OpenClose(tree, item, stateOn, TRUE); if (IS_DELETED(item)) return; Item_ToggleOpen(tree, item, stateOff, stateOn); TreeNotify_OpenClose(tree, item, stateOn, FALSE); } } /* *---------------------------------------------------------------------- * * TreeItem_Delete -- * * Recursively frees resources associated with an Item and its * descendants. * * Results: * Items are removed from their parent and freed. * * Side effects: * Memory is freed. If the active item or selection-anchor item * is deleted, the root becomes the active/anchor item. * Display changes may occur. * *---------------------------------------------------------------------- */ void TreeItem_Delete( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { if (TreeItem_ReallyVisible(tree, item)) Tree_InvalidateColumnWidth(tree, NULL); while (item->numChildren > 0) TreeItem_Delete(tree, item->firstChild); TreeItem_RemoveFromParent(tree, item); TreeDisplay_ItemDeleted(tree, item); Tree_RemoveItem(tree, item); TreeItem_FreeResources(tree, item); if (tree->activeItem == item) { tree->activeItem = tree->root; TreeItem_ChangeState(tree, tree->activeItem, 0, STATE_ACTIVE); } if (tree->anchorItem == item) tree->anchorItem = tree->root; if (tree->debug.enable && tree->debug.data) Tree_Debug(tree); } /* *---------------------------------------------------------------------- * * TreeItem_Deleted -- * * Return 1 if the given item is deleted. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_Deleted( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return IS_DELETED(item); } /* *---------------------------------------------------------------------- * * TreeItem_FirstAndLast -- * * Determine the order of two items and swap them if needed. * * Results: * If the items do not share a common ancestor, 0 is returned and * an error message is left in the interpreter result. * Otherwise the return value is the number of items in the * range between first and last. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_FirstAndLast( TreeCtrl *tree, /* Widget info. */ TreeItem *first, /* Item token. */ TreeItem *last /* Item token. */ ) { int indexFirst, indexLast, index; if (TreeItem_RootAncestor(tree, *first) != TreeItem_RootAncestor(tree, *last)) { FormatResult(tree->interp, "item %s%d and item %s%d don't share a common ancestor", tree->itemPrefix, TreeItem_GetID(tree, *first), tree->itemPrefix, TreeItem_GetID(tree, *last)); return 0; } TreeItem_ToIndex(tree, *first, &indexFirst, NULL); TreeItem_ToIndex(tree, *last, &indexLast, NULL); if (indexFirst > indexLast) { TreeItem item = *first; *first = *last; *last = item; index = indexFirst; indexFirst = indexLast; indexLast = index; } return indexLast - indexFirst + 1; } /* *---------------------------------------------------------------------- * * TreeItem_ListDescendants -- * * Appends descendants of an item to a list of items. * * Results: * List of items may grow. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_ListDescendants( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemList *items /* List of items to append descendants to. */ ) { TreeItem last; if (item->firstChild == NULL) return; last = item; while (last->lastChild != NULL) last = last->lastChild; item = item->firstChild; while (1) { TreeItemList_Append(items, item); if (item == last) break; item = TreeItem_Next(tree, item); } } /* *---------------------------------------------------------------------- * * TreeItem_UpdateDepth -- * * Recursively updates Item.depth of an Item and its * descendants. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_UpdateDepth( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem child; if (IS_ROOT(item)) return; if (item->parent != NULL) item->depth = item->parent->depth + 1; else item->depth = 0; child = item->firstChild; while (child != NULL) { TreeItem_UpdateDepth(tree, child); child = child->nextSibling; } } /* *---------------------------------------------------------------------- * * TreeItem_AddToParent -- * * Called *after* an Item is added as a child to another Item. * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void TreeItem_AddToParent( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem last; /* If this is the new last child, redraw the lines of the previous * sibling and all of its descendants so the line from the previous * sibling reaches this item */ if ((item->prevSibling != NULL) && (item->nextSibling == NULL) && tree->showLines && (tree->columnTree != NULL)) { last = item->prevSibling; while (last->lastChild != NULL) last = last->lastChild; Tree_InvalidateItemDInfo(tree, tree->columnTree, item->prevSibling, last); } tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES); /* Tree_UpdateItemIndex() also recalcs depth, but in one of my demos * I retrieve item depth during list creation. Since Tree_UpdateItemIndex() * is slow I will keep depth up-to-date here. */ TreeItem_UpdateDepth(tree, item); Tree_InvalidateColumnWidth(tree, NULL); if (tree->debug.enable && tree->debug.data) Tree_Debug(tree); } /* *---------------------------------------------------------------------- * * RemoveFromParentAux -- * * Recursively update Item.depth, Item.index and Item.indexVis. * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void RemoveFromParentAux( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item being removed. */ int *index /* New value of Item.index. Is incremented. */ ) { TreeItem child; /* Invalidate display info. Don't free it because we may just be * moving the item to a new parent. FIXME: if it is being moved, * it might not actually need to be redrawn (just copied) */ if (item->dInfo != NULL) Tree_InvalidateItemDInfo(tree, NULL, item, NULL); if (item->parent != NULL) item->depth = item->parent->depth + 1; else item->depth = 0; item->index = (*index)++; item->indexVis = -1; child = item->firstChild; while (child != NULL) { RemoveFromParentAux(tree, child, index); child = child->nextSibling; } } /* *---------------------------------------------------------------------- * * TreeItem_RemoveFromParent -- * * Remove an Item from its parent (if any). * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void TreeItem_RemoveFromParent( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem parent = item->parent; TreeItem last; int index = 0; if (parent == NULL) return; /* If this is the last child, redraw the lines of the previous * sibling and all of its descendants because the line from * the previous sibling to us is now gone */ if ((item->prevSibling != NULL) && (item->nextSibling == NULL) && tree->showLines && (tree->columnTree != NULL)) { last = item->prevSibling; while (last->lastChild != NULL) last = last->lastChild; Tree_InvalidateItemDInfo(tree, tree->columnTree, item->prevSibling, last); } /* * Set a flag indicating that item indexes are out-of-date. This doesn't * cover the current item being removed. */ tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES); if (item->prevSibling) item->prevSibling->nextSibling = item->nextSibling; if (item->nextSibling) item->nextSibling->prevSibling = item->prevSibling; if (parent->firstChild == item) { parent->firstChild = item->nextSibling; if (!parent->firstChild) parent->lastChild = NULL; } if (parent->lastChild == item) parent->lastChild = item->prevSibling; item->prevSibling = item->nextSibling = NULL; item->parent = NULL; parent->numChildren--; /* * Update Item.depth, Item.index and Item.indexVis for the item and its * descendants. An up-to-date Item.index is needed for some operations that * use a range of items, such as [item delete]. */ RemoveFromParentAux(tree, item, &index); } /* *---------------------------------------------------------------------- * * TreeItem_RemoveColumns -- * * Free a range of Columns in an Item. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeItem_RemoveColumns( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int first, /* 0-based column index at start of * the range. Must be <= last */ int last /* 0-based column index at end of * the range. Must be >= first */ ) { Column *column = item->columns; Column *prev = NULL, *next = NULL; int i = 0; while (column != NULL) { next = column->next; if (i == first - 1) prev = column; else if (i >= first) Column_FreeResources(tree, column); if (i == last) break; ++i; column = next; } if (prev != NULL) prev->next = next; else item->columns = next; } /* *---------------------------------------------------------------------- * * TreeItem_RemoveAllColumns -- * * Free all the Columns in an Item. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeItem_RemoveAllColumns( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { Column *column = item->columns; while (column != NULL) { Column *next = column->next; Column_FreeResources(tree, column); column = next; } item->columns = NULL; } /* *---------------------------------------------------------------------- * * Item_CreateColumn -- * * Allocate a Column record for an Item if it doesn't already * exist. * * Results: * Pointer to new or existing Column record. * * Side effects: * Any column records preceding the desired one are allocated * if they weren't already. Memory is allocated. * *---------------------------------------------------------------------- */ static Column * Item_CreateColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to contain the column. */ int columnIndex, /* 0-based index of new column. */ int *isNew /* May be NULL. Set to TRUE if the * column record was created. */ ) { Column *column; int i; if (isNew != NULL) (*isNew) = FALSE; column = item->columns; if (column == NULL) { column = Column_Alloc(tree); item->columns = column; if (isNew != NULL) (*isNew) = TRUE; } for (i = 0; i < columnIndex; i++) { if (column->next == NULL) { column->next = Column_Alloc(tree); if (isNew != NULL) (*isNew) = TRUE; } column = column->next; } return column; } /* *---------------------------------------------------------------------- * * TreeItem_MoveColumn -- * * Rearranges an Item's list of Column records by moving one * in front of another. * * Results: * If the Column to be moved does not exist and the Column to place it * in front of does not exist, then nothing happens. If the Column is * to be moved past all currently allocated Columns, then new * Column records are allocated. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ void TreeItem_MoveColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int columnIndex, /* 0-based index of the column to move. */ int beforeIndex /* 0-based index of the second column to move * the first column to the left of. */ ) { Column *before = NULL, *move = NULL; Column *prevM = NULL, *prevB = NULL; Column *last = NULL, *prev, *walk; int index = 0; prev = NULL; walk = item->columns; while (walk != NULL) { if (index == columnIndex) { prevM = prev; move = walk; } if (index == beforeIndex) { prevB = prev; before = walk; } prev = walk; if (walk->next == NULL) last = walk; index++; walk = walk->next; } if (move == NULL && before == NULL) return; if (move == NULL) move = Column_Alloc(tree); else { if (before == NULL) { prevB = Item_CreateColumn(tree, item, beforeIndex - 1, NULL); last = prevB; } if (prevM == NULL) item->columns = move->next; else prevM->next = move->next; } if (before == NULL) { last->next = move; move->next = NULL; } else { if (prevB == NULL) item->columns = move; else prevB->next = move; move->next = before; } } /* *---------------------------------------------------------------------- * * TreeItem_FreeResources -- * * Free memory etc assocated with an Item. * * Results: * None. * * Side effects: * Memory is deallocated. Display changes. * *---------------------------------------------------------------------- */ void TreeItem_FreeResources( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { Column *column; column = item->columns; while (column != NULL) column = Column_FreeResources(tree, column); if (item->dInfo != NULL) Tree_FreeItemDInfo(tree, item, NULL); if (item->rInfo != NULL) Tree_FreeItemRInfo(tree, item); if (item->spans != NULL) ckfree((char *) item->spans); Tk_FreeConfigOptions((char *) item, tree->itemOptionTable, tree->tkwin); /* Add the item record to the "preserved" list. It will be freed later. */ TreeItemList_Append(&tree->preserveItemList, item); } /* *---------------------------------------------------------------------- * * TreeItem_Release -- * * Finally free an item record when it is no longer needed. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeItem_Release( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, ItemUid, (char *) item, sizeof(TreeItem_)); #else WFREE(item, TreeItem_); #endif } /* *---------------------------------------------------------------------- * * Item_UseHeight -- * * Return the height used by styles in an Item. * * Results: * Maximum height in pixels of the style in each visible Column. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Item_HeightOfStyles( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item record. */ ) { Column *column = item->columns; TreeColumn treeColumn = tree->columns; StyleDrawArgs drawArgs; int height = 0; drawArgs.tree = tree; while (column != NULL) { if (TreeColumn_Visible(treeColumn) && (column->style != NULL)) { drawArgs.state = item->state | column->cstate; drawArgs.style = column->style; drawArgs.indent = (treeColumn == tree->columnTree) ? TreeItem_Indent(tree, item) : 0; if ((TreeColumn_FixedWidth(treeColumn) != -1) || TreeColumn_Squeeze(treeColumn)) { drawArgs.width = TreeColumn_UseWidth(treeColumn); } else drawArgs.width = -1; height = MAX(height, TreeStyle_UseHeight(&drawArgs)); } treeColumn = TreeColumn_Next(treeColumn); column = column->next; } return height; } /* *---------------------------------------------------------------------- * * TreeItem_Height -- * * Return the height of an Item. * * Results: * If the Item -height option is > 0, the result is the maximum * of the button height (if a button is displayed) and the -height * option. * If the TreeCtrl -itemheight option is > 0, the result is the maximum * of the button height (if a button is displayed) and the -itemheight * option. * Otherwise the result is the maximum of the button height (if a button * is displayed) AND the TreeCtrl -minitemheight AND the height of * the style in each visible Column. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_Height( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { int buttonHeight = 0; int useHeight; if (!IS_VISIBLE(item) || (IS_ROOT(item) && !tree->showRoot)) return 0; /* Get requested height of the style in each column */ useHeight = Item_HeightOfStyles(tree, item); /* Can't have less height than our button */ if (tree->showButtons && HAS_BUTTON(item) && (!IS_ROOT(item) || tree->showRootButton)) { buttonHeight = ButtonHeight(tree, item->state); } /* User specified a fixed height for this item */ if (item->fixedHeight > 0) return MAX(item->fixedHeight, buttonHeight); /* Fixed height of all items */ if (tree->itemHeight > 0) return MAX(tree->itemHeight, buttonHeight); /* Minimum height of all items */ if (tree->minItemHeight > 0) useHeight = MAX(useHeight, tree->minItemHeight); /* No fixed height specified */ return MAX(useHeight, buttonHeight); } /* *---------------------------------------------------------------------- * * TreeItem_InvalidateHeight -- * * Marks Item.neededHeight out-of-date. * NOTE: Item.neededHeight is unused. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_InvalidateHeight( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { } /* *---------------------------------------------------------------------- * * Item_FindColumn -- * * Return a Column record given a zero-based index. * * Results: * The Column record or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Column * Item_FindColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ int columnIndex /* 0-based index of column to find. */ ) { Column *column; int i = 0; column = item->columns; if (!column) return NULL; while (column != NULL && i < columnIndex) { column = column->next; i++; } return column; } /* *---------------------------------------------------------------------- * * Item_FindColumnFromObj -- * * Return a Column record given a Tcl_Obj column description. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Item_FindColumnFromObj( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ Tcl_Obj *obj, /* Column description. */ Column **columnPtr, /* Returned column, or NULL. */ int *indexPtr /* May be NULL. Returned 0-based index of * the column. */ ) { TreeColumn treeColumn; int columnIndex; if (TreeColumn_FromObj(tree, obj, &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; columnIndex = TreeColumn_Index(treeColumn); (*columnPtr) = Item_FindColumn(tree, item, columnIndex); if (indexPtr != NULL) (*indexPtr) = columnIndex; return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeItem_FindColumn -- * * Return an item-column token given a zero-based index. * * Results: * The item-column token or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemColumn TreeItem_FindColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int columnIndex /* 0-based index of column to find. */ ) { return (TreeItemColumn) Item_FindColumn(tree, item, columnIndex); } /* *---------------------------------------------------------------------- * * TreeItem_ColumnFromObj -- * * Return an item-column token given a Tcl_Obj column description. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_ColumnFromObj( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ Tcl_Obj *obj, /* Column description. */ TreeItemColumn *columnPtr, /* Returned column, or NULL. */ int *indexPtr /* May be NULL. Returned 0-based index of * the column. */ ) { return Item_FindColumnFromObj(tree, item, obj, (Column **) columnPtr, indexPtr); } #if 0 /* *---------------------------------------------------------------------- * * Item_CreateColumnFromObj -- * * Return a Column record given a Tcl_Obj column description. * The Column record is allocated if it doesn't exist. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static int Item_CreateColumnFromObj( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ Tcl_Obj *obj, /* Column description. */ Column **column, /* Returned column. */ int *indexPtr, /* May be NULL. Returned 0-based index of * the column. */ int *isNew /* May be NULL. Set to TRUE if the * column record was created. */ ) { TreeColumn treeColumn; int columnIndex; if (TreeColumn_FromObj(tree, obj, &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; columnIndex = TreeColumn_Index(treeColumn); (*column) = Item_CreateColumn(tree, item, columnIndex, isNew); if (indexPtr != NULL) (*indexPtr) = columnIndex; return TCL_OK; } #endif /* *---------------------------------------------------------------------- * * TreeItem_Indent -- * * Return the amount of indentation for the given item. This is * the width of the buttons/lines. * * Results: * Pixel value >= 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_Indent( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { int indent; if (IS_ROOT(item)) return (tree->showRoot && tree->showButtons && tree->showRootButton) ? tree->useIndent : 0; Tree_UpdateItemIndex(tree); indent = tree->useIndent * item->depth; if (tree->showRoot || tree->showButtons || tree->showLines) indent += tree->useIndent; if (tree->showRoot && tree->showButtons && tree->showRootButton) indent += tree->useIndent; return indent; } /* *---------------------------------------------------------------------- * * ItemDrawBackground -- * * Draws part of the background area of an Item. The area is * erased to the -itembackground color of the tree column or the * TreeCtrl -background color. If the TreeCtrl -backgroundimage * option is specified then that image is tiled over the given area. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ static void ItemDrawBackground( TreeCtrl *tree, /* Widget info. */ TreeColumn treeColumn, /* Tree-column token. */ TreeItem item, /* Item record. */ Column *column, /* First column. */ Drawable drawable, /* Where to draw. */ int x, int y, /* Area of the item to draw. */ int width, int height, /* ^ */ int index /* Used to select a color from the * tree-column's -itembackground option. */ ) { GC gc = None; gc = TreeColumn_BackgroundGC(treeColumn, index); if (gc == None) gc = Tk_3DBorderGC(tree->tkwin, tree->border, TK_3D_FLAT_GC); /* * FIXME: If the background image is non-transparent, there is no * need to erase first. */ XFillRectangle(tree->display, drawable, gc, x, y, width, height); if (tree->backgroundImage != NULL) { Tree_DrawTiledImage(tree, drawable, tree->backgroundImage, x, y, x + width, y + height, tree->drawableXOrigin, tree->drawableYOrigin); } } /* *---------------------------------------------------------------------- * * TreeItem_SpansInvalidate -- * * Invalidates the Item.spans field of one or all items. * * Results: * The item(s) are removed from the TreeCtrl.itemSpansHash to * indicate that the list of spans must be recalculated. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_SpansInvalidate( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. NULL for all items. */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; int count = 0; if (item == NULL) { hPtr = Tcl_FirstHashEntry(&tree->itemSpansHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->itemSpansHash, hPtr); item->flags &= ~ITEM_FLAG_SPANS_VALID; count++; hPtr = Tcl_NextHashEntry(&search); } if (count) { Tcl_DeleteHashTable(&tree->itemSpansHash); Tcl_InitHashTable(&tree->itemSpansHash, TCL_ONE_WORD_KEYS); } } else if (item->flags & ITEM_FLAG_SPANS_VALID) { hPtr = Tcl_FindHashEntry(&tree->itemSpansHash, (char *) item); Tcl_DeleteHashEntry(hPtr); item->flags &= ~ITEM_FLAG_SPANS_VALID; count++; } if (count && tree->debug.enable && tree->debug.display) dbwin("TreeItem_SpansInvalidate forgot %d items\n", count); } /* *---------------------------------------------------------------------- * * TreeItem_SpansRedo -- * * Updates the Item.spans field of an item. * * Results: * Item.spans is resized if needed to (at least) the current number * of tree columns. For tree column N, the index of the item * column displayed there is written to spans[N]. * * The return value is 1 if every span is 1, otherwise 0. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int TreeItem_SpansRedo( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeColumn treeColumn = tree->columns; Column *itemColumn = item->columns; int columnIndex = 0, spanner = 0, span = 1, simple = TRUE; int lock = TreeColumn_Lock(treeColumn); if (tree->debug.enable && tree->debug.display) dbwin("TreeItem_SpansRedo item %d\n", item->id); if (item->spans == NULL) { item->spans = (int *) ckalloc(sizeof(int) * tree->columnCount); item->spanAlloc = tree->columnCount; } else if (item->spanAlloc < tree->columnCount) { item->spans = (int *) ckrealloc((char *) item->spans, sizeof(int) * tree->columnCount); item->spanAlloc = tree->columnCount; } while (treeColumn != NULL) { /* End current span if column lock changes. */ if (TreeColumn_Lock(treeColumn) != lock) { lock = TreeColumn_Lock(treeColumn); span = 1; } if (--span == 0) { if (TreeColumn_Visible(treeColumn)) span = itemColumn ? itemColumn->span : 1; else span = 1; if (span > 1) simple = FALSE; spanner = columnIndex; } item->spans[columnIndex] = spanner; columnIndex++; treeColumn = TreeColumn_Next(treeColumn); if (itemColumn != NULL) itemColumn = itemColumn->next; } return simple; } /* *---------------------------------------------------------------------- * * TreeItem_SpansRedoIfNeeded -- * * Updates the Item.spans field of an item if needed. * * Results: * If all spans are known to be 1, nothing is done. If the list of * spans is marked valid, nothing is done. Otherwise the list of * spans is recalculated; if any span is > 1 the item is added * to TreeCtrl.itemSpansHash. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ void TreeItem_SpansRedoIfNeeded( TreeCtrl *tree, TreeItem item ) { /* All the spans are 1. */ if (item->flags & ITEM_FLAG_SPANS_SIMPLE) return; /* Some spans > 1, but we calculated them already. */ if (item->flags & ITEM_FLAG_SPANS_VALID) return; if (TreeItem_SpansRedo(tree, item)) { /* Reverted to all spans=1. */ item->flags |= ITEM_FLAG_SPANS_SIMPLE; } else { int isNew; Tcl_HashEntry *hPtr; hPtr = Tcl_CreateHashEntry(&tree->itemSpansHash, (char *) item, &isNew); Tcl_SetHashValue(hPtr, (ClientData) item); item->flags |= ITEM_FLAG_SPANS_VALID; } } /* *---------------------------------------------------------------------- * * TreeItem_GetSpans -- * * Returns the spans[] array for an item. * * Results: * If all spans are known to be 1, the result is NULL. Otherwise the * list of spans is returned. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int * TreeItem_GetSpans( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem_SpansRedoIfNeeded(tree, item); if (item->flags & ITEM_FLAG_SPANS_SIMPLE) return NULL; return item->spans; } /* * The following structure holds information about which item column * is displayed at a given tree column. */ typedef struct SpanInfo { TreeColumn treeColumn; /* Always non-null. */ TreeItemColumn itemColumn; /* May be null. */ int span; /* Number of tree-columns spanned. */ int width; /* Width of the span. */ } SpanInfo; /* *---------------------------------------------------------------------- * * Item_GetSpans -- * * Fills an array of SpanInfo records, one per visible span. * * Results: * The return value is the number of SpanInfo records written. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Item_GetSpans( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeColumn firstColumn, /* Which columns. */ SpanInfo spans[] /* Returned span records. */ ) { TreeColumn treeColumn = firstColumn; int columnIndex = TreeColumn_Index(firstColumn); Column *column = Item_FindColumn(tree, item, columnIndex); int spanCount = 0, span = 1; SpanInfo *spanPtr = NULL; while (treeColumn != NULL) { if (TreeColumn_Lock(treeColumn) != TreeColumn_Lock(firstColumn)) break; if (--span == 0) { if (TreeColumn_Visible(treeColumn)) { span = column ? column->span : 1; if (spanPtr == NULL) spanPtr = spans; else spanPtr++; spanPtr->treeColumn = treeColumn; spanPtr->itemColumn = (TreeItemColumn) column; spanPtr->span = 0; spanPtr->width = 0; spanCount++; } else { span = 1; goto next; } } spanPtr->span++; spanPtr->width += TreeColumn_UseWidth(treeColumn); next: ++columnIndex; treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } return spanCount; } typedef int (*TreeItemWalkSpansProc)( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ); /* *---------------------------------------------------------------------- * * TreeItem_WalkSpans -- * * Iterates over the spans of an item and calls a callback routine * for each span of non-zero width. This is used for drawing, * hit-testing and other purposes. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_WalkSpans( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int lock, /* Which columns. */ int x, int y, /* Drawable coordinates of the item. */ int width, int height, /* Total size of the item. */ TreeItemWalkSpansProc proc, /* Callback routine. */ ClientData clientData /* Data passed to callback routine. */ ) { int columnWidth, totalWidth; Column *itemColumn; StyleDrawArgs drawArgs; TreeColumn treeColumn = tree->columnLockNone; int spanCount, spanIndex, columnCount = tree->columnCountVis; SpanInfo staticSpans[STATIC_SIZE], *spans = staticSpans; int area = TREE_AREA_CONTENT; switch (lock) { case COLUMN_LOCK_LEFT: treeColumn = tree->columnLockLeft; columnCount = tree->columnCountVisLeft; area = TREE_AREA_LEFT; break; case COLUMN_LOCK_NONE: break; case COLUMN_LOCK_RIGHT: treeColumn = tree->columnLockRight; columnCount = tree->columnCountVisRight; area = TREE_AREA_RIGHT; break; } if (!Tree_AreaBbox(tree, area, &drawArgs.bounds[0], &drawArgs.bounds[1], &drawArgs.bounds[2], &drawArgs.bounds[3])) { drawArgs.bounds[0] = drawArgs.bounds[1] = drawArgs.bounds[2] = drawArgs.bounds[3] = 0; } STATIC_ALLOC(spans, SpanInfo, columnCount); spanCount = Item_GetSpans(tree, item, treeColumn, spans); drawArgs.tree = tree; drawArgs.drawable = None; totalWidth = 0; for (spanIndex = 0; spanIndex < spanCount; spanIndex++) { treeColumn = spans[spanIndex].treeColumn; itemColumn = (Column *) spans[spanIndex].itemColumn; /* If this is the single visible column, use the provided width which * may be different than the column's width. */ if ((tree->columnCountVis == 1) && (treeColumn == tree->columnVis)) { columnWidth = width; /* More than one column is visible, or this is not the visible * column. */ } else { columnWidth = spans[spanIndex].width; } if (columnWidth <= 0) continue; if (itemColumn != NULL) { drawArgs.state = item->state | itemColumn->cstate; drawArgs.style = itemColumn->style; /* may be NULL */ } else { drawArgs.state = item->state; drawArgs.style = NULL; } if (treeColumn == tree->columnTree) drawArgs.indent = TreeItem_Indent(tree, item); else drawArgs.indent = 0; drawArgs.x = x + totalWidth; drawArgs.y = y; drawArgs.width = columnWidth; drawArgs.height = height; drawArgs.justify = TreeColumn_Justify(treeColumn); if ((*proc)(tree, item, &spans[spanIndex], &drawArgs, clientData)) break; totalWidth += columnWidth; } STATIC_FREE(spans, SpanInfo, columnCount); } /* *---------------------------------------------------------------------- * * SpanWalkProc_Draw -- * * Callback routine to TreeItem_WalkSpans for TreeItem_Draw. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ static int SpanWalkProc_Draw( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { TreeColumn treeColumn = spanPtr->treeColumn; Column *itemColumn = (Column *) spanPtr->itemColumn; int i, x; struct { Drawable drawable; int minX; int maxX; int index; } *data = clientData; /* Draw nothing if the entire span is out-of-bounds. */ if ((drawArgs->x >= data->maxX) || (drawArgs->x + drawArgs->width <= data->minX)) return 0; drawArgs->drawable = data->drawable; /* Draw background colors. */ if (spanPtr->span == 1) { /* Important point: use drawArgs->width since an item's width may * be totally different than tree->columnVis' width. */ ItemDrawBackground(tree, treeColumn, item, itemColumn, drawArgs->drawable, drawArgs->x, drawArgs->y, drawArgs->width, drawArgs->height, data->index); } else { x = drawArgs->x; for (i = 0; i < spanPtr->span; i++) { int columnWidth = TreeColumn_UseWidth(treeColumn); if ((columnWidth > 0) && (x < data->maxX) && (x + columnWidth > data->minX)) { ItemDrawBackground(tree, treeColumn, item, itemColumn, drawArgs->drawable, x, drawArgs->y, columnWidth, drawArgs->height, data->index); } x += columnWidth; treeColumn = TreeColumn_Next(treeColumn); } } if (drawArgs->style != NULL) { StyleDrawArgs drawArgsCopy = *drawArgs; TreeStyle_Draw(&drawArgsCopy); } if (spanPtr->treeColumn == tree->columnTree) { if (tree->showLines) TreeItem_DrawLines(tree, item, drawArgs->x, drawArgs->y, drawArgs->width, drawArgs->height, data->drawable); if (tree->showButtons) TreeItem_DrawButton(tree, item, drawArgs->x, drawArgs->y, drawArgs->width, drawArgs->height, data->drawable); } /* Stop walking if we went past the right edge of the dirty area. */ return drawArgs->x + drawArgs->width >= data->maxX; } /* *---------------------------------------------------------------------- * * TreeItem_Draw -- * * Draws part of an Item. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ void TreeItem_Draw( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int lock, /* Which columns. */ int x, int y, /* Drawable coordinates of the item. */ int width, int height, /* Total size of the item. */ Drawable drawable, /* Where to draw. */ int minX, int maxX, /* Left/right edge that needs to be drawn. */ int index /* Used to select a color from a * tree-column's -itembackground option. */ ) { struct { Drawable drawable; int minX; int maxX; int index; } clientData; clientData.drawable = drawable; clientData.minX = minX; clientData.maxX = maxX; clientData.index = index; TreeItem_WalkSpans(tree, item, lock, x, y, width, height, SpanWalkProc_Draw, (ClientData) &clientData); } /* *---------------------------------------------------------------------- * * TreeItem_DrawLines -- * * Draws horizontal and vertical lines indicating parent-child * relationship in an item. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ void TreeItem_DrawLines( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int x, int y, /* Drawable coordinates of columnTree. */ int width, int height, /* Total size of columnTree. */ Drawable drawable /* Where to draw. */ ) { TreeItem parent, walk; int indent, left, lineLeft, lineTop; int hasPrev, hasNext; int i, vert = 0; indent = TreeItem_Indent(tree, item); /* Left edge of button/line area */ left = x /* + tree->columnTreeLeft */ + indent - tree->useIndent; /* Left edge of vertical line */ lineLeft = left + (tree->useIndent - tree->lineThickness) / 2; /* Top edge of horizontal line */ lineTop = y + (height - tree->lineThickness) / 2; /* NOTE: The next three checks do not call TreeItem_ReallyVisible() * since 'item' is ReallyVisible */ /* Check for ReallyVisible previous sibling */ walk = item->prevSibling; while ((walk != NULL) && !IS_VISIBLE(walk)) walk = walk->prevSibling; hasPrev = (walk != NULL); /* Check for ReallyVisible parent */ if ((item->parent != NULL) && (!IS_ROOT(item->parent) || tree->showRoot)) hasPrev = TRUE; /* Check for ReallyVisible next sibling */ walk = item->nextSibling; while ((walk != NULL) && !IS_VISIBLE(walk)) walk = walk->nextSibling; hasNext = (walk != NULL); /* Option: Don't connect children of root item */ if ((item->parent != NULL) && IS_ROOT(item->parent) && !tree->showRootLines) hasPrev = hasNext = FALSE; /* Vertical line to parent and/or previous/next sibling */ if (hasPrev || hasNext) { int top = y, bottom = y + height; if (!hasPrev) top = lineTop; if (!hasNext) bottom = lineTop + tree->lineThickness; if (tree->lineStyle == LINE_STYLE_DOT) { for (i = 0; i < tree->lineThickness; i++) VDotLine(tree, drawable, tree->lineGC, lineLeft + i, top, bottom); } else XFillRectangle(tree->display, drawable, tree->lineGC, lineLeft, top, tree->lineThickness, bottom - top); /* Don't overlap horizontal line */ vert = tree->lineThickness; } /* Horizontal line to self */ if (hasPrev || hasNext) { if (tree->lineStyle == LINE_STYLE_DOT) { for (i = 0; i < tree->lineThickness; i++) HDotLine(tree, drawable, tree->lineGC, lineLeft + vert, lineTop + i, x /* + tree->columnTreeLeft */ + indent); } else XFillRectangle(tree->display, drawable, tree->lineGC, lineLeft + vert, lineTop, left + tree->useIndent - (lineLeft + vert), tree->lineThickness); } /* Vertical lines from ancestors to their next siblings */ for (parent = item->parent; parent != NULL; parent = parent->parent) { lineLeft -= tree->useIndent; /* Option: Don't connect children of root item */ if ((parent->parent != NULL) && IS_ROOT(parent->parent) && !tree->showRootLines) continue; /* Check for ReallyVisible next sibling */ item = parent->nextSibling; while ((item != NULL) && !IS_VISIBLE(item)) item = item->nextSibling; if (item != NULL) { if (tree->lineStyle == LINE_STYLE_DOT) { for (i = 0; i < tree->lineThickness; i++) VDotLine(tree, drawable, tree->lineGC, lineLeft + i, y, y + height); } else XFillRectangle(tree->display, drawable, tree->lineGC, lineLeft, y, tree->lineThickness, height); } } } /* *---------------------------------------------------------------------- * * TreeItem_DrawButton -- * * Draws the button (if any) in an item. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ void TreeItem_DrawButton( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int x, int y, /* Drawable coordinates of columnTree. */ int width, int height, /* Total size of columnTree. */ Drawable drawable /* Where to draw. */ ) { int indent, left, lineLeft, lineTop; int buttonLeft, buttonTop, w1; int macoffset = 0; Tk_Image image; Pixmap bitmap; if (!HAS_BUTTON(item)) return; if (IS_ROOT(item) && !tree->showRootButton) return; #if defined(MAC_TCL) || defined(MAC_OSX_TK) /* QuickDraw on Mac is offset by one pixel in both x and y. */ macoffset = 1; #endif indent = TreeItem_Indent(tree, item); /* Left edge of button/line area */ left = x /* + tree->columnTreeLeft */ + indent - tree->useIndent; image = PerStateImage_ForState(tree, &tree->buttonImage, item->state, NULL); if (image != NULL) { int imgW, imgH; Tk_SizeOfImage(image, &imgW, &imgH); Tk_RedrawImage(image, 0, 0, imgW, imgH, drawable, left + (tree->useIndent - imgW) / 2, y + (height - imgH) / 2); return; } bitmap = PerStateBitmap_ForState(tree, &tree->buttonBitmap, item->state, NULL); if (bitmap != None) { int bmpW, bmpH; int bx, by; Tk_SizeOfBitmap(tree->display, bitmap, &bmpW, &bmpH); bx = left + (tree->useIndent - bmpW) / 2; by = y + (height - bmpH) / 2; Tree_DrawBitmap(tree, bitmap, drawable, NULL, NULL, 0, 0, (unsigned int) bmpW, (unsigned int) bmpH, bx, by); return; } if (tree->useTheme) { int bw, bh; if (TreeTheme_GetButtonSize(tree, drawable, item->state & STATE_OPEN, &bw, &bh) == TCL_OK) { if (TreeTheme_DrawButton(tree, drawable, item->state & STATE_OPEN, left + (tree->useIndent - bw) / 2, y + (height - bh) / 2, bw, bh) == TCL_OK) { return; } } } w1 = tree->buttonThickness / 2; /* Left edge of vertical line */ /* Make sure this matches TreeItem_DrawLines() */ lineLeft = left + (tree->useIndent - tree->buttonThickness) / 2; /* Top edge of horizontal line */ /* Make sure this matches TreeItem_DrawLines() */ lineTop = y + (height - tree->buttonThickness) / 2; buttonLeft = left + (tree->useIndent - tree->buttonSize) / 2; buttonTop = y + (height - tree->buttonSize) / 2; /* Erase button background */ XFillRectangle(tree->display, drawable, Tk_3DBorderGC(tree->tkwin, tree->border, TK_3D_FLAT_GC), buttonLeft + tree->buttonThickness, buttonTop + tree->buttonThickness, tree->buttonSize - tree->buttonThickness, tree->buttonSize - tree->buttonThickness); /* Draw button outline */ XDrawRectangle(tree->display, drawable, tree->buttonGC, buttonLeft + w1, buttonTop + w1, tree->buttonSize - tree->buttonThickness + macoffset, tree->buttonSize - tree->buttonThickness + macoffset); /* Horizontal '-' */ XFillRectangle(tree->display, drawable, tree->buttonGC, buttonLeft + tree->buttonThickness * 2, lineTop, tree->buttonSize - tree->buttonThickness * 4, tree->buttonThickness); if (!(item->state & STATE_OPEN)) { /* Finish '+' */ XFillRectangle(tree->display, drawable, tree->buttonGC, lineLeft, buttonTop + tree->buttonThickness * 2, tree->buttonThickness, tree->buttonSize - tree->buttonThickness * 4); } } /* *---------------------------------------------------------------------- * * SpanWalkProc_UpdateWindowPositions -- * * Callback routine to TreeItem_WalkSpans for * TreeItem_UpdateWindowPositions. * * Results: * None. * * Side effects: * Windows in window elements may be resized/repositioned. * *---------------------------------------------------------------------- */ static int SpanWalkProc_UpdateWindowPositions( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { StyleDrawArgs drawArgsCopy; int requests; if ((drawArgs->x >= drawArgs->bounds[2]) || (drawArgs->x + drawArgs->width <= drawArgs->bounds[0]) || (drawArgs->style == NULL)) return 0; TreeDisplay_GetReadyForTrouble(tree, &requests); drawArgsCopy = *drawArgs; TreeStyle_UpdateWindowPositions(&drawArgsCopy); if (TreeDisplay_WasThereTrouble(tree, requests)) return 1; /* Stop walking if we went past the right edge of the display area. */ return drawArgs->x + drawArgs->width >= drawArgs->bounds[2]; } /* *---------------------------------------------------------------------- * * TreeItem_UpdateWindowPositions -- * * Updates the geometry of any on-screen window elements. Called * by the display code when an item was possibly scrolled. * * Results: * None. * * Side effects: * Windows in window elements may be resized/repositioned. * *---------------------------------------------------------------------- */ void TreeItem_UpdateWindowPositions( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int lock, /* Columns we care about. */ int x, int y, /* Window coordinates of the item. */ int width, int height /* Total size of the item. */ ) { TreeItem_WalkSpans(tree, item, lock, x, y, width, height, SpanWalkProc_UpdateWindowPositions, (ClientData) NULL); } /* *---------------------------------------------------------------------- * * TreeItem_OnScreen -- * * Called by the display code when the item becomes visible * (i.e., actually displayed) or hidden. * * Results: * None. * * Side effects: * Windows in window elements may be mapped/unmapped. * *---------------------------------------------------------------------- */ void TreeItem_OnScreen( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int onScreen /* TRUE if item is displayed. */ ) { #if 0 Column *column = item->columns; while (column != NULL) { if (column->style != NULL) { TreeStyle_OnScreen(tree, column->style, onScreen); } column = column->next; } #endif } /* *---------------------------------------------------------------------- * * TreeItem_ReallyVisible -- * * Return whether the given Item could be displayed. * * Results: * TRUE if the item's -visible is TRUE, all of its ancestors' * -visible options are TRUE, and all of its ancestors are open. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_ReallyVisible( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { #if 0 Tree_UpdateItemIndex(tree); return item->indexVis != -1; #else if (!tree->updateIndex) return item->indexVis != -1; if (!IS_VISIBLE(item)) return 0; if (item->parent == NULL) return IS_ROOT(item) ? tree->showRoot : 0; if (IS_ROOT(item->parent)) { if (!IS_VISIBLE(item->parent)) return 0; if (!tree->showRoot) return 1; if (!(item->parent->state & STATE_OPEN)) return 0; } if (!IS_VISIBLE(item->parent) || !(item->parent->state & STATE_OPEN)) return 0; return TreeItem_ReallyVisible(tree, item->parent); #endif } /* *---------------------------------------------------------------------- * * TreeItem_RootAncestor -- * * Return the toplevel ancestor of an Item. * * Results: * Returns the root, or an orphan ancestor, or the given Item. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_RootAncestor( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { while (item->parent != NULL) item = item->parent; return item; } /* *---------------------------------------------------------------------- * * TreeItem_IsAncestor -- * * Determine if one Item is the ancestor of another. * * Results: * TRUE if item1 is an ancestor of item2. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_IsAncestor( TreeCtrl *tree, /* Widget info. */ TreeItem item1, /* Possible ancestor. */ TreeItem item2 /* Item to check ancestry of. */ ) { if (item1 == item2) return 0; while (item2 && item2 != item1) item2 = item2->parent; return item2 != NULL; } /* *---------------------------------------------------------------------- * * TreeItem_ToObj -- * * Convert an Item to a Tcl_Obj. * * Results: * A new Tcl_Obj representing the Item. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ Tcl_Obj *TreeItem_ToObj( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { if (tree->itemPrefixLen) { char buf[100 + TCL_INTEGER_SPACE]; (void) sprintf(buf, "%s%d", tree->itemPrefix, item->id); return Tcl_NewStringObj(buf, -1); } return Tcl_NewIntObj(item->id); } /* *---------------------------------------------------------------------- * * Item_Configure -- * * This procedure is called to process an objc/objv list, plus * the Tk option database, in order to configure (or reconfigure) * an Item. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then the interp's result contains an error message. * * Side effects: * Configuration information gets set for item; old resources get * freed, if there were any. * *---------------------------------------------------------------------- */ static int Item_Configure( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to configure. */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Array of arguments */ ) { Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int mask; int lastVisible = IS_VISIBLE(item); for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) item, tree->itemOptionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* xxx */ Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* xxx */ Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } if (mask & ITEM_CONF_SIZE) { Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } if (mask & ITEM_CONF_BUTTON) if (tree->columnTree != NULL) Tree_InvalidateItemDInfo(tree, tree->columnTree, item, NULL); if ((mask & ITEM_CONF_VISIBLE) && (IS_VISIBLE(item) != lastVisible)) { /* May change the width of any column */ Tree_InvalidateColumnWidth(tree, NULL); /* If this is the last child, redraw the lines of the previous * sibling and all of its descendants because the line from * the previous sibling to us is appearing/disappearing */ if ((item->prevSibling != NULL) && (item->nextSibling == NULL) && tree->showLines && (tree->columnTree != NULL)) { TreeItem last = item->prevSibling; while (last->lastChild != NULL) last = last->lastChild; Tree_InvalidateItemDInfo(tree, tree->columnTree, item->prevSibling, last); } tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES | DINFO_REDO_SELECTION); } return TCL_OK; } /* *---------------------------------------------------------------------- * * ItemCreateCmd -- * * This procedure is invoked to process the [item create] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemCreateCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *optionNames[] = { "-button", "-count", "-height", "-nextsibling", "-open", "-parent", "-prevsibling", "-returnid", "-tags", "-visible", (char *) NULL }; enum { OPT_BUTTON, OPT_COUNT, OPT_HEIGHT, OPT_NEXTSIBLING, OPT_OPEN, OPT_PARENT, OPT_PREVSIBLING, OPT_RETURNID, OPT_TAGS, OPT_VISIBLE }; int index, i, count = 1, button = 0, returnId = 1, open = 1, visible = 1; int height = 0; TreeItem item, parent = NULL, prevSibling = NULL, nextSibling = NULL; TreeItem head = NULL, tail = NULL; Tcl_Obj *listObj = NULL, *tagsObj = NULL; TagInfo *tagInfo = NULL; TreeColumn treeColumn; for (i = 3; i < objc; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], optionNames, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (i + 1 == objc) { FormatResult(interp, "missing value for \"%s\" option", optionNames[index]); return TCL_ERROR; } switch (index) { case OPT_BUTTON: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &button) != TCL_OK) { return TCL_ERROR; } break; case OPT_COUNT: if (Tcl_GetIntFromObj(interp, objv[i + 1], &count) != TCL_OK) return TCL_ERROR; if (count <= 0) { FormatResult(interp, "bad count \"%d\": must be > 0", count); } break; case OPT_HEIGHT: if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &height) != TCL_OK) return TCL_ERROR; if (height < 0) { FormatResult(interp, "bad screen distance \"%s\": must be > 0", Tcl_GetString(objv[i + 1])); } break; case OPT_NEXTSIBLING: if (TreeItem_FromObj(tree, objv[i + 1], &nextSibling, IFO_NOT_NULL | IFO_NOT_ROOT | IFO_NOT_ORPHAN) != TCL_OK) { return TCL_ERROR; } parent = prevSibling = NULL; break; case OPT_OPEN: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &open) != TCL_OK) { return TCL_ERROR; } break; case OPT_PARENT: if (TreeItem_FromObj(tree, objv[i + 1], &parent, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } prevSibling = nextSibling = NULL; break; case OPT_PREVSIBLING: if (TreeItem_FromObj(tree, objv[i + 1], &prevSibling, IFO_NOT_NULL | IFO_NOT_ROOT | IFO_NOT_ORPHAN) != TCL_OK) { return TCL_ERROR; } parent = nextSibling = NULL; break; case OPT_RETURNID: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &returnId) != TCL_OK) { return TCL_ERROR; } break; case OPT_TAGS: tagsObj = objv[i + 1]; break; case OPT_VISIBLE: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &visible) != TCL_OK) { return TCL_ERROR; } break; } } /* Do it here so I don't have to free it above if an error occurs. */ if (tagsObj != NULL) { if (TagInfo_FromObj(tree, tagsObj, &tagInfo) != TCL_OK) return TCL_ERROR; } if (returnId) listObj = Tcl_NewListObj(0, NULL); /* Don't allow non-deleted items to become children of a * deleted item. */ if ((parent && IS_DELETED(parent)) || (prevSibling && IS_DELETED(prevSibling->parent)) || (nextSibling && IS_DELETED(nextSibling->parent))) parent = prevSibling = nextSibling = NULL; for (i = 0; i < count; i++) { item = Item_Alloc(tree); if (button) item->flags |= ITEM_FLAG_BUTTON; else item->flags &= ~ITEM_FLAG_BUTTON; if (visible) item->flags |= ITEM_FLAG_VISIBLE; else item->flags &= ~ITEM_FLAG_VISIBLE; if (open) item->state |= STATE_OPEN; else item->state &= ~STATE_OPEN; item->fixedHeight = height; /* Apply each column's -itemstyle option. */ for (treeColumn = tree->columns; treeColumn != NULL; treeColumn = TreeColumn_Next(treeColumn)) { TreeStyle style = TreeColumn_ItemStyle(treeColumn); if (style != NULL) { Column *column = Item_CreateColumn(tree, item, TreeColumn_Index(treeColumn), NULL); column->style = TreeStyle_NewInstance(tree, style); } } #ifdef DEPRECATED /* Apply default styles */ if (tree->defaultStyle.numStyles) { int i, n = MIN(tree->columnCount, tree->defaultStyle.numStyles); for (i = 0; i < n; i++) { Column *column = Item_CreateColumn(tree, item, i, NULL); if (column->style != NULL) continue; if (tree->defaultStyle.styles[i] != NULL) { column->style = TreeStyle_NewInstance(tree, tree->defaultStyle.styles[i]); } } } #endif /* DEPRECATED */ if (tagInfo != NULL) { if (count == 1) { item->tagInfo = tagInfo; tagInfo = NULL; } else { item->tagInfo = TagInfo_Copy(tree, tagInfo); } } /* Link the new items together as siblings */ if (parent || prevSibling || nextSibling) { if (head == NULL) head = item; if (tail != NULL) { tail->nextSibling = item; item->prevSibling = tail; } tail = item; } if (returnId) Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); } if (parent != NULL) { head->prevSibling = parent->lastChild; if (parent->lastChild != NULL) parent->lastChild->nextSibling = head; else parent->firstChild = head; parent->lastChild = tail; } else if (prevSibling != NULL) { parent = prevSibling->parent; if (prevSibling->nextSibling != NULL) prevSibling->nextSibling->prevSibling = tail; else parent->lastChild = tail; head->prevSibling = prevSibling; tail->nextSibling = prevSibling->nextSibling; prevSibling->nextSibling = head; } else if (nextSibling != NULL) { parent = nextSibling->parent; if (nextSibling->prevSibling != NULL) nextSibling->prevSibling->nextSibling = head; else parent->firstChild = head; head->prevSibling = nextSibling->prevSibling; tail->nextSibling = nextSibling; nextSibling->prevSibling = tail; } if (parent != NULL) { for (item = head; item != NULL; item = item->nextSibling) { item->parent = parent; item->depth = parent->depth + 1; } parent->numChildren += count; TreeItem_AddToParent(tree, head); } TagInfo_Free(tree, tagInfo); if (returnId) Tcl_SetObjResult(interp, listObj); return TCL_OK; } /* *---------------------------------------------------------------------- * * NoStyleMsg -- * * Utility to set the interpreter result with a message indicating * a Column has no assigned style. * * Results: * None. * * Side effects: * Interpreter result is changed. * *---------------------------------------------------------------------- */ static void NoStyleMsg( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ int columnIndex /* 0-based index of the column that * has no style. */ ) { FormatResult(tree->interp, "item %s%d column %s%d has no style", tree->itemPrefix, item->id, tree->columnPrefix, TreeColumn_GetID(Tree_FindColumn(tree, columnIndex))); } /* *---------------------------------------------------------------------- * * ItemElementCmd -- * * This procedure is invoked to process the [item element] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemElementCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandNames[] = { #ifdef DEPRECATED "actual", #endif "cget", "configure", "perstate", (char *) NULL }; enum { #ifdef DEPRECATED COMMAND_ACTUAL, #endif COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_PERSTATE }; int index; int columnIndex; Column *column; TreeItemList itemList; TreeItem item; int flags = IFO_NOT_NULL; int result = TCL_OK; if (objc < 7) { Tcl_WrongNumArgs(interp, 3, objv, "command item column element ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) return TCL_ERROR; /* * [configure] without an option-value pair can operate on a single item * only. [cget] and [perstate] only operate on a single item. */ if ((index != COMMAND_CONFIGURE) || (objc < 9)) flags |= IFO_NOT_MANY; if (TreeItemList_FromObj(tree, objv[4], &itemList, flags) != TCL_OK) return TCL_ERROR; item = TreeItemList_Nth(&itemList, 0); switch (index) { /* T item element perstate I C E option ?stateList? */ #ifdef DEPRECATED case COMMAND_ACTUAL: #endif case COMMAND_PERSTATE: { int state; if (objc < 8 || objc > 9) { Tcl_WrongNumArgs(tree->interp, 4, objv, "item column element option ?stateList?"); result = TCL_ERROR; break; } if (Item_FindColumnFromObj(tree, item, objv[5], &column, &columnIndex) != TCL_OK) { result = TCL_ERROR; break; } if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; break; } state = item->state | column->cstate; if (objc == 9) { int states[3]; if (Tree_StateFromListObj(tree, objv[8], states, SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) { result = TCL_ERROR; break; } state = states[STATE_OP_ON]; } result = TreeStyle_ElementActual(tree, column->style, state, objv[6], objv[7]); break; } /* T item element cget I C E option */ case COMMAND_CGET: { if (objc != 8) { Tcl_WrongNumArgs(tree->interp, 4, objv, "item column element option"); result = TCL_ERROR; break; } if (Item_FindColumnFromObj(tree, item, objv[5], &column, &columnIndex) != TCL_OK) { result = TCL_ERROR; break; } if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; break; } result = TreeStyle_ElementCget(tree, item, (TreeItemColumn) column, column->style, objv[6], objv[7]); break; } /* T item element configure I C E ... */ case COMMAND_CONFIGURE: { struct columnObj { TreeColumnList columns; int isColumn; int numArgs; } staticCO[STATIC_SIZE], *co = staticCO; int i, index, indexElem, prevColumn; ItemForEach iter; /* If no option-value pair is given, we can't specify more than * one column. */ flags = CFO_NOT_NULL | CFO_NOT_TAIL; if (objc < 9) flags |= CFO_NOT_MANY; STATIC_ALLOC(co, struct columnObj, objc); for (i = 5; i < objc; i++) { co[i].isColumn = FALSE; co[i].numArgs = -1; } indexElem = 6; /* Get the first column(s) */ i = indexElem - 1; if (TreeColumnList_FromObj(tree, objv[i], &co[i].columns, flags) != TCL_OK) { result = TCL_ERROR; break; } co[i].isColumn = TRUE; prevColumn = i; while (1) { int numArgs = 0; char breakChar = '\0'; /* Look for a + or , */ for (index = indexElem + 1; index < objc; index++) { if (numArgs % 2 == 0) { int length; char *s = Tcl_GetStringFromObj(objv[index], &length); if ((length == 1) && ((s[0] == '+') || (s[0] == ','))) { breakChar = s[0]; break; } } numArgs++; } /* Require at least one option-value pair if more than one * element is specified. */ if ((breakChar || indexElem != 6) && (numArgs < 2)) { FormatResult(interp, "missing option-value pair after element \"%s\"", Tcl_GetString(objv[indexElem])); result = TCL_ERROR; goto doneCONF; } co[indexElem].numArgs = numArgs; if (!breakChar) break; if (index == objc - 1) { FormatResult(interp, "missing %s after \"%c\"", (breakChar == '+') ? "element name" : "column", breakChar); result = TCL_ERROR; goto doneCONF; } /* + indicates start of another element */ if (breakChar == '+') { indexElem = index + 1; } /* , indicates start of another column */ else if (breakChar == ',') { co[prevColumn].numArgs = index - prevColumn; if (TreeColumnList_FromObj(tree, objv[index + 1], &co[index + 1].columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneCONF; } co[index + 1].isColumn = TRUE; prevColumn = index + 1; indexElem = index + 2; if (indexElem == objc) { FormatResult(interp, "missing element name after column \"%s\"", Tcl_GetString(objv[index + 1])); result = TCL_ERROR; goto doneCONF; } } } co[prevColumn].numArgs = index - prevColumn; ITEM_FOR_EACH(item, &itemList, NULL, &iter) { /* T item element configure I C E option value \ * + E option value , C E option value */ int iMask = 0; /* co[index].numArgs is the number of arguments from the C * to the next separator (but not including that separator). */ for (index = 5; index < objc; index += co[index].numArgs + 1) { ColumnForEach citer; TreeColumn treeColumn; if (!co[index].isColumn) panic("isColumn == FALSE"); COLUMN_FOR_EACH(treeColumn, &co[index].columns, NULL, &citer) { int columnIndex, cMask = 0; columnIndex = TreeColumn_Index(treeColumn); column = Item_FindColumn(tree, item, columnIndex); if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; break; } indexElem = index + 1; /* Do each element in this column */ while (1) { int eMask, index2; if (co[indexElem].numArgs == -1) panic("indexElem=%d (%s) objc=%d numArgs == -1", indexElem, Tcl_GetString(objv[indexElem]), objc); result = TreeStyle_ElementConfigure(tree, item, (TreeItemColumn) column, column->style, objv[indexElem], co[indexElem].numArgs, (Tcl_Obj **) objv + indexElem + 1, &eMask); if (result != TCL_OK) break; cMask |= eMask; /* co[indexElem].numArgs is the number of * option-value arguments after the element. */ index2 = indexElem + co[indexElem].numArgs; if (index2 == objc - 1) break; /* Skip the '+' or ',' */ index2 += 2; if (co[index2].isColumn) break; indexElem = index2; } if (cMask & CS_LAYOUT) { TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_InvalidateColumnWidth(tree, treeColumn); } else if (cMask & CS_DISPLAY) { Tree_InvalidateItemDInfo(tree, treeColumn, item, NULL); } iMask |= cMask; if (result != TCL_OK) break; } if (result != TCL_OK) break; } if (iMask & CS_LAYOUT) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } else if (iMask & CS_DISPLAY) { } if (result != TCL_OK) break; } doneCONF: for (i = 5; i < objc; i++) { if (co[i].isColumn) TreeColumnList_Free(&co[i].columns); } STATIC_FREE(co, struct columnObj, objc); break; } } TreeItemList_Free(&itemList); return result; } /* *---------------------------------------------------------------------- * * ItemStyleCmd -- * * This procedure is invoked to process the [item style] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemStyleCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandNames[] = { "elements", "map", "set", (char *) NULL }; enum { COMMAND_ELEMENTS, COMMAND_MAP, COMMAND_SET }; int index; TreeItemList itemList; TreeItem item; int flags = IFO_NOT_NULL; int result = TCL_OK; if (objc < 5) { Tcl_WrongNumArgs(interp, 3, objv, "command item ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } /* [style elements] only works on a single item. * [style set] only works on a single item without a column-style pair. */ if ((index == COMMAND_ELEMENTS) || (index == COMMAND_SET && objc < 7)) flags |= IFO_NOT_MANY; if (TreeItemList_FromObj(tree, objv[4], &itemList, flags) != TCL_OK) { return TCL_ERROR; } item = TreeItemList_Nth(&itemList, 0); switch (index) { /* T item style elements I C */ case COMMAND_ELEMENTS: { Column *column; int columnIndex; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "item column"); result = TCL_ERROR; break; } if (Item_FindColumnFromObj(tree, item, objv[5], &column, &columnIndex) != TCL_OK) { result = TCL_ERROR; break; } if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; break; } TreeStyle_ListElements(tree, column->style); break; } /* T item style map I C S map */ case COMMAND_MAP: { TreeStyle style; TreeColumnList columns; TreeColumn treeColumn; Column *column; int columnIndex; int objcM; Tcl_Obj **objvM; ItemForEach iter; ColumnForEach citer; if (objc != 8) { Tcl_WrongNumArgs(interp, 4, objv, "item column style map"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[5], &columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; break; } if (TreeStyle_FromObj(tree, objv[6], &style) != TCL_OK) { result = TCL_ERROR; goto doneMAP; } if (Tcl_ListObjGetElements(interp, objv[7], &objcM, &objvM) != TCL_OK) { result = TCL_ERROR; goto doneMAP; } if (objcM & 1) { FormatResult(interp, "list must contain even number of elements"); result = TCL_ERROR; goto doneMAP; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { COLUMN_FOR_EACH(treeColumn, &columns, NULL, &citer) { columnIndex = TreeColumn_Index(treeColumn); column = Item_CreateColumn(tree, item, columnIndex, NULL); if (column->style != NULL) { if (TreeStyle_Remap(tree, column->style, style, objcM, objvM) != TCL_OK) { result = TCL_ERROR; break; } } else { column->style = TreeStyle_NewInstance(tree, style); } TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_InvalidateColumnWidth(tree, treeColumn); } TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); if (result != TCL_OK) break; } Tree_DInfoChanged(tree, DINFO_REDO_RANGES); doneMAP: TreeColumnList_Free(&columns); break; } /* T item style set I ?C? ?S? ?C S ...?*/ case COMMAND_SET: { struct columnStyle { TreeColumnList columns; TreeStyle style; }; struct columnStyle staticCS[STATIC_SIZE], *cs = staticCS; TreeColumn treeColumn; Column *column; int i, count = 0, length, changed = FALSE, changedI; ItemForEach iter; ColumnForEach citer; if (objc < 5) { Tcl_WrongNumArgs(interp, 4, objv, "item ?column? ?style? ?column style ...?"); return TCL_ERROR; } /* Return list of styles. */ if (objc == 5) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); treeColumn = tree->columns; column = item->columns; while (treeColumn != NULL) { if ((column != NULL) && (column->style != NULL)) Tcl_ListObjAppendElement(interp, listObj, TreeStyle_ToObj(TreeStyle_GetMaster( tree, column->style))); else Tcl_ListObjAppendElement(interp, listObj, Tcl_NewObj()); treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } Tcl_SetObjResult(interp, listObj); break; } /* Return style in one column. */ if (objc == 6) { if (Item_FindColumnFromObj(tree, item, objv[5], &column, NULL) != TCL_OK) return TCL_ERROR; if ((column != NULL) && (column->style != NULL)) Tcl_SetObjResult(interp, TreeStyle_ToObj( TreeStyle_GetMaster(tree, column->style))); break; } /* Get column/style pairs. */ STATIC_ALLOC(cs, struct columnStyle, objc / 2); for (i = 5; i < objc; i += 2) { if (TreeColumnList_FromObj(tree, objv[i], &cs[count].columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneSET; } if (i + 1 == objc) { FormatResult(interp, "missing style for column \"%s\"", Tcl_GetString(objv[i])); result = TCL_ERROR; goto doneSET; } (void) Tcl_GetStringFromObj(objv[i + 1], &length); if (length == 0) { cs[count].style = NULL; } else { if (TreeStyle_FromObj(tree, objv[i + 1], &cs[count].style) != TCL_OK) { result = TCL_ERROR; goto doneSET; } } count++; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { changedI = FALSE; for (i = 0; i < count; i++) { COLUMN_FOR_EACH(treeColumn, &cs[i].columns, NULL, &citer) { if (cs[i].style == NULL) { column = Item_FindColumn(tree, item, TreeColumn_Index(treeColumn)); if (column == NULL || column->style == NULL) continue; TreeItemColumn_ForgetStyle(tree, (TreeItemColumn) column); } else { column = Item_CreateColumn(tree, item, TreeColumn_Index(treeColumn), NULL); if (column->style != NULL) { if (TreeStyle_GetMaster(tree, column->style) == cs[i].style) continue; TreeItemColumn_ForgetStyle(tree, (TreeItemColumn) column); } column->style = TreeStyle_NewInstance(tree, cs[i].style); } TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_InvalidateColumnWidth(tree, treeColumn); changedI = TRUE; } if (changedI) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); changed = TRUE; } } } if (changed) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); doneSET: for (i = 0; i < count; i++) { TreeColumnList_Free(&cs[i].columns); } STATIC_FREE(cs, struct columnStyle, objc / 2); break; } } TreeItemList_Free(&itemList); return result; } /* one per column per SortItem */ struct SortItem1 { long longValue; double doubleValue; char *string; }; /* one per Item */ struct SortItem { TreeItem item; struct SortItem1 *item1; Tcl_Obj *obj; /* TreeItem_ToObj() */ }; typedef struct SortData SortData; /* Used to process -element option */ struct SortElement { TreeStyle style; TreeElement elem; int elemIndex; }; /* One per TreeColumn */ struct SortColumn { int (*proc)(SortData *, struct SortItem *, struct SortItem *, int); int sortBy; int column; int order; Tcl_Obj *command; struct SortElement elems[20]; int elemCount; }; /* Data for sort as a whole */ struct SortData { TreeCtrl *tree; struct SortItem *items; struct SortItem1 *item1s; /* SortItem.item1 points in here */ #define MAX_SORT_COLUMNS 40 struct SortColumn columns[MAX_SORT_COLUMNS]; int columnCount; /* max number of columns to compare */ int result; }; /* from Tcl 8.4.0 */ static int DictionaryCompare( char *left, char *right ) { Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower; int diff, zeros; int secondaryDiff = 0; while (1) { if (isdigit(UCHAR(*right)) && isdigit(UCHAR(*left))) { /* INTL: digit */ /* * There are decimal numbers embedded in the two * strings. Compare them as numbers, rather than * strings. If one number has more leading zeros than * the other, the number with more leading zeros sorts * later, but only as a secondary choice. */ zeros = 0; while ((*right == '0') && (isdigit(UCHAR(right[1])))) { right++; zeros--; } while ((*left == '0') && (isdigit(UCHAR(left[1])))) { left++; zeros++; } if (secondaryDiff == 0) { secondaryDiff = zeros; } /* * The code below compares the numbers in the two * strings without ever converting them to integers. It * does this by first comparing the lengths of the * numbers and then comparing the digit values. */ diff = 0; while (1) { if (diff == 0) { diff = UCHAR(*left) - UCHAR(*right); } right++; left++; if (!isdigit(UCHAR(*right))) { /* INTL: digit */ if (isdigit(UCHAR(*left))) { /* INTL: digit */ return 1; } else { /* * The two numbers have the same length. See * if their values are different. */ if (diff != 0) { return diff; } break; } } else if (!isdigit(UCHAR(*left))) { /* INTL: digit */ return -1; } } continue; } /* * Convert character to Unicode for comparison purposes. If either * string is at the terminating null, do a byte-wise comparison and * bail out immediately. */ if ((*left != '\0') && (*right != '\0')) { left += Tcl_UtfToUniChar(left, &uniLeft); right += Tcl_UtfToUniChar(right, &uniRight); /* * Convert both chars to lower for the comparison, because * dictionary sorts are case insensitve. Covert to lower, not * upper, so chars between Z and a will sort before A (where most * other interesting punctuations occur) */ uniLeftLower = Tcl_UniCharToLower(uniLeft); uniRightLower = Tcl_UniCharToLower(uniRight); } else { diff = UCHAR(*left) - UCHAR(*right); break; } diff = uniLeftLower - uniRightLower; if (diff) { return diff; } else if (secondaryDiff == 0) { if (Tcl_UniCharIsUpper(uniLeft) && Tcl_UniCharIsLower(uniRight)) { secondaryDiff = -1; } else if (Tcl_UniCharIsUpper(uniRight) && Tcl_UniCharIsLower(uniLeft)) { secondaryDiff = 1; } } } if (diff == 0) { diff = secondaryDiff; } return diff; } static int CompareAscii( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { char *left = a->item1[n].string; char *right = b->item1[n].string; /* make sure to handle case where no string value has been set */ if (left == NULL) { return ((right == NULL) ? 0 : (0 - UCHAR(*right))); } else if (right == NULL) { return UCHAR(*left); } else { return strcmp(left, right); } } static int CompareDict( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { char *left = a->item1[n].string; char *right = b->item1[n].string; /* make sure to handle case where no string value has been set */ if (left == NULL) { return ((right == NULL) ? 0 : (0 - UCHAR(*right))); } else if (right == NULL) { return UCHAR(*left); } else { return DictionaryCompare(left, right); } } static int CompareDouble( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { return (a->item1[n].doubleValue < b->item1[n].doubleValue) ? -1 : ((a->item1[n].doubleValue == b->item1[n].doubleValue) ? 0 : 1); } static int CompareLong( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { return (a->item1[n].longValue < b->item1[n].longValue) ? -1 : ((a->item1[n].longValue == b->item1[n].longValue) ? 0 : 1); } static int CompareCmd( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { Tcl_Interp *interp = sortData->tree->interp; Tcl_Obj **objv, *paramObjv[2]; int objc, v; paramObjv[0] = a->obj; paramObjv[1] = b->obj; Tcl_ListObjLength(interp, sortData->columns[n].command, &objc); Tcl_ListObjReplace(interp, sortData->columns[n].command, objc - 2, 2, 2, paramObjv); Tcl_ListObjGetElements(interp, sortData->columns[n].command, &objc, &objv); sortData->result = Tcl_EvalObjv(interp, objc, objv, 0); if (sortData->result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (evaluating item sort -command)"); return 0; } sortData->result = Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &v); if (sortData->result != TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "-command returned non-numeric result", -1); return 0; } return v; } static int CompareProc( SortData *sortData, struct SortItem *a, struct SortItem *b ) { int i, v; if (a->item == b->item) return 0; for (i = 0; i < sortData->columnCount; i++) { v = (*sortData->columns[i].proc)(sortData, a, b, i); /* -command returned error */ if (sortData->result != TCL_OK) return 0; if (v != 0) { if (i && (sortData->columns[i].order != sortData->columns[0].order)) v *= -1; return v; } } return 0; } /* BEGIN custom quicksort() */ static int find_pivot( SortData *sortData, struct SortItem *left, struct SortItem *right, struct SortItem *pivot ) { struct SortItem *a, *b, *c, *p, *tmp; int v; a = left; b = (left + (right - left) / 2); c = right; /* Arrange a <= b <= c. */ v = CompareProc(sortData, a, b); if (sortData->result != TCL_OK) return 0; if (v > 0) { tmp = a; a = b; b = tmp; } v = CompareProc(sortData, a, c); if (sortData->result != TCL_OK) return 0; if (v > 0) { tmp = a; a = c; c = tmp; } v = CompareProc(sortData, b, c); if (sortData->result != TCL_OK) return 0; if (v > 0) { tmp = b; b = c; c = tmp; } /* if (a < b) pivot = b */ v = CompareProc(sortData, a, b); if (sortData->result != TCL_OK) return 0; if (v < 0) { (*pivot) = *b; return 1; } /* if (b < c) pivot = c */ v = CompareProc(sortData, b, c); if (sortData->result != TCL_OK) return 0; if (v < 0) { (*pivot) = *c; return 1; } for (p = left + 1; p <= right; p++) { int v = CompareProc(sortData, p, left); if (sortData->result != TCL_OK) return 0; if (v != 0) { (*pivot) = (v < 0) ? *left : *p; return 1; } } return 0; } /* If the user provides a -command which does not properly compare two * elements, quicksort may go into an infinite loop or access illegal memory. * This #define indicates parts of the code which are not part of a normal * quicksort, but are present to detect the aforementioned bugs. */ #define BUGGY_COMMAND static struct SortItem * partition( SortData *sortData, struct SortItem *left, struct SortItem *right, struct SortItem *pivot ) { int v; #ifdef BUGGY_COMMAND struct SortItem *min = left, *max = right; #endif while (left <= right) { /* while (*left < *pivot) ++left; */ while (1) { v = CompareProc(sortData, left, pivot); if (sortData->result != TCL_OK) return NULL; if (v >= 0) break; #ifdef BUGGY_COMMAND /* If -command always returns < 0, 'left' becomes invalid */ if (left == max) goto buggy; #endif left++; } /* while (*right >= *pivot) --right; */ while (1) { v = CompareProc(sortData, right, pivot); if (sortData->result != TCL_OK) return NULL; if (v < 0) break; #ifdef BUGGY_COMMAND /* If -command always returns >= 0, 'right' becomes invalid */ if (right == min) goto buggy; #endif right--; } if (left < right) { struct SortItem tmp = *left; *left = *right; *right = tmp; left++; right--; } } return left; #ifdef BUGGY_COMMAND buggy: FormatResult(sortData->tree->interp, "buggy item sort -command detected"); sortData->result = TCL_ERROR; return NULL; #endif } static void quicksort( SortData *sortData, struct SortItem *left, struct SortItem *right ) { struct SortItem *p, pivot; if (sortData->result != TCL_OK) return; if (left == right) return; /* FIXME: switch to insertion sort or similar when the number of * elements is small. */ if (find_pivot(sortData, left, right, &pivot) == 1) { p = partition(sortData, left, right, &pivot); quicksort(sortData, left, p - 1); quicksort(sortData, p, right); } } /* END custom quicksort() */ /* *---------------------------------------------------------------------- * * ItemSortCmd -- * * This procedure is invoked to process the [item sort] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemSortCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; TreeItem item, first, last, walk, lastChild; Column *column; int i, j, count, elemIndex, index, indexF = 0, indexL = 0; int sawColumn = FALSE, sawCmd = FALSE; static int (*sortProc[5])(SortData *, struct SortItem *, struct SortItem *, int) = { CompareAscii, CompareDict, CompareDouble, CompareLong, CompareCmd }; SortData sortData; TreeColumn treeColumn; struct SortElement *elemPtr; int notReally = FALSE; int result = TCL_OK; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "item ?option ...?"); return TCL_ERROR; } if (TreeItem_FromObj(tree, objv[3], &item, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; /* If the item has no children, then nothing is done and no error * is generated. */ if (item->numChildren < 1) return TCL_OK; /* Defaults: sort ascii strings in column 0 only */ sortData.tree = tree; sortData.columnCount = 1; sortData.columns[0].column = 0; sortData.columns[0].sortBy = SORT_ASCII; sortData.columns[0].order = 1; sortData.columns[0].elemCount = 0; sortData.result = TCL_OK; first = item->firstChild; last = item->lastChild; for (i = 4; i < objc; ) { static CONST84 char *optionName[] = { "-ascii", "-column", "-command", "-decreasing", "-dictionary", "-element", "-first", "-increasing", "-integer", "-last", "-notreally", "-real", NULL }; int numArgs[] = { 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1 }; enum { OPT_ASCII, OPT_COLUMN, OPT_COMMAND, OPT_DECREASING, OPT_DICT, OPT_ELEMENT, OPT_FIRST, OPT_INCREASING, OPT_INTEGER, OPT_LAST, OPT_NOT_REALLY, OPT_REAL }; if (Tcl_GetIndexFromObj(interp, objv[i], optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; if (objc - i < numArgs[index]) { FormatResult(interp, "missing value for \"%s\" option", optionName[index]); return TCL_ERROR; } switch (index) { case OPT_ASCII: sortData.columns[sortData.columnCount - 1].sortBy = SORT_ASCII; break; case OPT_COLUMN: if (TreeColumn_FromObj(tree, objv[i + 1], &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; /* The first -column we see is the first column we compare */ if (sawColumn) { if (sortData.columnCount + 1 > MAX_SORT_COLUMNS) { FormatResult(interp, "can't compare more than %d columns", MAX_SORT_COLUMNS); return TCL_ERROR; } sortData.columnCount++; /* Defaults for this column */ sortData.columns[sortData.columnCount - 1].sortBy = SORT_ASCII; sortData.columns[sortData.columnCount - 1].order = 1; sortData.columns[sortData.columnCount - 1].elemCount = 0; } sortData.columns[sortData.columnCount - 1].column = TreeColumn_Index(treeColumn); sawColumn = TRUE; break; case OPT_COMMAND: sortData.columns[sortData.columnCount - 1].command = objv[i + 1]; sortData.columns[sortData.columnCount - 1].sortBy = SORT_COMMAND; sawCmd = TRUE; break; case OPT_DECREASING: sortData.columns[sortData.columnCount - 1].order = 0; break; case OPT_DICT: sortData.columns[sortData.columnCount - 1].sortBy = SORT_DICT; break; case OPT_ELEMENT: { int listObjc; Tcl_Obj **listObjv; if (Tcl_ListObjGetElements(interp, objv[i + 1], &listObjc, &listObjv) != TCL_OK) return TCL_ERROR; elemPtr = sortData.columns[sortData.columnCount - 1].elems; sortData.columns[sortData.columnCount - 1].elemCount = 0; if (listObjc == 0) { } else if (listObjc == 1) { if (TreeElement_FromObj(tree, listObjv[0], &elemPtr->elem) != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } if (!TreeElement_IsType(tree, elemPtr->elem, "text")) { FormatResult(interp, "element %s is not of type \"text\"", Tcl_GetString(listObjv[0])); Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } elemPtr->style = NULL; elemPtr->elemIndex = -1; sortData.columns[sortData.columnCount - 1].elemCount++; } else { if (listObjc & 1) { FormatResult(interp, "list must have even number of elements"); Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } for (j = 0; j < listObjc; j += 2) { if ((TreeStyle_FromObj(tree, listObjv[j], &elemPtr->style) != TCL_OK) || (TreeElement_FromObj(tree, listObjv[j + 1], &elemPtr->elem) != TCL_OK) || (TreeStyle_FindElement(tree, elemPtr->style, elemPtr->elem, &elemPtr->elemIndex) != TCL_OK)) { Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } if (!TreeElement_IsType(tree, elemPtr->elem, "text")) { FormatResult(interp, "element %s is not of type \"text\"", Tcl_GetString(listObjv[j + 1])); Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } sortData.columns[sortData.columnCount - 1].elemCount++; elemPtr++; } } break; } case OPT_FIRST: if (TreeItem_FromObj(tree, objv[i + 1], &first, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (first->parent != item) { FormatResult(interp, "item %s%d is not a child of item %s%d", tree->itemPrefix, first->id, tree->itemPrefix, item->id); return TCL_ERROR; } break; case OPT_INCREASING: sortData.columns[sortData.columnCount - 1].order = 1; break; case OPT_INTEGER: sortData.columns[sortData.columnCount - 1].sortBy = SORT_LONG; break; case OPT_LAST: if (TreeItem_FromObj(tree, objv[i + 1], &last, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (last->parent != item) { FormatResult(interp, "item %s%d is not a child of item %s%d", tree->itemPrefix, last->id, tree->itemPrefix, item->id); return TCL_ERROR; } break; case OPT_NOT_REALLY: notReally = TRUE; break; case OPT_REAL: sortData.columns[sortData.columnCount - 1].sortBy = SORT_DOUBLE; break; } i += numArgs[index]; } /* If there are no columns, we cannot perform a sort unless -command * is specified. */ if ((tree->columnCount < 1) && (sortData.columns[0].sortBy != SORT_COMMAND)) { FormatResult(interp, "there are no columns"); return TCL_ERROR; } /* If there is only one item to sort, then return early. */ if (first == last) { if (notReally) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, first)); return TCL_OK; } for (i = 0; i < sortData.columnCount; i++) { /* Initialize the sort procedure for this column. */ sortData.columns[i].proc = sortProc[sortData.columns[i].sortBy]; /* Append two dummy args to the -command argument. These two dummy * args are replaced by the 2 item ids being compared. See * CompareCmd(). */ if (sortData.columns[i].sortBy == SORT_COMMAND) { Tcl_Obj *obj = Tcl_DuplicateObj(sortData.columns[i].command); Tcl_Obj *obj2 = Tcl_NewObj(); Tcl_IncrRefCount(obj); if (Tcl_ListObjAppendElement(interp, obj, obj2) != TCL_OK) { Tcl_DecrRefCount(obj); Tcl_IncrRefCount(obj2); Tcl_DecrRefCount(obj2); for (j = 0; j < i; j++) { if (sortData.columns[j].sortBy == SORT_COMMAND) { Tcl_DecrRefCount(sortData.columns[j].command); } } return TCL_ERROR; } (void) Tcl_ListObjAppendElement(interp, obj, obj2); sortData.columns[i].command = obj; } } index = 0; walk = item->firstChild; while (walk != NULL) { if (walk == first) indexF = index; if (walk == last) indexL = index; index++; walk = walk->nextSibling; } if (indexF > indexL) { walk = last; last = first; first = walk; index = indexL; indexL = indexF; indexF = index; } count = indexL - indexF + 1; sortData.item1s = (struct SortItem1 *) ckalloc(sizeof(struct SortItem1) * count * sortData.columnCount); sortData.items = (struct SortItem *) ckalloc(sizeof(struct SortItem) * count); for (i = 0; i < count; i++) { sortData.items[i].item1 = sortData.item1s + i * sortData.columnCount; sortData.items[i].obj = NULL; } index = 0; walk = first; while (walk != last->nextSibling) { struct SortItem *sortItem = &sortData.items[index]; sortItem->item = walk; if (sawCmd) { Tcl_Obj *obj = TreeItem_ToObj(tree, walk); Tcl_IncrRefCount(obj); sortData.items[index].obj = obj; } for (i = 0; i < sortData.columnCount; i++) { struct SortItem1 *sortItem1 = sortItem->item1 + i; if (sortData.columns[i].sortBy == SORT_COMMAND) continue; column = Item_FindColumn(tree, walk, sortData.columns[i].column); if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, walk, sortData.columns[i].column); result = TCL_ERROR; goto done; } /* -element was empty. Find the first text element in the style */ if (sortData.columns[i].elemCount == 0) elemIndex = -1; /* -element was element name. Find the element in the style */ else if ((sortData.columns[i].elemCount == 1) && (sortData.columns[i].elems[0].style == NULL)) { if (TreeStyle_FindElement(tree, column->style, sortData.columns[i].elems[0].elem, &elemIndex) != TCL_OK) { result = TCL_ERROR; goto done; } } /* -element was style/element pair list */ else { TreeStyle masterStyle = TreeStyle_GetMaster(tree, column->style); /* If the item style does not match any in the -element list, * we will use the first text element in the item style. */ elemIndex = -1; /* Match a style from the -element list. Look in reverse order * to handle duplicates. */ for (j = sortData.columns[i].elemCount - 1; j >= 0; j--) { if (sortData.columns[i].elems[j].style == masterStyle) { elemIndex = sortData.columns[i].elems[j].elemIndex; break; } } } if (TreeStyle_GetSortData(tree, column->style, elemIndex, sortData.columns[i].sortBy, &sortItem1->longValue, &sortItem1->doubleValue, &sortItem1->string) != TCL_OK) { result = TCL_ERROR; goto done; } } index++; walk = walk->nextSibling; } quicksort(&sortData, sortData.items, sortData.items + count - 1); if (sortData.result != TCL_OK) { result = sortData.result; goto done; } if (sawCmd) Tcl_ResetResult(interp); if (notReally) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); Tcl_Obj *itemObj; /* Smallest to largest */ if (sortData.columns[0].order == 1) { for (i = 0; i < count; i++) { itemObj = sortData.items[i].obj; if (itemObj == NULL) itemObj = TreeItem_ToObj(tree, sortData.items[i].item); Tcl_ListObjAppendElement(interp, listObj, itemObj); } } /* Largest to smallest */ else { for (i = count - 1; i >= 0; i--) { itemObj = sortData.items[i].obj; if (itemObj == NULL) itemObj = TreeItem_ToObj(tree, sortData.items[i].item); Tcl_ListObjAppendElement(interp, listObj, itemObj); } } Tcl_SetObjResult(interp, listObj); goto done; } first = first->prevSibling; last = last->nextSibling; /* Smallest to largest */ if (sortData.columns[0].order == 1) { for (i = 0; i < count - 1; i++) { sortData.items[i].item->nextSibling = sortData.items[i + 1].item; sortData.items[i + 1].item->prevSibling = sortData.items[i].item; } indexF = 0; indexL = count - 1; } /* Largest to smallest */ else { for (i = count - 1; i > 0; i--) { sortData.items[i].item->nextSibling = sortData.items[i - 1].item; sortData.items[i - 1].item->prevSibling = sortData.items[i].item; } indexF = count - 1; indexL = 0; } lastChild = item->lastChild; sortData.items[indexF].item->prevSibling = first; if (first) first->nextSibling = sortData.items[indexF].item; else item->firstChild = sortData.items[indexF].item; sortData.items[indexL].item->nextSibling = last; if (last) last->prevSibling = sortData.items[indexL].item; else item->lastChild = sortData.items[indexL].item; /* Redraw the lines of the old/new lastchild */ if ((item->lastChild != lastChild) && tree->showLines && (tree->columnTree != NULL)) { if (lastChild->dInfo != NULL) Tree_InvalidateItemDInfo(tree, tree->columnTree, lastChild, NULL); if (item->lastChild->dInfo != NULL) Tree_InvalidateItemDInfo(tree, tree->columnTree, item->lastChild, NULL); } tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES); done: for (i = 0; i < count; i++) { if (sortData.items[i].obj != NULL) { Tcl_DecrRefCount(sortData.items[i].obj); } } for (i = 0; i < sortData.columnCount; i++) { if (sortData.columns[i].sortBy == SORT_COMMAND) { Tcl_DecrRefCount(sortData.columns[i].command); } } ckfree((char *) sortData.item1s); ckfree((char *) sortData.items); if (tree->debug.enable && tree->debug.data) { Tree_Debug(tree); } return result; } /* *---------------------------------------------------------------------- * * TreeItemList_Sort -- * * Sorts a list of items. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TILSCompare( CONST VOID *first_, CONST VOID *second_ ) { TreeItem first = *(TreeItem *) first_; TreeItem second = *(TreeItem *) second_; return first->index - second->index; } void TreeItemList_Sort( TreeItemList *items ) { Tree_UpdateItemIndex(items->tree); /* TkTable uses this, but mentions possible lack of thread-safety. */ qsort((VOID *) TreeItemList_Items(items), (size_t) TreeItemList_Count(items), sizeof(TreeItem), TILSCompare); } /* *---------------------------------------------------------------------- * * ItemStateCmd -- * * This procedure is invoked to process the [item state] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemStateCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandNames[] = { "forcolumn", "get", "set", (char *) NULL }; enum { COMMAND_FORCOLUMN, COMMAND_GET, COMMAND_SET }; int index; TreeItem item; if (objc < 5) { Tcl_WrongNumArgs(interp, 3, objv, "command item ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { /* T item state forcolumn I C ?stateList? */ case COMMAND_FORCOLUMN: { TreeItemList itemList; TreeColumnList columns; TreeColumn treeColumn; Tcl_Obj *listObj; Column *column; int columnIndex; int i, states[3], stateOn, stateOff; ItemForEach iter; ColumnForEach citer; int flags = IFO_NOT_NULL; int result = TCL_OK; if (objc < 6 || objc > 7) { Tcl_WrongNumArgs(interp, 4, objv, "item column ?stateList?"); return TCL_ERROR; } /* Without a stateList only one item is accepted. */ if (objc == 6) flags |= IFO_NOT_MANY; if (TreeItemList_FromObj(tree, objv[4], &itemList, flags) != TCL_OK) return TCL_ERROR; TreeColumnList_Init(tree, &columns, 0); if (objc == 6) { item = TreeItemList_Nth(&itemList, 0); if (Item_FindColumnFromObj(tree, item, objv[5], &column, &columnIndex) != TCL_OK) { result = TCL_ERROR; goto doneFORC; } if ((column == NULL) || !column->cstate) goto doneFORC; listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < 32; i++) { if (tree->stateNames[i] == NULL) continue; if (column->cstate & (1L << i)) { Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(tree->stateNames[i], -1)); } } Tcl_SetObjResult(interp, listObj); goto doneFORC; } if (TreeColumnList_FromObj(tree, objv[5], &columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneFORC; } if (Tree_StateFromListObj(tree, objv[6], states, SFO_NOT_STATIC) != TCL_OK) { result = TCL_ERROR; goto doneFORC; } if ((states[0] | states[1] | states[2]) == 0) goto doneFORC; ITEM_FOR_EACH(item, &itemList, NULL, &iter) { COLUMN_FOR_EACH(treeColumn, &columns, NULL, &citer) { columnIndex = TreeColumn_Index(treeColumn); column = Item_CreateColumn(tree, item, columnIndex, NULL); stateOn = states[STATE_OP_ON]; stateOff = states[STATE_OP_OFF]; stateOn |= ~column->cstate & states[STATE_OP_TOGGLE]; stateOff |= column->cstate & states[STATE_OP_TOGGLE]; Column_ChangeState(tree, item, column, treeColumn, stateOff, stateOn); } } doneFORC: TreeColumnList_Free(&columns); TreeItemList_Free(&itemList); return result; } /* T item state get I ?state? */ case COMMAND_GET: { Tcl_Obj *listObj; int i, states[3]; if (objc > 6) { Tcl_WrongNumArgs(interp, 5, objv, "?state?"); return TCL_ERROR; } if (TreeItem_FromObj(tree, objv[4], &item, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (objc == 6) { states[STATE_OP_ON] = 0; if (Tree_StateFromObj(tree, objv[5], states, NULL, SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewBooleanObj((item->state & states[STATE_OP_ON]) != 0)); break; } listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < 32; i++) { if (tree->stateNames[i] == NULL) continue; if (item->state & (1L << i)) { Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(tree->stateNames[i], -1)); } } Tcl_SetObjResult(interp, listObj); break; } /* T item state set I ?I? {state ...} */ case COMMAND_SET: { TreeItemList itemList, item2List; int states[3], stateOn, stateOff; ItemForEach iter; int result = TCL_OK; if (objc < 6 || objc > 7) { Tcl_WrongNumArgs(interp, 5, objv, "?last? stateList"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &itemList, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (objc == 6) { TreeItemList_Init(tree, &item2List, 0); } if (objc == 7) { if (TreeItemList_FromObj(tree, objv[5], &item2List, IFO_NOT_NULL) != TCL_OK) { result = TCL_ERROR; goto doneSET; } } if (Tree_StateFromListObj(tree, objv[objc - 1], states, SFO_NOT_STATIC) != TCL_OK) { result = TCL_ERROR; goto doneSET; } if ((states[0] | states[1] | states[2]) == 0) goto doneSET; ITEM_FOR_EACH(item, &itemList, &item2List, &iter) { stateOn = states[STATE_OP_ON]; stateOff = states[STATE_OP_OFF]; stateOn |= ~item->state & states[STATE_OP_TOGGLE]; stateOff |= item->state & states[STATE_OP_TOGGLE]; TreeItem_ChangeState(tree, item, stateOff, stateOn); } if (iter.error) result = TCL_ERROR; doneSET: TreeItemList_Free(&itemList); TreeItemList_Free(&item2List); return result; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * ItemTagCmd -- * * This procedure is invoked to process the [item tag] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemTagCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandNames[] = { "add", "expr", "names", "remove", (char *) NULL }; enum { COMMAND_ADD, COMMAND_EXPR, COMMAND_NAMES, COMMAND_REMOVE }; int index; ItemForEach iter; TreeItemList items; TreeItem item; int result = TCL_OK; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T item tag add I tagList */ case COMMAND_ADD: { int i, numTags; Tcl_Obj **listObjv; Tk_Uid staticTags[STATIC_SIZE], *tags = staticTags; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "item tagList"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &items, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[5], &numTags, &listObjv) != TCL_OK) { result = TCL_ERROR; break; } STATIC_ALLOC(tags, Tk_Uid, numTags); for (i = 0; i < numTags; i++) { tags[i] = Tk_GetUid(Tcl_GetString(listObjv[i])); } ITEM_FOR_EACH(item, &items, NULL, &iter) { item->tagInfo = TagInfo_Add(tree, item->tagInfo, tags, numTags); } STATIC_FREE(tags, Tk_Uid, numTags); break; } /* T item tag expr I tagExpr */ case COMMAND_EXPR: { TagExpr expr; int ok = TRUE; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "item tagExpr"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &items, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } if (TagExpr_Init(tree, objv[5], &expr) != TCL_OK) { result = TCL_ERROR; break; } ITEM_FOR_EACH(item, &items, NULL, &iter) { if (!TagExpr_Eval(&expr, item->tagInfo)) { ok = FALSE; break; } } TagExpr_Free(&expr); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ok)); break; } /* T item tag names I */ case COMMAND_NAMES: { Tcl_Obj *listObj; Tk_Uid *tags = NULL; int i, tagSpace, numTags = 0; if (objc != 5) { Tcl_WrongNumArgs(interp, 4, objv, "item"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &items, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } ITEM_FOR_EACH(item, &items, NULL, &iter) { tags = TagInfo_Names(tree, item->tagInfo, tags, &numTags, &tagSpace); } if (numTags) { listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < numTags; i++) { Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewStringObj((char *) tags[i], -1)); } Tcl_SetObjResult(interp, listObj); ckfree((char *) tags); } break; } /* T item tag remove I tagList */ case COMMAND_REMOVE: { int i, numTags; Tcl_Obj **listObjv; Tk_Uid staticTags[STATIC_SIZE], *tags = staticTags; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "item tagList"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &items, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[5], &numTags, &listObjv) != TCL_OK) { result = TCL_ERROR; break; } STATIC_ALLOC(tags, Tk_Uid, numTags); for (i = 0; i < numTags; i++) { tags[i] = Tk_GetUid(Tcl_GetString(listObjv[i])); } ITEM_FOR_EACH(item, &items, NULL, &iter) { item->tagInfo = TagInfo_Remove(tree, item->tagInfo, tags, numTags); } STATIC_FREE(tags, Tk_Uid, numTags); break; } } TreeItemList_Free(&items); return result; } #ifdef SELECTION_VISIBLE /* *---------------------------------------------------------------------- * * Tree_DeselectHidden -- * * Removes any selected items which are no longer ReallyVisible() * from the selection. * * Results: * None. * * Side effects: * event may be generated. * *---------------------------------------------------------------------- */ /* * FIXME: optimize all calls to this routine. * Optionally call Tree_DInfoChanged(tree, DINFO_REDO_SELECTION) instead. */ void Tree_DeselectHidden( TreeCtrl *tree /* Widget info. */ ) { TreeItemList items; Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeItem item; int i; if (tree->selectCount < 1) return; /* This call is slow for large lists. */ Tree_UpdateItemIndex(tree); TreeItemList_Init(tree, &items, tree->selectCount); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); if (!TreeItem_ReallyVisible(tree, item)) TreeItemList_Append(&items, item); hPtr = Tcl_NextHashEntry(&search); } for (i = 0; i < TreeItemList_Count(&items); i++) Tree_RemoveFromSelection(tree, TreeItemList_Nth(&items, i)); if (TreeItemList_Count(&items)) { TreeNotify_Selection(tree, NULL, &items); } TreeItemList_Free(&items); } #endif /* SELECTION_VISIBLE */ /* *---------------------------------------------------------------------- * * TreeItemCmd -- * * This procedure is invoked to process the [item] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeItemCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; enum { COMMAND_ANCESTORS, COMMAND_BBOX, COMMAND_CGET, COMMAND_CHILDREN, COMMAND_COLLAPSE, COMMAND_COMPARE, #ifdef DEPRECATED COMMAND_COMPLEX, #endif COMMAND_CONFIGURE, COMMAND_COUNT, COMMAND_CREATE, COMMAND_DELETE, COMMAND_DESCENDANTS, COMMAND_DUMP, COMMAND_ELEMENT, COMMAND_ENABLED, COMMAND_EXPAND, COMMAND_FIRSTCHILD, COMMAND_ID, COMMAND_IMAGE, COMMAND_ISANCESTOR, COMMAND_ISOPEN, COMMAND_LASTCHILD, COMMAND_NEXTSIBLING, COMMAND_NUMCHILDREN, COMMAND_ORDER, COMMAND_PARENT, COMMAND_PREVSIBLING, COMMAND_RANGE, COMMAND_REMOVE, COMMAND_RNC, COMMAND_SORT, COMMAND_SPAN, COMMAND_STATE, COMMAND_STYLE, COMMAND_TAG, COMMAND_TEXT, COMMAND_TOGGLE }; #define AF_NOT_ANCESTOR 0x00010000 /* item can't be ancestor of other item */ #define AF_NOT_EQUAL 0x00020000 /* second item can't be same as first */ #define AF_SAMEROOT 0x00040000 /* both items must be descendants of a common ancestor */ #define AF_NOT_ITEM 0x00080000 /* arg is not an Item */ struct { char *cmdName; int minArgs; int maxArgs; int flags; /* AF_xxx | IFO_xxx for 1st arg. */ int flags2; /* AF_xxx | IFO_xxx for 2nd arg. */ int flags3; /* AF_xxx | IFO_xxx for 3rd arg. */ char *argString; Tcl_ObjCmdProc *proc; } argInfo[] = { { "ancestors", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "bbox", 1, 3, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?column? ?element?", NULL }, { "cget", 2, 2, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, 0, "item option", NULL }, { "children", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "collapse", 1, 2, IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?-recurse?", NULL}, { "compare", 3, 3, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, IFO_NOT_MANY | IFO_NOT_NULL | AF_SAMEROOT, "item1 op item2", NULL }, #ifdef DEPRECATED { "complex", 2, 100000, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item list ...", NULL }, #endif { "configure", 1, 100000, IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?option? ?value? ?option value ...?", NULL }, { "count", 0, 1, 0, 0, 0, "?itemDesc?" , NULL}, { "create", 0, 0, 0, 0, 0, NULL, ItemCreateCmd }, { "delete", 1, 2, IFO_NOT_NULL, IFO_NOT_NULL | AF_SAMEROOT, 0, "first ?last?", NULL }, { "descendants", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "dump", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "element", 0, 0, 0, 0, 0, NULL, ItemElementCmd }, { "enabled", 1, 2, IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?boolean?", NULL }, { "expand", 1, 2, IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?-recurse?", NULL}, { "firstchild", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | AF_NOT_ANCESTOR | AF_NOT_EQUAL, 0, "item ?newFirstChild?", NULL }, { "id", 1, 1, 0, 0, 0, "item", NULL }, { "image", 1, 100000, IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?column? ?image? ?column image ...?", NULL }, { "isancestor", 2, 2, IFO_NOT_MANY | IFO_NOT_NULL, IFO_NOT_MANY | IFO_NOT_NULL, 0, "item item2", NULL }, { "isopen", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "lastchild", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | AF_NOT_ANCESTOR | AF_NOT_EQUAL, 0, "item ?newLastChild?", NULL }, { "nextsibling", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | IFO_NOT_ORPHAN, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | AF_NOT_ANCESTOR | AF_NOT_EQUAL, 0, "item ?newNextSibling?", NULL }, { "numchildren", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "order", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?-visible?", NULL }, { "parent", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "prevsibling", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | IFO_NOT_ORPHAN, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | AF_NOT_ANCESTOR | AF_NOT_EQUAL, 0, "item ?newPrevSibling?", NULL }, { "range", 2, 2, IFO_NOT_MANY | IFO_NOT_NULL, IFO_NOT_MANY | IFO_NOT_NULL | AF_SAMEROOT, 0, "first last", NULL }, { "remove", 1, 1, IFO_NOT_NULL | IFO_NOT_ROOT, 0, 0, "item", NULL }, { "rnc", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "sort", 0, 0, 0, 0, 0, NULL, ItemSortCmd }, { "span", 1, 100000, IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?column? ?span? ?column span ...?", NULL }, { "state", 0, 0, 0, 0, 0, NULL, ItemStateCmd }, { "style", 0, 0, 0, 0, 0, NULL, ItemStyleCmd }, { "tag", 0, 0, 0, 0, 0, NULL, ItemTagCmd }, { "text", 1, 100000, IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?column? ?text? ?column text ...?", NULL }, { "toggle", 1, 2, IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?-recurse?", NULL}, { NULL } }; int index; int numArgs = objc - 3; TreeItemList itemList, item2List; TreeItem item = NULL, item2 = NULL, child; ItemForEach iter; int result = TCL_OK; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObjStruct(interp, objv[2], argInfo, sizeof(argInfo[0]), "command", 0, &index) != TCL_OK) { return TCL_ERROR; } if (argInfo[index].proc != NULL) return argInfo[index].proc(clientData, interp, objc, objv); if ((numArgs < argInfo[index].minArgs) || (numArgs > argInfo[index].maxArgs)) { Tcl_WrongNumArgs(interp, 3, objv, argInfo[index].argString); return TCL_ERROR; } TreeItemList_Init(tree, &itemList, 0); TreeItemList_Init(tree, &item2List, 0); if ((numArgs >= 1) && !(argInfo[index].flags & AF_NOT_ITEM)) { if (TreeItemList_FromObj(tree, objv[3], &itemList, argInfo[index].flags & 0xFFFF) != TCL_OK) { goto errorExit; } item = TreeItemList_Nth(&itemList, 0); /* May be NULL. */ } if (((numArgs >= 2) && !(argInfo[index].flags2 & AF_NOT_ITEM)) || ((numArgs >= 3) && !(argInfo[index].flags3 & AF_NOT_ITEM))) { int flags, obji; if (argInfo[index].flags2 & AF_NOT_ITEM) { obji = 5; flags = argInfo[index].flags3; } else { obji = 4; flags = argInfo[index].flags2; } if (TreeItemList_FromObj(tree, objv[obji], &item2List, flags & 0xFFFF) != TCL_OK) { goto errorExit; } item2 = TreeItemList_Nth(&item2List, 0); /* May be NULL. */ if ((flags & AF_NOT_EQUAL) && (item == item2)) { FormatResult(interp, "item %s%d same as second item", tree->itemPrefix, item->id); goto errorExit; } if ((argInfo[index].flags & AF_NOT_ANCESTOR) && TreeItem_IsAncestor(tree, item, item2)) { FormatResult(interp, "item %s%d is ancestor of item %s%d", tree->itemPrefix, item->id, tree->itemPrefix, item2->id); goto errorExit; } if ((flags & AF_NOT_ANCESTOR) && TreeItem_IsAncestor(tree, item2, item)) { FormatResult(interp, "item %s%d is ancestor of item %s%d", tree->itemPrefix, item2->id, tree->itemPrefix, item->id); goto errorExit; } if ((flags & AF_SAMEROOT) && TreeItem_RootAncestor(tree, item) != TreeItem_RootAncestor(tree, item2)) { FormatResult(interp, "item %s%d and item %s%d don't share a common ancestor", tree->itemPrefix, item->id, tree->itemPrefix, item2->id); goto errorExit; } } switch (index) { case COMMAND_ANCESTORS: { Tcl_Obj *listObj; TreeItem parent = item->parent; if (parent == NULL) break; /* empty list */ listObj = Tcl_NewListObj(0, NULL); while (parent != NULL) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, parent)); parent = parent->parent; } Tcl_SetObjResult(interp, listObj); break; } /* T item bbox I ?C? ?E? */ case COMMAND_BBOX: { int x, y, w, h; int count; TreeColumn treeColumn; XRectangle rect; if (objc == 4) { if (Tree_ItemBbox(tree, item, COLUMN_LOCK_NONE, &x, &y, &w, &h) < 0) break; } else { if (TreeColumn_FromObj(tree, objv[4], &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) goto errorExit; /* Bounds of a column. */ if (objc == 5) { objc = 0; objv = NULL; /* Single element in a column. */ } else { objc -= 5; objv += 5; } count = TreeItem_GetRects(tree, item, treeColumn, objc, objv, &rect); if (count == 0) break; if (count == -1) goto errorExit; x = rect.x; y = rect.y; w = rect.width; h = rect.height; } FormatResult(interp, "%d %d %d %d", x - tree->xOrigin, y - tree->yOrigin, x - tree->xOrigin + w, y - tree->yOrigin + h); break; } case COMMAND_CGET: { Tcl_Obj *resultObjPtr; resultObjPtr = Tk_GetOptionValue(interp, (char *) item, tree->itemOptionTable, objv[4], tree->tkwin); if (resultObjPtr == NULL) goto errorExit; Tcl_SetObjResult(interp, resultObjPtr); break; } case COMMAND_CHILDREN: { if (item->numChildren != 0) { Tcl_Obj *listObj; listObj = Tcl_NewListObj(0, NULL); child = item->firstChild; while (child != NULL) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, child)); child = child->nextSibling; } Tcl_SetObjResult(interp, listObj); } break; } case COMMAND_COLLAPSE: case COMMAND_EXPAND: case COMMAND_TOGGLE: { int recurse = 0; int mode = 0; /* lint */ int i, count; TreeItemList items; if (numArgs == 2) { int len; char *s = Tcl_GetStringFromObj(objv[4], &len); if (strncmp(s, "-recurse", len)) { FormatResult(interp, "bad option \"%s\": must be -recurse", s); goto errorExit; } recurse = 1; } switch (index) { case COMMAND_COLLAPSE: mode = 0; break; case COMMAND_EXPAND: mode = 1; break; case COMMAND_TOGGLE: mode = -1; break; } TreeItemList_Init(tree, &items, 0); ITEM_FOR_EACH(item, &itemList, NULL, &iter) { TreeItemList_Append(&items, item); if (!iter.all && recurse) { TreeItem_ListDescendants(tree, item, &items); } } count = TreeItemList_Count(&items); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&items, i); TreeItem_OpenClose(tree, item, mode); } TreeItemList_Free(&items); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif break; } /* T item compare I op I */ case COMMAND_COMPARE: { static CONST84 char *opName[] = { "<", "<=", "==", ">=", ">", "!=", NULL }; int op, compare = 0, index1, index2; if (Tcl_GetIndexFromObj(interp, objv[4], opName, "comparison operator", 0, &op) != TCL_OK) goto errorExit; TreeItem_ToIndex(tree, item, &index1, NULL); TreeItem_ToIndex(tree, item2, &index2, NULL); switch (op) { case 0: compare = index1 < index2; break; case 1: compare = index1 <= index2; break; case 2: compare = index1 == index2; break; case 3: compare = index1 >= index2; break; case 4: compare = index1 > index2; break; case 5: compare = index1 != index2; break; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(compare)); break; } #ifdef DEPRECATED case COMMAND_COMPLEX: { int i, j, columnIndex; int objc1, objc2; Tcl_Obj **objv1, **objv2; TreeColumn treeColumn = tree->columns; Column *column; int eMask, cMask, iMask = 0; if (objc <= 4) break; columnIndex = 0; for (i = 4; i < objc; i++, columnIndex++, treeColumn = TreeColumn_Next(treeColumn)) { if (treeColumn == NULL) { FormatResult(interp, "column #%d doesn't exist", columnIndex); result = TCL_ERROR; goto doneComplex; } column = Item_FindColumn(tree, item, columnIndex); if (column == NULL) { FormatResult(interp, "item %s%d doesn't have column %s%d", tree->itemPrefix, item->id, tree->columnPrefix, TreeColumn_GetID(treeColumn)); result = TCL_ERROR; goto doneComplex; } /* List of element-configs per column */ if (Tcl_ListObjGetElements(interp, objv[i], &objc1, &objv1) != TCL_OK) { result = TCL_ERROR; goto doneComplex; } if (objc1 == 0) continue; if (column->style == NULL) { FormatResult(interp, "item %s%d column %s%d has no style", tree->itemPrefix, item->id, tree->columnPrefix, TreeColumn_GetID(treeColumn)); result = TCL_ERROR; goto doneComplex; } cMask = 0; for (j = 0; j < objc1; j++) { /* elem option value... */ if (Tcl_ListObjGetElements(interp, objv1[j], &objc2, &objv2) != TCL_OK) { result = TCL_ERROR; goto doneComplex; } if (objc2 < 3) { FormatResult(interp, "wrong # args: should be \"element option value ...\""); result = TCL_ERROR; goto doneComplex; } if (TreeStyle_ElementConfigure(tree, item, (TreeItemColumn) column, column->style, objv2[0], objc2 - 1, objv2 + 1, &eMask) != TCL_OK) { result = TCL_ERROR; goto doneComplex; } cMask |= eMask; iMask |= eMask; } if (cMask & CS_LAYOUT) TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); } doneComplex: if (iMask & CS_DISPLAY) Tree_InvalidateItemDInfo(tree, NULL, item, NULL); if (iMask & CS_LAYOUT) { Tree_InvalidateColumnWidth(tree, NULL); TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } break; } #endif /* DEPRECATED*/ /* T item configure I ?option? ?value? ?option value ...? */ case COMMAND_CONFIGURE: { if (objc <= 5) { Tcl_Obj *resultObjPtr; if (IS_ALL(item) || (TreeItemList_Count(&itemList) > 1)) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } resultObjPtr = Tk_GetOptionInfo(interp, (char *) item, tree->itemOptionTable, (objc == 4) ? (Tcl_Obj *) NULL : objv[4], tree->tkwin); if (resultObjPtr == NULL) goto errorExit; Tcl_SetObjResult(interp, resultObjPtr); break; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { result = Item_Configure(tree, item, objc - 4, objv + 4); if (result != TCL_OK) break; } break; } case COMMAND_COUNT: { int count = tree->itemCount; if (objc == 4) { count = 0; ITEM_FOR_EACH(item, &itemList, &item2List, &iter) { count++; } } Tcl_SetObjResult(interp, Tcl_NewIntObj(count)); break; } case COMMAND_DELETE: { TreeItemList deleted, selected; int i, count; /* The root is never deleted */ if (tree->itemCount == 1) break; if (objc == 5) { if (item == NULL || item2 == NULL) { FormatResult(interp, "invalid range \"%s\" to \"%s\"", Tcl_GetString(objv[3]), Tcl_GetString(objv[4])); goto errorExit; } } /* * ITEM_FLAG_DELETED prevents us from adding the same item * twice to the 'deleted' list. It also prevents nested * calls to this command (through binding scripts) deleting * the same item twice. */ TreeItemList_Init(tree, &deleted, tree->itemCount - 1); TreeItemList_Init(tree, &selected, tree->selectCount); ITEM_FOR_EACH(item, &itemList, &item2List, &iter) { if (IS_ROOT(item)) continue; if (IS_DELETED(item)) continue; item->flags |= ITEM_FLAG_DELETED; TreeItemList_Append(&deleted, item); if (TreeItem_GetSelected(tree, item)) TreeItemList_Append(&selected, item); if (iter.all) continue; /* Check every descendant. */ if (item->firstChild == NULL) continue; item2 = item; while (item2->lastChild != NULL) item2 = item2->lastChild; item = item->firstChild; while (1) { if (IS_DELETED(item)) { /* Skip all descendants (they are already flagged). */ while (item->lastChild != NULL) item = item->lastChild; } else { item->flags |= ITEM_FLAG_DELETED; TreeItemList_Append(&deleted, item); if (TreeItem_GetSelected(tree, item)) TreeItemList_Append(&selected, item); } if (item == item2) break; item = TreeItem_Next(tree, item); } } count = TreeItemList_Count(&selected); if (count) { for (i = 0; i < count; i++) { item = TreeItemList_Nth(&selected, i); Tree_RemoveFromSelection(tree, item); } /* Generate event for selected items being deleted. */ TreeNotify_Selection(tree, NULL, &selected); } count = TreeItemList_Count(&deleted); if (count) { /* Generate event for items being deleted. */ TreeNotify_ItemDeleted(tree, &deleted); /* Remove every item from its parent. Needed because items * are deleted recursively. */ for (i = 0; i < count; i++) { item = TreeItemList_Nth(&deleted, i); TreeItem_RemoveFromParent(tree, item); } /* Delete the items. The item record will be freed when no * longer in use; however, the item cannot be referred to * by commands from this point on. */ for (i = 0; i < count; i++) { item = TreeItemList_Nth(&deleted, i); TreeItem_Delete(tree, item); } } TreeItemList_Free(&selected); TreeItemList_Free(&deleted); break; } case COMMAND_DESCENDANTS: { Tcl_Obj *listObj; if (item->firstChild == NULL) break; item2 = item; while (item2->lastChild != NULL) item2 = item2->lastChild; item = item->firstChild; listObj = Tcl_NewListObj(0, NULL); while (1) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); if (item == item2) break; item = TreeItem_Next(tree, item); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_DUMP: { Tree_UpdateItemIndex(tree); FormatResult(interp, "index %d indexVis %d", item->index, item->indexVis); break; } /* T item enabled I ?boolean? */ case COMMAND_ENABLED: { int enabled; TreeItemList newD; int stateOff, stateOn; if (objc == 4) { if (IS_ALL(item) || (TreeItemList_Count(&itemList) > 1)) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(item->state & STATE_ENABLED)); break; } if (Tcl_GetBooleanFromObj(interp, objv[4], &enabled) != TCL_OK) goto errorExit; stateOff = enabled ? 0 : STATE_ENABLED; stateOn = enabled ? STATE_ENABLED : 0; TreeItemList_Init(tree, &newD, tree->selectCount); ITEM_FOR_EACH(item, &itemList, NULL, &iter) { if (enabled != TreeItem_GetEnabled(tree, item)) { TreeItem_ChangeState(tree, item, stateOff, stateOn); /* Disabled items cannot be selected. */ if (!enabled && TreeItem_GetSelected(tree, item)) { Tree_RemoveFromSelection(tree, item); TreeItemList_Append(&newD, item); } } } if (TreeItemList_Count(&newD)) TreeNotify_Selection(tree, NULL, &newD); TreeItemList_Free(&newD); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(enabled)); break; } case COMMAND_FIRSTCHILD: { /* Don't allow non-deleted items to become children of a * deleted item. */ if (item2 != NULL && item2 != item->firstChild && (!IS_DELETED(item) || IS_DELETED(item2))) { TreeItem_RemoveFromParent(tree, item2); item2->nextSibling = item->firstChild; if (item->firstChild != NULL) item->firstChild->prevSibling = item2; else item->lastChild = item2; item->firstChild = item2; item2->parent = item; item->numChildren++; TreeItem_AddToParent(tree, item2); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif } if (item->firstChild != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->firstChild)); break; } /* T item id I */ case COMMAND_ID: { Tcl_Obj *listObj; listObj = Tcl_NewListObj(0, NULL); ITEM_FOR_EACH(item, &itemList, NULL, &iter) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_ISANCESTOR: { Tcl_SetObjResult(interp, Tcl_NewBooleanObj( TreeItem_IsAncestor(tree, item, item2))); break; } case COMMAND_ISOPEN: { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(item->state & STATE_OPEN)); break; } case COMMAND_LASTCHILD: { /* Don't allow non-deleted items to become children of a * deleted item. */ if (item2 != NULL && item2 != item->lastChild && (!IS_DELETED(item) || IS_DELETED(item2))) { TreeItem_RemoveFromParent(tree, item2); item2->prevSibling = item->lastChild; if (item->lastChild != NULL) item->lastChild->nextSibling = item2; else item->firstChild = item2; item->lastChild = item2; item2->parent = item; item->numChildren++; TreeItem_AddToParent(tree, item2); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif } if (item->lastChild != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->lastChild)); break; } case COMMAND_NEXTSIBLING: { if (item2 != NULL && item2 != item->nextSibling) { TreeItem_RemoveFromParent(tree, item2); item2->prevSibling = item; if (item->nextSibling != NULL) { item->nextSibling->prevSibling = item2; item2->nextSibling = item->nextSibling; } else item->parent->lastChild = item2; item->nextSibling = item2; item2->parent = item->parent; item->parent->numChildren++; TreeItem_AddToParent(tree, item2); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif } if (item->nextSibling != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->nextSibling)); break; } case COMMAND_NUMCHILDREN: { Tcl_SetObjResult(interp, Tcl_NewIntObj(item->numChildren)); break; } /* T item order I ?-visible? */ case COMMAND_ORDER: { int visible = FALSE; if (objc == 5) { int len; char *s = Tcl_GetStringFromObj(objv[4], &len); if ((s[0] == '-') && (strncmp(s, "-visible", len) == 0)) visible = TRUE; else { FormatResult(interp, "bad switch \"%s\": must be -visible", s); goto errorExit; } } Tree_UpdateItemIndex(tree); Tcl_SetObjResult(interp, Tcl_NewIntObj(visible ? item->indexVis : item->index)); break; } /* T item range I I */ case COMMAND_RANGE: { TreeItem itemFirst = item; TreeItem itemLast = item2; Tcl_Obj *listObj; if (itemFirst == itemLast) { Tcl_SetObjResult(interp, TreeItem_ToObj(tree, itemFirst)); break; } (void) TreeItem_FirstAndLast(tree, &itemFirst, &itemLast); listObj = Tcl_NewListObj(0, NULL); while (itemFirst != NULL) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, itemFirst)); if (itemFirst == itemLast) break; itemFirst = TreeItem_Next(tree, itemFirst); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_PARENT: { if (item->parent != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->parent)); break; } case COMMAND_PREVSIBLING: { if (item2 != NULL && item2 != item->prevSibling) { TreeItem_RemoveFromParent(tree, item2); item2->nextSibling = item; if (item->prevSibling != NULL) { item->prevSibling->nextSibling = item2; item2->prevSibling = item->prevSibling; } else item->parent->firstChild = item2; item->prevSibling = item2; item2->parent = item->parent; item->parent->numChildren++; TreeItem_AddToParent(tree, item2); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif } if (item->prevSibling != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->prevSibling)); break; } case COMMAND_REMOVE: { int removed = FALSE; ITEM_FOR_EACH(item, &itemList, NULL, &iter) { if (item->parent != NULL) { TreeItem_RemoveFromParent(tree, item); Tree_FreeItemDInfo(tree, item, NULL); removed = TRUE; } } if (!removed) break; if (tree->debug.enable && tree->debug.data) Tree_Debug(tree); Tree_InvalidateColumnWidth(tree, NULL); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif break; } case COMMAND_RNC: { int row,col; if (Tree_ItemToRNC(tree, item, &row, &col) == TCL_OK) FormatResult(interp, "%d %d", row, col); break; } /* T item span I ?C? ?span? ?C span ...? */ case COMMAND_SPAN: { TreeColumn treeColumn = tree->columns; Column *column = item->columns; Tcl_Obj *listObj; struct columnSpan { TreeColumnList columns; int span; } staticCS[STATIC_SIZE], *cs = staticCS; int i, count = 0, span, changed = FALSE; ColumnForEach citer; if ((objc < 6) && (IS_ALL(item) || (TreeItemList_Count(&itemList) > 1))) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } if (objc == 4) { listObj = Tcl_NewListObj(0, NULL); while (treeColumn != NULL) { Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(column ? column->span : 1)); treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } Tcl_SetObjResult(interp, listObj); break; } if (objc == 5) { if (Item_FindColumnFromObj(tree, item, objv[4], &column, NULL) != TCL_OK) { goto errorExit; } Tcl_SetObjResult(interp, Tcl_NewIntObj(column ? column->span : 1)); break; } if ((objc - 4) & 1) { FormatResult(interp, "missing argument after column \"%s\"", Tcl_GetString(objv[objc - 1])); goto errorExit; } /* Gather column/span pairs. */ STATIC_ALLOC(cs, struct columnSpan, objc / 2); for (i = 4; i < objc; i += 2) { if (TreeColumnList_FromObj(tree, objv[i], &cs[count].columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneSPAN; } if (Tcl_GetIntFromObj(interp, objv[i + 1], &span) != TCL_OK) { result = TCL_ERROR; goto doneSPAN; } if (span <= 0) { FormatResult(interp, "bad span \"%d\": must be > 0", span); result = TCL_ERROR; goto doneSPAN; } cs[count].span = span; count++; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { int changedI = FALSE; for (i = 0; i < count; i++) { COLUMN_FOR_EACH(treeColumn, &cs[i].columns, NULL, &citer) { column = Item_CreateColumn(tree, item, TreeColumn_Index(treeColumn), NULL); if (column->span != cs[i].span) { if (cs[i].span > 1) { item->flags &= ~ITEM_FLAG_SPANS_SIMPLE; } TreeItem_SpansInvalidate(tree, item); column->span = cs[i].span; TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); changedI = TRUE; Tree_InvalidateColumnWidth(tree, treeColumn); } } } if (changedI) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); changed = TRUE; } } if (changed) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); doneSPAN: for (i = 0; i < count; i++) { TreeColumnList_Free(&cs[i].columns); } STATIC_FREE(cs, struct columnSpan, objc / 2); break; } /* T item image I ?C? ?image? ?C image ...? */ case COMMAND_IMAGE: /* T item text I ?C? ?text? ?C text ...? */ case COMMAND_TEXT: { TreeColumn treeColumn = tree->columns; Column *column; Tcl_Obj *objPtr; int isImage = (index == COMMAND_IMAGE); struct columnObj { TreeColumnList columns; Tcl_Obj *obj; } staticCO[STATIC_SIZE], *co = staticCO; int i, count = 0, changed = FALSE, columnIndex; ColumnForEach citer; if ((objc < 6) && (IS_ALL(item) || (TreeItemList_Count(&itemList) > 1))) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } if (objc == 4) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); column = item->columns; while (treeColumn != NULL) { if ((column != NULL) && (column->style != NULL)) objPtr = isImage ? TreeStyle_GetImage(tree, column->style) : TreeStyle_GetText(tree, column->style); else objPtr = NULL; if (objPtr == NULL) objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, listObj, objPtr); treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } Tcl_SetObjResult(interp, listObj); break; } if (objc == 5) { if (Item_FindColumnFromObj(tree, item, objv[4], &column, NULL) != TCL_OK) { goto errorExit; } if ((column != NULL) && (column->style != NULL)) { objPtr = isImage ? TreeStyle_GetImage(tree, column->style) : TreeStyle_GetText(tree, column->style); if (objPtr != NULL) Tcl_SetObjResult(interp, objPtr); } break; } if ((objc - 4) & 1) { FormatResult(interp, "missing argument after column \"%s\"", Tcl_GetString(objv[objc - 1])); goto errorExit; } /* Gather column/obj pairs. */ STATIC_ALLOC(co, struct columnObj, objc / 2); for (i = 4; i < objc; i += 2) { if (TreeColumnList_FromObj(tree, objv[i], &co[count].columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneTEXT; } co[count].obj = objv[i + 1]; count++; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { int changedI = FALSE; for (i = 0; i < count; i++) { COLUMN_FOR_EACH(treeColumn, &co[i].columns, NULL, &citer) { columnIndex = TreeColumn_Index(treeColumn); column = Item_FindColumn(tree, item, columnIndex); if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; goto doneTEXT; } result = isImage ? TreeStyle_SetImage(tree, item, (TreeItemColumn) column, column->style, co[i].obj) : TreeStyle_SetText(tree, item, (TreeItemColumn) column, column->style, co[i].obj); if (result != TCL_OK) goto doneTEXT; TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_InvalidateColumnWidth(tree, treeColumn); changedI = TRUE; } } if (changedI) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); changed = TRUE; } } if (changed) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); doneTEXT: for (i = 0; i < count; i++) { TreeColumnList_Free(&co[i].columns); } STATIC_FREE(co, struct columnObj, objc / 2); break; } } TreeItemList_Free(&itemList); TreeItemList_Free(&item2List); return result; errorExit: TreeItemList_Free(&itemList); TreeItemList_Free(&item2List); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TreeItem_Debug -- * * Perform some sanity checks on an Item and its descendants. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_Debug( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem child; Tcl_Interp *interp = tree->interp; int count; if (item->parent == item) { FormatResult(interp, "parent of %d is itself", item->id); return TCL_ERROR; } if (item->parent == NULL) { if (item->prevSibling != NULL) { FormatResult(interp, "parent of %d is nil, prevSibling is not nil", item->id); return TCL_ERROR; } if (item->nextSibling != NULL) { FormatResult(interp, "parent of %d is nil, nextSibling is not nil", item->id); return TCL_ERROR; } } if (item->prevSibling != NULL) { if (item->prevSibling == item) { FormatResult(interp, "prevSibling of %d is itself", item->id); return TCL_ERROR; } if (item->prevSibling->nextSibling != item) { FormatResult(interp, "item%d.prevSibling.nextSibling is not it", item->id); return TCL_ERROR; } } if (item->nextSibling != NULL) { if (item->nextSibling == item) { FormatResult(interp, "nextSibling of %d is itself", item->id); return TCL_ERROR; } if (item->nextSibling->prevSibling != item) { FormatResult(interp, "item%d.nextSibling->prevSibling is not it", item->id); return TCL_ERROR; } } if (item->numChildren < 0) { FormatResult(interp, "numChildren of %d is %d", item->id, item->numChildren); return TCL_ERROR; } if (item->numChildren == 0) { if (item->firstChild != NULL) { FormatResult(interp, "item%d.numChildren is zero, firstChild is not nil", item->id); return TCL_ERROR; } if (item->lastChild != NULL) { FormatResult(interp, "item%d.numChildren is zero, lastChild is not nil", item->id); return TCL_ERROR; } } if (item->numChildren > 0) { if (item->firstChild == NULL) { FormatResult(interp, "item%d.firstChild is nil", item->id); return TCL_ERROR; } if (item->firstChild == item) { FormatResult(interp, "item%d.firstChild is itself", item->id); return TCL_ERROR; } if (item->firstChild->parent != item) { FormatResult(interp, "item%d.firstChild.parent is not it", item->id); return TCL_ERROR; } if (item->firstChild->prevSibling != NULL) { FormatResult(interp, "item%d.firstChild.prevSibling is not nil", item->id); return TCL_ERROR; } if (item->lastChild == NULL) { FormatResult(interp, "item%d.lastChild is nil", item->id); return TCL_ERROR; } if (item->lastChild == item) { FormatResult(interp, "item%d.lastChild is itself", item->id); return TCL_ERROR; } if (item->lastChild->parent != item) { FormatResult(interp, "item%d.lastChild.parent is not it", item->id); return TCL_ERROR; } if (item->lastChild->nextSibling != NULL) { FormatResult(interp, "item%d.lastChild.nextSibling is not nil", item->id); return TCL_ERROR; } /* Count number of children */ count = 0; child = item->firstChild; while (child != NULL) { count++; child = child->nextSibling; } if (count != item->numChildren) { FormatResult(interp, "item%d.numChildren is %d, but counted %d", item->id, item->numChildren, count); return TCL_ERROR; } /* Debug each child recursively */ child = item->firstChild; while (child != NULL) { if (child->parent != item) { FormatResult(interp, "child->parent of %d is not it", item->id); return TCL_ERROR; } if (TreeItem_Debug(tree, child) != TCL_OK) return TCL_ERROR; child = child->nextSibling; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * SpanWalkProc_Identify -- * * Callback routine to TreeItem_WalkSpans for TreeItem_Identify. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SpanWalkProc_Identify( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { struct { int x; int y; char *buf; } *data = clientData; if ((data->x < drawArgs->x + drawArgs->indent) || (data->x >= drawArgs->x + drawArgs->width)) return 0; sprintf(data->buf + strlen(data->buf), " column %s%d", tree->columnPrefix, TreeColumn_GetID(spanPtr->treeColumn)); if (drawArgs->style != NULL) { char *elem = TreeStyle_Identify(drawArgs, data->x, data->y); if (elem != NULL) sprintf(data->buf + strlen(data->buf), " elem %s", elem); } return 1; /* stop */ } /* *---------------------------------------------------------------------- * * TreeItem_Identify -- * * Determine which column and element the given point is in. * This is used by the [identify] widget command. * * Results: * If the Item is not ReallyVisible() or no columns are visible * then buf[] is untouched. Otherwise the given string may be * appended with "column C" followed by "elem E" although both * are optional. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_Identify( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int lock, /* Columns to hit-test. */ int x, int y, /* Item coords to hit-test with. */ char *buf /* NULL-terminated string which may be * appended. */ ) { int left, top, width, height; struct { int x; int y; char *buf; } clientData; if (Tree_ItemBbox(tree, item, lock, &left, &top, &width, &height) < 0) return; /* Tree_ItemBbox returns canvas coords. x/y are item coords. */ clientData.x = x; clientData.y = y; clientData.buf = buf; TreeItem_WalkSpans(tree, item, lock, 0, 0, width, height, SpanWalkProc_Identify, (ClientData) &clientData); } /* *---------------------------------------------------------------------- * * SpanWalkProc_Identify2 -- * * Callback routine to TreeItem_WalkSpans for TreeItem_Identify2. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SpanWalkProc_Identify2( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { Tcl_Obj *subListObj; struct { int x1; int y1; int x2; int y2; Tcl_Obj *listObj; } *data = clientData; if ((data->x2 < drawArgs->x + drawArgs->indent) || (data->x1 >= drawArgs->x + drawArgs->width)) return 0; subListObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(tree->interp, subListObj, TreeColumn_ToObj(tree, spanPtr->treeColumn)); if (drawArgs->style != NULL) { StyleDrawArgs drawArgsCopy = *drawArgs; TreeStyle_Identify2(&drawArgsCopy, data->x1, data->y1, data->x2, data->y2, subListObj); } Tcl_ListObjAppendElement(tree->interp, data->listObj, subListObj); return drawArgs->x + drawArgs->width >= data->x2; } /* *---------------------------------------------------------------------- * * TreeItem_Identify2 -- * * Determine which columns and elements intersect the given * area. This is used by the [marquee identify] widget command. * * Results: * If the Item is not ReallyVisible() or no columns are visible * then listObj is untouched. Otherwise the list is appended * with C {E ...} C {E...}. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_Identify2( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int x1, int y1, /* Top-left of area to hit-test. */ int x2, int y2, /* Bottom-right of area to hit-test. */ Tcl_Obj *listObj /* Initialized list object. */ ) { int left, top, width, height; struct { int x1; int y1; int x2; int y2; Tcl_Obj *listObj; } clientData; if (Tree_ItemBbox(tree, item, COLUMN_LOCK_NONE, &left, &top, &width, &height) < 0) return; /* Tree_ItemBbox returns canvas coords. x1 etc are canvas coords. */ clientData.x1 = x1; clientData.y1 = y1; clientData.x2 = x2; clientData.y2 = y2; clientData.listObj = listObj; TreeItem_WalkSpans(tree, item, COLUMN_LOCK_NONE, left, top, width, height, SpanWalkProc_Identify2, (ClientData) &clientData); } /* *---------------------------------------------------------------------- * * SpanWalkProc_GetRects -- * * Callback routine to TreeItem_WalkSpans for TreeItem_GetRects. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SpanWalkProc_GetRects( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { int objc; Tcl_Obj *CONST *objv; struct { TreeColumn treeColumn; int count; Tcl_Obj *CONST *objv; XRectangle *rects; int result; } *data = clientData; if (spanPtr->treeColumn != data->treeColumn) return 0; /* Bounds of span. */ if (data->count == 0) { /* Not sure why I add 'indent' but for compatibility I will leave * it in. */ data->rects[0].x = drawArgs->x + drawArgs->indent; data->rects[0].y = drawArgs->y; data->rects[0].width = drawArgs->width - drawArgs->indent; data->rects[0].height = drawArgs->height; data->result = 1; /* # of rects */ return 1; /* stop */ } if (drawArgs->style == NULL) { NoStyleMsg(tree, item, TreeColumn_Index(spanPtr->treeColumn)); data->result = -1; /* error */ return 1; /* stop */ } if (data->count == -1) { /* All the elements. */ objc = 0; objv = NULL; } else { objc = data->count; objv = data->objv; } data->result = TreeStyle_GetElemRects(drawArgs, objc, objv, data->rects); return 1; /* stop */ } /* *---------------------------------------------------------------------- * * TreeItem_GetRects -- * * Returns zero or more bounding boxes for an item-column or * element(s) in an item-column. * * Results: * If the item is not visible, or has zero height/width, or the given * column is obscurred by a preceding span, or the column has zero * width or is not visible, the return value is zero. * * If count==0, the bounding box of the span is returned and the * return value is 1 (for a single rect). * * If count!=0, and the item-column does not have a style assigned, an * error is left in the interpreter result and the return value is -1. * * If count==-1, the bounding box of each element in the style is * returned and the return value is the number of elements in the style. * * If count>0, the bounding box of each element specified by the objv[] * array is returned and the return value is equal to count. If any of * the objv[] elements in not in the style, an error is left in the * interpreter result and the return value is -1. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetRects( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeColumn treeColumn, /* The column to get rects for. */ int count, /* -1 means get rects for all elements. * 0 means get bounds of the span. * 1+ means objv[] contains names of elements * to get rects for. */ Tcl_Obj *CONST objv[], /* Array of element names or NULL. */ XRectangle rects[] /* Out: returned bounding boxes. */ ) { int left, top, width, height; int lock = TreeColumn_Lock(treeColumn); struct { TreeColumn treeColumn; int count; Tcl_Obj *CONST *objv; XRectangle *rects; int result; } clientData; if (Tree_ItemBbox(tree, item, lock, &left, &top, &width, &height) < 0) return 0; clientData.treeColumn = treeColumn; clientData.count = count; clientData.objv = objv; clientData.rects = rects; clientData.result = 0; /* -1 error, 0 no rects, 1+ success */ TreeItem_WalkSpans(tree, item, lock, left, top, width, height, SpanWalkProc_GetRects, (ClientData) &clientData); return clientData.result; } /* *---------------------------------------------------------------------- * * TreeItem_Init -- * * Perform item-related initialization when a new TreeCtrl is * created. * * Results: * TCL_OK. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ int TreeItem_Init( TreeCtrl *tree /* Widget info. */ ) { BooleanFlagCO_Init(itemOptionSpecs, "-button", ITEM_FLAG_BUTTON); BooleanFlagCO_Init(itemOptionSpecs, "-visible", ITEM_FLAG_VISIBLE); tree->itemOptionTable = Tk_CreateOptionTable(tree->interp, itemOptionSpecs); tree->root = Item_AllocRoot(tree); tree->activeItem = tree->root; /* always non-null */ tree->anchorItem = tree->root; /* always non-null */ return TCL_OK; } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeDisplay.c0000644000175000017500000057742210674273023025450 0ustar domibeldomibel/* * tkTreeDisplay.c -- * * This module implements treectrl widget's main display code. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: tkTreeDisplay.c,v 1.2 2007-09-19 19:18:43 barre Exp $ */ #include "tkTreeCtrl.h" /* Window -> Canvas */ #define W2Cy(y) ((y) + tree->yOrigin) #define DW2Cy(y) ((y) + dInfo->yOrigin) #define COMPLEX_WHITESPACE typedef struct TreeDInfo_ TreeDInfo_; typedef struct RItem RItem; typedef struct Range Range; typedef struct DItem DItem; static void Range_RedoIfNeeded(TreeCtrl *tree); static int Range_TotalWidth(TreeCtrl *tree, Range *range_); static int Range_TotalHeight(TreeCtrl *tree, Range *range_); static void Range_Redo(TreeCtrl *tree); static Range *Range_UnderPoint(TreeCtrl *tree, int *x_, int *y_, int nearest); static RItem *Range_ItemUnderPoint(TreeCtrl *tree, Range *range, int *x_, int *y_); /* One of these per TreeItem. */ struct RItem { TreeItem item; /* The item. */ Range *range; /* Range the item is in. */ int size; /* Height or width consumed in Range. */ int offset; /* Vertical or horizontal offset in Range. */ int index; /* 0-based index in Range. */ }; /* A collection of visible TreeItems. */ struct Range { RItem *first; RItem *last; int totalWidth; int totalHeight; int index; /* 0-based index in list of Ranges. */ int offset; /* vertical/horizontal offset from canvas * top/left. */ Range *prev; Range *next; }; typedef struct DItemArea { int x; /* Where it should be drawn, window coords. */ int width; /* Current width. */ int dirty[4]; /* Dirty area in item coords. */ #define DITEM_DIRTY 0x0001 #define DITEM_ALL_DIRTY 0x0002 int flags; } DItemArea; /* Display information for a TreeItem. */ struct DItem { #ifdef TREECTRL_DEBUG char magic[4]; #endif TreeItem item; int y; /* Where it should be drawn, window coords. */ int height; /* Current height. */ DItemArea area; DItemArea left, right; int oldX, oldY; /* Where it was last drawn, window coords. */ Range *range; /* Range the TreeItem is in. */ int index; /* Used for alternating background colors. */ int oldIndex; /* Used for alternating background colors. */ int *spans; /* span[n] is the column index of the item * column displayed at the n'th tree column. */ DItem *next; }; typedef struct ColumnInfo { TreeColumn column; int offset; /* Last seen x-offset */ int width; /* Last seen column width */ } ColumnInfo; /* Display information for a TreeCtrl. */ struct TreeDInfo_ { GC scrollGC; int xOrigin; /* Last seen TreeCtrl.xOrigin */ int yOrigin; /* Last seen TreeCtrl.yOrigin */ int totalWidth; /* Last seen Tree_TotalWidth() */ int totalHeight; /* Last seen Tree_TotalHeight() */ ColumnInfo *columns; /* Last seen offset & width of each column */ int columnsSize; /* Num elements in columns[] */ int headerHeight; /* Last seen TreeCtrl.headerHeight */ DItem *dItem; /* Head of list for each displayed item */ DItem *dItemLast; /* Temp for UpdateDInfo() */ DItem *dItemFree; /* List of unused DItems */ Range *rangeFirst; /* Head of Ranges */ Range *rangeLast; /* Tail of Ranges */ Range *rangeFirstD; /* First range with valid display info */ Range *rangeLastD; /* Last range with valid display info */ RItem *rItem; /* Block of RItems for all Ranges */ int rItemMax; /* size of rItem[] */ int itemHeight; /* Observed max TreeItem height */ int itemWidth; /* Observed max TreeItem width */ Pixmap pixmap; /* DOUBLEBUFFER_WINDOW */ int dirty[4]; /* DOUBLEBUFFER_WINDOW */ int flags; /* DINFO_XXX */ int xScrollIncrement; /* Last seen TreeCtr.xScrollIncrement */ int yScrollIncrement; /* Last seen TreeCtr.yScrollIncrement */ int *xScrollIncrements; /* When tree->xScrollIncrement is zero */ int *yScrollIncrements; /* When tree->yScrollIncrement is zero */ int xScrollIncrementCount; /* Size of xScrollIncrements. */ int yScrollIncrementCount; /* Size of yScrollIncrements. */ int incrementTop; /* yScrollIncrement[] index of item at top */ int incrementLeft; /* xScrollIncrement[] index of item at left */ TkRegion wsRgn; /* Region containing whitespace */ #ifdef COMPLEX_WHITESPACE int complexWhitespace; #endif Tcl_HashTable itemVisHash; /* Table of visible items */ int requests; /* Incremented for every call to Tree_EventuallyRedraw */ int bounds[4], empty; /* Bounds of TREE_AREA_CONTENT */ int boundsL[4], emptyL; /* Bounds of TREE_AREA_LEFT */ int boundsR[4], emptyR; /* Bounds of TREE_AREA_RIGHT */ int widthOfColumnsLeft; /* Last seen Tree_WidthOfLeftColumns() */ int widthOfColumnsRight; /* Last seen Tree_WidthOfRightColumns() */ Range *rangeLock; /* If there is no Range for non-locked * columns, this range holds the vertical * offset and height of each ReallyVisible * item for displaying locked columns. */ }; #ifdef COMPLEX_WHITESPACE static int ComplexWhitespace(TreeCtrl *tree); #endif /*========*/ void Tree_FreeItemRInfo(TreeCtrl *tree, TreeItem item) { TreeItem_SetRInfo(tree, item, NULL); } static Range * Range_Free(TreeCtrl *tree, Range *range) { Range *next = range->next; WFREE(range, Range); return next; } /* *---------------------------------------------------------------------- * * Range_Redo -- * * This procedure puts all ReallyVisible() TreeItems into a list of * Ranges. If tree->wrapMode is TREE_WRAP_NONE there will only be a * single Range. * * Results: * None. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Range_Redo( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *rangeList = dInfo->rangeFirst; Range *range; RItem *rItem; TreeItem item = tree->root; int fixedWidth = -1, stepWidth = -1; int wrapCount = 0, wrapPixels = 0; int count, pixels, rItemCount = 0; int rangeIndex = 0, itemIndex; if (tree->debug.enable && tree->debug.display) dbwin("Range_Redo %s\n", Tk_PathName(tree->tkwin)); /* Update column variables */ (void) Tree_WidthOfColumns(tree); dInfo->rangeFirst = NULL; dInfo->rangeLast = NULL; if (tree->columnCountVis < 1) goto freeRanges; switch (tree->wrapMode) { case TREE_WRAP_NONE: break; case TREE_WRAP_ITEMS: wrapCount = tree->wrapArg; break; case TREE_WRAP_PIXELS: wrapPixels = tree->wrapArg; break; case TREE_WRAP_WINDOW: wrapPixels = tree->vertical ? Tree_ContentHeight(tree) : Tree_ContentWidth(tree); if (wrapPixels < 0) wrapPixels = 0; break; } /* For horizontal layout with wrapping I need to know how wide each item * is. This is the same block of code as in Range_TotalWidth */ if ((wrapPixels > 0) && !tree->vertical) { /* More than one item column, so all items have the same width */ if (tree->columnCountVis > 1) fixedWidth = Tree_WidthOfColumns(tree); /* Single item column, fixed width for all items */ else if (tree->itemWidth > 0) fixedWidth = tree->itemWidth; /* Single item column, fixed width for all items */ /* THIS IS FOR COMPATIBILITY ONLY */ else if (TreeColumn_FixedWidth(tree->columnVis) != -1) fixedWidth = TreeColumn_FixedWidth(tree->columns); /* Single item column, want all items same width */ else if (tree->itemWidthEqual #ifdef DEPRECATED || TreeColumn_WidthHack(tree->columnVis) #endif /* DEPRECATED */ ) { fixedWidth = TreeColumn_WidthOfItems(tree->columnVis); /* Each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ if ((stepWidth != -1) && (fixedWidth % stepWidth)) fixedWidth += stepWidth - fixedWidth % stepWidth; /* Single item column, variable item width */ } else { /* Each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ } } /* Speed up ReallyVisible() and get itemVisCount */ Tree_UpdateItemIndex(tree); if (dInfo->rItemMax < tree->itemVisCount) { dInfo->rItem = (RItem *) ckrealloc((char *) dInfo->rItem, tree->itemVisCount * sizeof(RItem)); dInfo->rItemMax = tree->itemVisCount; } if (!TreeItem_ReallyVisible(tree, item)) item = TreeItem_NextVisible(tree, item); while (item != NULL) { if (rangeList == NULL) range = (Range *) ckalloc(sizeof(Range)); else { range = rangeList; rangeList = rangeList->next; } memset(range, '\0', sizeof(Range)); range->totalWidth = -1; range->totalHeight = -1; range->index = rangeIndex++; count = 0; pixels = 0; itemIndex = 0; while (1) { rItem = dInfo->rItem + rItemCount; if (rItemCount >= dInfo->rItemMax) panic("rItemCount > dInfo->rItemMax"); if (range->first == NULL) range->first = range->last = rItem; TreeItem_SetRInfo(tree, item, (TreeItemRInfo) rItem); rItem->item = item; rItem->range = range; rItem->index = itemIndex; /* Range must be <= this number of pixels */ if (wrapPixels > 0) { rItem->offset = pixels; if (tree->vertical) { rItem->size = TreeItem_Height(tree, item); } else { if (fixedWidth != -1) { rItem->size = fixedWidth; } else { TreeItemColumn itemColumn = TreeItem_FindColumn(tree, item, TreeColumn_Index(tree->columnVis)); if (itemColumn != NULL) { int columnWidth = TreeItemColumn_NeededWidth(tree, item, itemColumn); if (tree->columnTreeVis) columnWidth += TreeItem_Indent(tree, item); rItem->size = columnWidth; } else rItem->size = 0; if ((stepWidth != -1) && (rItem->size % stepWidth)) rItem->size += stepWidth - rItem->size % stepWidth; } } /* Too big */ if (pixels + rItem->size > wrapPixels) { /* Ensure at least one item is in this Range */ if (itemIndex == 0) { pixels += rItem->size; rItemCount++; } break; } pixels += rItem->size; } range->last = rItem; itemIndex++; rItemCount++; if (++count == wrapCount) break; item = TreeItem_NextVisible(tree, item); if (item == NULL) break; } /* Since we needed to calculate the height or width of this range, * we don't need to do it later in Range_TotalWidth/Height() */ if (wrapPixels > 0) { if (tree->vertical) range->totalHeight = pixels; else range->totalWidth = pixels; } if (dInfo->rangeFirst == NULL) dInfo->rangeFirst = range; else { range->prev = dInfo->rangeLast; dInfo->rangeLast->next = range; } dInfo->rangeLast = range; item = TreeItem_NextVisible(tree, range->last->item); } freeRanges: while (rangeList != NULL) rangeList = Range_Free(tree, rangeList); /* If there are no visible non-locked columns, we won't have a Range. * But we need to know the offset/size of each item for drawing any * locked columns (and for vertical scrolling... and hit testing). */ if (dInfo->rangeLock != NULL) { (void) Range_Free(tree, dInfo->rangeLock); dInfo->rangeLock = NULL; } (void) Tree_WidthOfColumns(tree); /* update columnCountVisLeft etc */ if ((dInfo->rangeFirst == NULL) && (tree->columnCountVisLeft || tree->columnCountVisRight)) { /* Speed up ReallyVisible() and get itemVisCount */ Tree_UpdateItemIndex(tree); if (tree->itemVisCount == 0) return; if (dInfo->rItemMax < tree->itemVisCount) { dInfo->rItem = (RItem *) ckrealloc((char *) dInfo->rItem, tree->itemVisCount * sizeof(RItem)); dInfo->rItemMax = tree->itemVisCount; } dInfo->rangeLock = (Range *) ckalloc(sizeof(Range)); range = dInfo->rangeLock; pixels = 0; itemIndex = 0; rItem = dInfo->rItem; item = tree->root; if (!TreeItem_ReallyVisible(tree, item)) item = TreeItem_NextVisible(tree, item); while (item != NULL) { rItem->item = item; rItem->range = range; rItem->size = TreeItem_Height(tree, item); rItem->offset = pixels; rItem->index = itemIndex++; TreeItem_SetRInfo(tree, item, (TreeItemRInfo) rItem); pixels += rItem->size; rItem++; item = TreeItem_NextVisible(tree, item); } range->offset = 0; range->first = dInfo->rItem; range->last = dInfo->rItem + tree->itemVisCount - 1; range->totalWidth = 1; range->totalHeight = pixels; range->prev = range->next = NULL; } } /* *---------------------------------------------------------------------- * * Range_TotalWidth -- * * Return the width of a Range. The width is only calculated if * it hasn't been done yet by Range_Redo(). * * Results: * Pixel width of the Range. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Range_TotalWidth( TreeCtrl *tree, /* Widget info. */ Range *range /* Range to return the width of. */ ) { TreeItem item; TreeItemColumn itemColumn; RItem *rItem; int fixedWidth = -1, stepWidth = -1; int itemWidth; if (range->totalWidth >= 0) return range->totalWidth; if (tree->vertical) { /* More than one item column, so all ranges have the same width */ if (tree->columnCountVis > 1) return range->totalWidth = Tree_WidthOfColumns(tree); /* If wrapping is disabled, then use the column width, * since it may expand to fill the window */ if (tree->wrapMode == TREE_WRAP_NONE) return range->totalWidth = TreeColumn_UseWidth(tree->columnVis); /* Single item column, fixed width for all ranges */ if (tree->itemWidth > 0) return range->totalWidth = tree->itemWidth; /* Single item column, fixed width for all ranges */ /* THIS IS FOR COMPATIBILITY ONLY */ if (TreeColumn_FixedWidth(tree->columnVis) != -1) return range->totalWidth = TreeColumn_FixedWidth(tree->columnVis); /* Single item column, each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ /* Single item column, want all items same width */ if (tree->itemWidthEqual #ifdef DEPRECATED || TreeColumn_WidthHack(tree->columnVis) #endif /* DEPRECATED */ ) { range->totalWidth = TreeColumn_WidthOfItems(tree->columnVis); if ((stepWidth != -1) && (range->totalWidth % stepWidth)) range->totalWidth += stepWidth - range->totalWidth % stepWidth; return range->totalWidth; } /* Max needed width of items in this range */ range->totalWidth = 0; rItem = range->first; while (1) { item = rItem->item; itemColumn = TreeItem_FindColumn(tree, item, TreeColumn_Index(tree->columnVis)); if (itemColumn != NULL) itemWidth = TreeItemColumn_NeededWidth(tree, item, itemColumn); else itemWidth = 0; if (tree->columnTreeVis) itemWidth += TreeItem_Indent(tree, item); if (itemWidth > range->totalWidth) range->totalWidth = itemWidth; if (rItem == range->last) break; rItem++; } if ((stepWidth != -1) && (range->totalWidth % stepWidth)) range->totalWidth += stepWidth - range->totalWidth % stepWidth; return range->totalWidth; } else { /* More than one item column, so all items have the same width */ if (tree->columnCountVis > 1) fixedWidth = Tree_WidthOfColumns(tree); /* Single item column, fixed width for all items */ else if (tree->itemWidth > 0) fixedWidth = tree->itemWidth; /* Single item column, fixed width for all items */ /* THIS IS FOR COMPATIBILITY ONLY */ else if (TreeColumn_FixedWidth(tree->columnVis) != -1) fixedWidth = TreeColumn_FixedWidth(tree->columnVis); /* Single item column, want all items same width */ else if (tree->itemWidthEqual #ifdef DEPRECATED || TreeColumn_WidthHack(tree->columnVis) #endif /* DEPRECATED */ ) { fixedWidth = TreeColumn_WidthOfItems(tree->columnVis); /* Each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ if ((stepWidth != -1) && (fixedWidth % stepWidth)) fixedWidth += stepWidth - fixedWidth % stepWidth; } /* Single item column, variable item width */ else { /* Each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ } /* Sum of widths of items in this range */ range->totalWidth = 0; rItem = range->first; while (1) { item = rItem->item; if (fixedWidth != -1) itemWidth = fixedWidth; else { itemColumn = TreeItem_FindColumn(tree, item, TreeColumn_Index(tree->columnVis)); if (itemColumn != NULL) itemWidth = TreeItemColumn_NeededWidth(tree, item, itemColumn); else itemWidth = 0; if (tree->columnTreeVis) itemWidth += TreeItem_Indent(tree, item); if ((stepWidth != -1) && (itemWidth % stepWidth)) itemWidth += stepWidth - itemWidth % stepWidth; } rItem = (RItem *) TreeItem_GetRInfo(tree, item); rItem->offset = range->totalWidth; rItem->size = itemWidth; range->totalWidth += itemWidth; if (rItem == range->last) break; rItem++; } return range->totalWidth; } } /* *---------------------------------------------------------------------- * * Range_TotalHeight -- * * Return the height of a Range. The height is only calculated if * it hasn't been done yet by Range_Redo(). * * Results: * Pixel height of the Range. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Range_TotalHeight( TreeCtrl *tree, /* Widget info. */ Range *range /* Range to return the height of. */ ) { TreeItem item; RItem *rItem; int itemHeight; if (range->totalHeight >= 0) return range->totalHeight; range->totalHeight = 0; rItem = range->first; while (1) { item = rItem->item; itemHeight = TreeItem_Height(tree, item); if (tree->vertical) { rItem->offset = range->totalHeight; rItem->size = itemHeight; range->totalHeight += itemHeight; } else { if (itemHeight > range->totalHeight) range->totalHeight = itemHeight; } if (rItem == range->last) break; rItem++; } return range->totalHeight; } /* *---------------------------------------------------------------------- * * Tree_TotalWidth -- * * Return the width needed by all the Ranges. The width is only * recalculated if it was marked out-of-date. * * Results: * Pixel width of the "canvas". * * Side effects: * The list of Ranges will be recalculated if needed. * *---------------------------------------------------------------------- */ int Tree_TotalWidth( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range; int rangeWidth; Range_RedoIfNeeded(tree); if (tree->totalWidth >= 0) return tree->totalWidth; if (dInfo->rangeFirst == NULL) return tree->totalWidth = Tree_WidthOfColumns(tree); tree->totalWidth = 0; range = dInfo->rangeFirst; while (range != NULL) { rangeWidth = Range_TotalWidth(tree, range); if (tree->vertical) { range->offset = tree->totalWidth; tree->totalWidth += rangeWidth; } else { if (rangeWidth > tree->totalWidth) tree->totalWidth = rangeWidth; } range = range->next; } return tree->totalWidth; } /* *---------------------------------------------------------------------- * * Tree_TotalHeight -- * * Return the height needed by all the Ranges. The height is only * recalculated if it was marked out-of-date. * * Results: * Pixel height of the "canvas". * * Side effects: * The list of Ranges will be recalculated if needed. * *---------------------------------------------------------------------- */ int Tree_TotalHeight( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range; int rangeHeight; Range_RedoIfNeeded(tree); if (tree->totalHeight >= 0) return tree->totalHeight; tree->totalHeight = 0; range = dInfo->rangeFirst; while (range != NULL) { rangeHeight = Range_TotalHeight(tree, range); if (tree->vertical) { if (rangeHeight > tree->totalHeight) tree->totalHeight = rangeHeight; } else { range->offset = tree->totalHeight; tree->totalHeight += rangeHeight; } range = range->next; } /* If dInfo->rangeLock is not NULL, then we are displaying some items * in locked columns but no non-locked columns. */ if (dInfo->rangeLock != NULL) { if (dInfo->rangeLock->totalHeight > tree->totalHeight) tree->totalHeight = dInfo->rangeLock->totalHeight; } return tree->totalHeight; } /* *---------------------------------------------------------------------- * * Range_UnderPoint -- * * Return the Range containing the given coordinates. * * Results: * Range containing the coordinates or NULL if the point is * outside any Range. * * Side effects: * The list of Ranges will be recalculated if needed. * *---------------------------------------------------------------------- */ static Range * Range_UnderPoint( TreeCtrl *tree, /* Widget info. */ int *x_, /* In: window x coordinate. * Out: x coordinate relative to the top-left * of the Range. */ int *y_, /* In: window y coordinate. * Out: y coordinate relative to the top-left * of the Range. */ int nearest /* TRUE if the Range nearest the coordinates * should be returned. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range; int x = *x_, y = *y_; Range_RedoIfNeeded(tree); if ((Tree_TotalWidth(tree) <= 0) || (Tree_TotalHeight(tree) <= 0)) return NULL; range = dInfo->rangeFirst; if (nearest) { int minX, minY, maxX, maxY; if (!Tree_AreaBbox(tree, TREE_AREA_CONTENT, &minX, &minY, &maxX, &maxY)) return NULL; /* Keep inside borders and header. Perhaps another flag needed. */ if (x < minX) x = minX; if (x >= maxX) x = maxX - 1; if (y < minY) y = minY; if (y >= maxY) y = maxY - 1; } /* Window -> canvas */ x += tree->xOrigin; y += tree->yOrigin; if (nearest) { if (x < 0) x = 0; if (x >= Tree_TotalWidth(tree)) x = Tree_TotalWidth(tree) - 1; if (y < 0) y = 0; if (y >= Tree_TotalHeight(tree)) y = Tree_TotalHeight(tree) - 1; } else { if (x < 0) return NULL; if (x >= Tree_TotalWidth(tree)) return NULL; if (y < 0) return NULL; if (y >= Tree_TotalHeight(tree)) return NULL; } if (tree->vertical) { while (range != NULL) { if ((x >= range->offset) && (x < range->offset + range->totalWidth)) { if (nearest || (y < range->totalHeight)) { (*x_) = x - range->offset; (*y_) = MIN(y, range->totalHeight - 1); return range; } return NULL; } range = range->next; } return NULL; } else { while (range != NULL) { if ((y >= range->offset) && (y < range->offset + range->totalHeight)) { if (nearest || (x < range->totalWidth)) { (*x_) = MIN(x, range->totalWidth - 1); (*y_) = y - range->offset; return range; } return NULL; } range = range->next; } return NULL; } } /* *---------------------------------------------------------------------- * * Range_ItemUnderPoint -- * * Return the RItem containing the given x and/or y coordinates. * * Results: * RItem containing the coordinates. Panics() if no RItem is found. * * Side effects: * None. * *---------------------------------------------------------------------- */ static RItem * Range_ItemUnderPoint( TreeCtrl *tree, /* Widget info. */ Range *range, /* Range to search. */ int *x_, /* In: x coordinate relative to top-left of * the Range. * Out: x coordinate relative to top-left of * the returned RItem. * May be NULL if y_ is not NULL. */ int *y_ /* In: y coordinate relative to top-left of * the Range. * Out: y coordinate relative to top-left of * the returned RItem. * May be NULL if x_ is not NULL. */ ) { RItem *rItem; int x = -666, y = -666; int i, l, u; if (x_ != NULL) { x = (*x_); if (x < 0 || x >= range->totalWidth) goto panicNow; } if (y_ != NULL) { y = (*y_); if (y < 0 || y >= range->totalHeight) goto panicNow; } if (tree->vertical) { /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem = range->first + i; if ((y >= rItem->offset) && (y < rItem->offset + rItem->size)) { /* Range -> item coords */ if (x_ != NULL) (*x_) = x; if (y_ != NULL) (*y_) = y - rItem->offset; return rItem; } if (y < rItem->offset) u = i - 1; else l = i + 1; } } else { /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem = range->first + i; if ((x >= rItem->offset) && (x < rItem->offset + rItem->size)) { /* Range -> item coords */ if (x_ != NULL) (*x_) = x - rItem->offset; if (y_ != NULL) (*y_) = y; return rItem; } if (x < rItem->offset) u = i - 1; else l = i + 1; } } panicNow: panic("Range_ItemUnderPoint: can't find TreeItem in Range: x %d y %d W %d H %d", x, y, range->totalWidth, range->totalHeight); return NULL; } /* *---------------------------------------------------------------------- * * Increment_AddX -- * * Appends one or more values to the list of horizontal scroll * increments. * * Results: * New size of DInfo.xScrollIncrements. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static int Increment_AddX( TreeCtrl *tree, /* Widget info. */ int offset, /* Offset to add. */ int size /* Current size of DInfo.xScrollIncrements. */ ) { TreeDInfo dInfo = tree->dInfo; int visWidth = Tree_ContentWidth(tree); while ((visWidth > 1) && (offset - dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] > visWidth)) { size = Increment_AddX(tree, dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] + visWidth, size); } if (dInfo->xScrollIncrementCount + 1 > size) { size *= 2; dInfo->xScrollIncrements = (int *) ckrealloc( (char *) dInfo->xScrollIncrements, size * sizeof(int)); } dInfo->xScrollIncrements[dInfo->xScrollIncrementCount++] = offset; return size; } /* *---------------------------------------------------------------------- * * Increment_AddY -- * * Appends one or more values to the list of vertical scroll * increments. * * Results: * New size of DInfo.yScrollIncrements. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static int Increment_AddY( TreeCtrl *tree, /* Widget info. */ int offset, /* Offset to add. */ int size /* Current size of DInfo.yScrollIncrements. */ ) { TreeDInfo dInfo = tree->dInfo; int visHeight = Tree_ContentHeight(tree); while ((visHeight > 1) && (offset - dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] > visHeight)) { size = Increment_AddY(tree, dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] + visHeight, size); } if (dInfo->yScrollIncrementCount + 1 > size) { size *= 2; dInfo->yScrollIncrements = (int *) ckrealloc( (char *) dInfo->yScrollIncrements, size * sizeof(int)); } dInfo->yScrollIncrements[dInfo->yScrollIncrementCount++] = offset; return size; } /* *---------------------------------------------------------------------- * * RItemsToIncrementsX -- * * Recalculate the list of horizontal scroll increments. This gets * called when the TreeCtrl -orient option is "horizontal" and * -xscrollincrement option is "". * * Results: * DInfo.xScrollIncrements is updated if the canvas width is > 0. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void RItemsToIncrementsX( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range, *rangeFirst = dInfo->rangeFirst; RItem *rItem; int visWidth = Tree_ContentWidth(tree); int totalWidth = Tree_TotalWidth(tree); int x1, x2, x; int size; if (totalWidth <= 0 /* dInfo->rangeFirst == NULL */) return; size = 10; dInfo->xScrollIncrements = (int *) ckalloc(size * sizeof(int)); if (rangeFirst == NULL) { /* Only the column headers are shown. */ } else if (rangeFirst->next == NULL) { /* A single horizontal range is easy. Add one increment for the * left edge of each item. */ rItem = rangeFirst->first; while (1) { size = Increment_AddX(tree, rItem->offset, size); if (rItem == rangeFirst->last) break; rItem++; } } else { /* First increment is zero */ dInfo->xScrollIncrements[dInfo->xScrollIncrementCount++] = 0; x1 = 0; while (1) { x2 = totalWidth; for (range = rangeFirst; range != NULL; range = range->next) { if (x1 >= range->totalWidth) continue; /* Find RItem whose right side is >= x1 by smallest amount */ x = x1; rItem = Range_ItemUnderPoint(tree, range, &x, NULL); if (rItem->offset + rItem->size < x2) x2 = rItem->offset + rItem->size; } if (x2 == totalWidth) break; size = Increment_AddX(tree, x2, size); x1 = x2; } } if ((visWidth > 1) && (totalWidth - dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] > visWidth)) { Increment_AddX(tree, totalWidth, size); dInfo->xScrollIncrementCount--; dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] = totalWidth - visWidth; } } /* *---------------------------------------------------------------------- * * RItemsToIncrementsY -- * * Recalculate the list of vertical scroll increments. This gets * called when the TreeCtrl -orient option is "vertical" and * -yscrollincrement option is "". * * Results: * DInfo.yScrollIncrements is updated if the canvas height is > 0. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void RItemsToIncrementsY( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range, *rangeFirst; RItem *rItem; int visHeight = Tree_ContentHeight(tree); int totalHeight = Tree_TotalHeight(tree); int y1, y2, y; int size; if (totalHeight <= 0 /* dInfo->rangeFirst == NULL */) return; size = 10; dInfo->yScrollIncrements = (int *) ckalloc(size * sizeof(int)); /* If only locked columns are visible, we still scroll vertically. */ rangeFirst = dInfo->rangeFirst; if (rangeFirst == NULL) rangeFirst = dInfo->rangeLock; if (rangeFirst->next == NULL) { /* A single vertical range is easy. Add one increment for the * top edge of each item. */ rItem = rangeFirst->first; while (1) { size = Increment_AddY(tree, rItem->offset, size); if (rItem == rangeFirst->last) break; rItem++; } } else { /* First increment is zero */ dInfo->yScrollIncrements[dInfo->yScrollIncrementCount++] = 0; y1 = 0; while (1) { y2 = totalHeight; for (range = rangeFirst; range != NULL; range = range->next) { if (y1 >= range->totalHeight) continue; /* Find RItem whose bottom edge is >= y1 by smallest amount */ y = y1; rItem = Range_ItemUnderPoint(tree, range, NULL, &y); if (rItem->offset + rItem->size < y2) y2 = rItem->offset + rItem->size; } if (y2 == totalHeight) break; size = Increment_AddY(tree, y2, size); y1 = y2; } } if ((visHeight > 1) && (totalHeight - dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] > visHeight)) { size = Increment_AddY(tree, totalHeight, size); dInfo->yScrollIncrementCount--; dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] = totalHeight - visHeight; } } /* *---------------------------------------------------------------------- * * RangesToIncrementsX -- * * Recalculate the list of horizontal scroll increments. This gets * called when the TreeCtrl -orient option is "vertical" and * -xscrollincrement option is "". * * Results: * DInfo.xScrollIncrements is updated if there are any Ranges. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void RangesToIncrementsX( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range = dInfo->rangeFirst; int visWidth = Tree_ContentWidth(tree); int totalWidth = Tree_TotalWidth(tree); int size; if (totalWidth <= visWidth) return; /* First increment is zero */ size = 10; dInfo->xScrollIncrements = (int *) ckalloc(size * sizeof(int)); dInfo->xScrollIncrements[dInfo->xScrollIncrementCount++] = 0; if (dInfo->rangeFirst != NULL) { range = dInfo->rangeFirst->next; while (range != NULL) { size = Increment_AddX(tree, range->offset, size); range = range->next; } } if ((visWidth > 1) && (totalWidth - dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] > visWidth)) { size = Increment_AddX(tree, totalWidth, size); dInfo->xScrollIncrementCount--; dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] = totalWidth - visWidth; } } /* *---------------------------------------------------------------------- * * RangesToIncrementsY -- * * Recalculate the list of vertical scroll increments. This gets * called when the TreeCtrl -orient option is "horizontal" and * -yscrollincrement option is "". * * Results: * DInfo.yScrollIncrements is updated if there are any Ranges. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void RangesToIncrementsY( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range = dInfo->rangeFirst; int visHeight = Tree_ContentHeight(tree); int totalHeight = Tree_TotalHeight(tree); int size; if (dInfo->rangeFirst == NULL) return; /* First increment is zero */ size = 10; dInfo->yScrollIncrements = (int *) ckalloc(size * sizeof(int)); dInfo->yScrollIncrements[dInfo->yScrollIncrementCount++] = 0; range = dInfo->rangeFirst->next; while (range != NULL) { size = Increment_AddY(tree, range->offset, size); range = range->next; } if ((visHeight > 1) && (totalHeight - dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] > visHeight)) { size = Increment_AddY(tree, totalHeight, size); dInfo->yScrollIncrementCount--; dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] = totalHeight - visHeight; } } /* *---------------------------------------------------------------------- * * Increment_Redo -- * * Recalculate the lists of scroll increments. * * Results: * DInfo.xScrollIncrements and DInfo.xScrollIncrements are updated. * Either may be set to NULL. The old values are freed, if any. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Increment_Redo( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; /* Free x */ if (dInfo->xScrollIncrements != NULL) ckfree((char *) dInfo->xScrollIncrements); dInfo->xScrollIncrements = NULL; dInfo->xScrollIncrementCount = 0; /* Free y */ if (dInfo->yScrollIncrements != NULL) ckfree((char *) dInfo->yScrollIncrements); dInfo->yScrollIncrements = NULL; dInfo->yScrollIncrementCount = 0; if (tree->vertical) { /* No xScrollIncrement is given. Snap to left edge of a Range */ if (tree->xScrollIncrement <= 0) RangesToIncrementsX(tree); /* No yScrollIncrement is given. Snap to top edge of a TreeItem */ if (tree->yScrollIncrement <= 0) RItemsToIncrementsY(tree); } else { /* No xScrollIncrement is given. Snap to left edge of a TreeItem */ if (tree->xScrollIncrement <= 0) RItemsToIncrementsX(tree); /* No yScrollIncrement is given. Snap to top edge of a Range */ if (tree->yScrollIncrement <= 0) RangesToIncrementsY(tree); } } /* *---------------------------------------------------------------------- * * Increment_RedoIfNeeded -- * * Recalculate the lists of scroll increments if needed. * * Results: * DInfo.xScrollIncrements and DInfo.xScrollIncrements may be * updated. * * Side effects: * Memory may be allocated. The list of Ranges will be recalculated * if needed. * *---------------------------------------------------------------------- */ static void Increment_RedoIfNeeded( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range_RedoIfNeeded(tree); /* Check for x|yScrollIncrement >0 changing to <=0 */ if (((dInfo->yScrollIncrement > 0) != (tree->yScrollIncrement > 0)) || ((dInfo->xScrollIncrement > 0) != (tree->xScrollIncrement > 0))) { dInfo->yScrollIncrement = tree->yScrollIncrement; dInfo->xScrollIncrement = tree->xScrollIncrement; dInfo->flags |= DINFO_REDO_INCREMENTS; } if (dInfo->flags & DINFO_REDO_INCREMENTS) { Increment_Redo(tree); dInfo->flags &= ~DINFO_REDO_INCREMENTS; } } /* *---------------------------------------------------------------------- * * B_IncrementFind -- * * Search a list of increments and return one nearest to the * given offset. * * Results: * Index of the nearest increment <= the given offset. * Panic() if no appropriate offset if found. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int B_IncrementFind( int *increments, /* DInfo.x|yScrollIncrements. */ int count, /* Length of increments[]. */ int offset /* Offset to search with. */ ) { int i, l, u, v; if (offset < 0) offset = 0; /* Binary search */ l = 0; u = count - 1; while (l <= u) { i = (l + u) / 2; v = increments[i]; if ((offset >= v) && ((i == count - 1) || (offset < increments[i + 1]))) return i; if (offset < v) u = i - 1; else l = i + 1; } panic("B_IncrementFind failed (count %d offset %d)", count, offset); return -1; } /* *---------------------------------------------------------------------- * * B_IncrementFindX -- * * Search DInfo.xScrollIncrements and return one nearest to the * given offset. * * Results: * Index of the nearest increment <= the given offset. * Panic() if no appropriate offset if found. * * Side effects: * None. * *---------------------------------------------------------------------- */ int B_IncrementFindX( TreeCtrl *tree, /* Widget info. */ int offset /* Offset to search with. */ ) { TreeDInfo dInfo = tree->dInfo; return B_IncrementFind( dInfo->xScrollIncrements, dInfo->xScrollIncrementCount, offset); } /* *---------------------------------------------------------------------- * * B_IncrementFindY -- * * Search DInfo.yScrollIncrements and return one nearest to the * given offset. * * Results: * Index of the nearest increment <= the given offset. * Panic() if no appropriate offset if found. * * Side effects: * None. * *---------------------------------------------------------------------- */ int B_IncrementFindY( TreeCtrl *tree, /* Widget info. */ int offset /* Offset to search with. */ ) { TreeDInfo dInfo = tree->dInfo; return B_IncrementFind( dInfo->yScrollIncrements, dInfo->yScrollIncrementCount, offset); } /* *-------------------------------------------------------------- * * B_XviewCmd -- * * This procedure is invoked to process the "xview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * NOTE: This procedure is called when the -xscrollincrement option * is unspecified. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ int B_XviewCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; TreeDInfo dInfo = tree->dInfo; if (objc == 2) { double fractions[2]; char buf[TCL_DOUBLE_SPACE * 2]; Tree_GetScrollFractionsX(tree, fractions); sprintf(buf, "%g %g", fractions[0], fractions[1]); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else { int count, index = 0, indexMax, offset, type; double fraction; int visWidth = Tree_ContentWidth(tree); int totWidth = Tree_TotalWidth(tree); if (visWidth < 0) visWidth = 0; if (totWidth <= visWidth) return TCL_OK; if (visWidth > 1) { /* Find incrementLeft when scrolled to right */ indexMax = Increment_FindX(tree, totWidth - visWidth); offset = Increment_ToOffsetX(tree, indexMax); if (offset < totWidth - visWidth) { indexMax++; offset = Increment_ToOffsetX(tree, indexMax); } /* Add some fake content to right */ if (offset + visWidth > totWidth) totWidth = offset + visWidth; } else { indexMax = Increment_FindX(tree, totWidth); visWidth = 1; } type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: return TCL_ERROR; case TK_SCROLL_MOVETO: offset = (int) (fraction * totWidth + 0.5); index = Increment_FindX(tree, offset); break; case TK_SCROLL_PAGES: offset = Tree_ContentLeft(tree) + tree->xOrigin; offset += (int) (count * visWidth * 0.9); index = Increment_FindX(tree, offset); if ((count > 0) && (index == Increment_FindX(tree, Tree_ContentLeft(tree) + tree->xOrigin))) index++; break; case TK_SCROLL_UNITS: index = dInfo->incrementLeft + count; break; } /* Don't scroll too far left */ if (index < 0) index = 0; /* Don't scroll too far right */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetX(tree, index); if ((index != dInfo->incrementLeft) || (tree->xOrigin != offset - Tree_ContentLeft(tree))) { dInfo->incrementLeft = index; tree->xOrigin = offset - Tree_ContentLeft(tree); Tree_EventuallyRedraw(tree); } } return TCL_OK; } /* *-------------------------------------------------------------- * * B_YviewCmd -- * * This procedure is invoked to process the "yview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * NOTE: This procedure is called when the -yscrollincrement option * is unspecified. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ int B_YviewCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; TreeDInfo dInfo = tree->dInfo; if (objc == 2) { double fractions[2]; char buf[TCL_DOUBLE_SPACE * 2]; Tree_GetScrollFractionsY(tree, fractions); sprintf(buf, "%g %g", fractions[0], fractions[1]); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else { int count, index = 0, indexMax, offset, type; double fraction; int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); if (visHeight < 0) visHeight = 0; if (totHeight <= visHeight) return TCL_OK; if (visHeight > 1) { /* Find incrementTop when scrolled to bottom */ indexMax = Increment_FindY(tree, totHeight - visHeight); offset = Increment_ToOffsetY(tree, indexMax); if (offset < totHeight - visHeight) { indexMax++; offset = Increment_ToOffsetY(tree, indexMax); } /* Add some fake content to bottom */ if (offset + visHeight > totHeight) totHeight = offset + visHeight; } else { indexMax = Increment_FindY(tree, totHeight); visHeight = 1; } type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: return TCL_ERROR; case TK_SCROLL_MOVETO: offset = (int) (fraction * totHeight + 0.5); index = Increment_FindY(tree, offset); break; case TK_SCROLL_PAGES: offset = Tree_ContentTop(tree) + tree->yOrigin; offset += (int) (count * visHeight * 0.9); index = Increment_FindY(tree, offset); if ((count > 0) && (index == Increment_FindY(tree, Tree_ContentTop(tree) + tree->yOrigin))) index++; break; case TK_SCROLL_UNITS: index = dInfo->incrementTop + count; break; } /* Don't scroll too far up */ if (index < 0) index = 0; /* Don't scroll too far down */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetY(tree, index); if ((index != dInfo->incrementTop) || (tree->yOrigin != offset - Tree_ContentTop(tree))) { dInfo->incrementTop = index; tree->yOrigin = offset - Tree_ContentTop(tree); Tree_EventuallyRedraw(tree); } } return TCL_OK; } /* *-------------------------------------------------------------- * * Tree_ItemUnderPoint -- * * Return a TreeItem containing the given coordinates. * * Results: * TreeItem token or NULL if no item contains the point. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ TreeItem Tree_ItemUnderPoint( TreeCtrl *tree, /* Widget info. */ int *x_, int *y_, /* In: window coordinates. * Out: coordinates relative to top-left * corner of the returned item. */ int nearest /* TRUE if the item nearest the coordinates * should be returned. */ ) { Range *range; RItem *rItem; int hit; hit = Tree_HitTest(tree, *x_, *y_); if (!nearest && ((hit == TREE_AREA_LEFT) || (hit == TREE_AREA_RIGHT))) { TreeDInfo dInfo = tree->dInfo; Range_RedoIfNeeded(tree); range = dInfo->rangeFirst; /* If range is NULL use dInfo->rangeLock. */ if (range == NULL) { if (dInfo->rangeLock == NULL) return NULL; range = dInfo->rangeLock; } if (*y_ + tree->yOrigin < range->totalHeight) { int x = *x_; int y = *y_; if (hit == TREE_AREA_RIGHT) { x -= Tree_ContentRight(tree); } else { x -= Tree_BorderLeft(tree); } /* Window -> canvas */ y += tree->yOrigin; rItem = Range_ItemUnderPoint(tree, range, NULL, &y); *x_ = x; *y_ = y; return rItem->item; } return NULL; } range = Range_UnderPoint(tree, x_, y_, nearest); if (range == NULL) return NULL; rItem = Range_ItemUnderPoint(tree, range, x_, y_); if (rItem != NULL) return rItem->item; return NULL; } /* *-------------------------------------------------------------- * * Tree_AreaBbox -- * * Return the bounding box of a visible area. * * Results: * Return value is TRUE if the area is non-empty. * * Side effects: * Column and item layout will be updated if needed. * *-------------------------------------------------------------- */ int Tree_AreaBbox( TreeCtrl *tree, int area, int *x1_, int *y1_, int *x2_, int *y2_ ) { int x1 = 0, y1 = 0, x2 = 0, y2 = 0; switch (area) { case TREE_AREA_HEADER: x1 = Tree_BorderLeft(tree); y1 = Tree_BorderTop(tree); x2 = Tree_BorderRight(tree); y2 = Tree_ContentTop(tree); break; case TREE_AREA_CONTENT: x1 = Tree_ContentLeft(tree); y1 = Tree_ContentTop(tree); x2 = Tree_ContentRight(tree); y2 = Tree_ContentBottom(tree); break; case TREE_AREA_LEFT: x1 = Tree_BorderLeft(tree); y1 = Tree_ContentTop(tree); x2 = Tree_ContentLeft(tree); y2 = Tree_ContentBottom(tree); /* Don't overlap right-locked columns. */ if (x2 > Tree_ContentRight(tree)) x2 = Tree_ContentRight(tree); break; case TREE_AREA_RIGHT: x1 = Tree_ContentRight(tree); y1 = Tree_ContentTop(tree); x2 = Tree_BorderRight(tree); y2 = Tree_ContentBottom(tree); break; } if (x2 <= x1 || y2 <= y1) return FALSE; if (x1 < Tree_BorderLeft(tree)) x1 = Tree_BorderLeft(tree); if (x2 > Tree_BorderRight(tree)) x2 = Tree_BorderRight(tree); if (y1 < Tree_BorderTop(tree)) y1 = Tree_BorderTop(tree); if (y2 > Tree_BorderBottom(tree)) y2 = Tree_BorderBottom(tree); *x1_ = x1; *y1_ = y1; *x2_ = x2; *y2_ = y2; return (x2 > x1) && (y2 > y1); } /* *-------------------------------------------------------------- * * Tree_HitTest -- * * Determine which are of the window contains the given point. * * Results: * Return value is one of the TREE_AREA_xxx constants. * * Side effects: * Column layout will be updated if needed. * *-------------------------------------------------------------- */ int Tree_HitTest( TreeCtrl *tree, int x, int y ) { if ((x < Tree_BorderLeft(tree)) || (x >= Tree_BorderRight(tree))) return TREE_AREA_NONE; if ((y < Tree_BorderTop(tree)) || (y >= Tree_BorderBottom(tree))) return TREE_AREA_NONE; if (y < Tree_HeaderBottom(tree)) { return TREE_AREA_HEADER; } /* Right-locked columns are drawn over the left. */ if (x >= Tree_ContentRight(tree)) { return TREE_AREA_RIGHT; } if (x < Tree_ContentLeft(tree)) { return TREE_AREA_LEFT; } if (Tree_ContentLeft(tree) >= Tree_ContentRight(tree)) { return TREE_AREA_NONE; } return TREE_AREA_CONTENT; } /* *-------------------------------------------------------------- * * Tree_ItemBbox -- * * Return the bounding box for an item. * * Results: * Return value is -1 if the item is not ReallyVisible() * or if there are no visible columns. The coordinates * are relative to the top-left corner of the canvas. * * Side effects: * Column layout will be updated if needed. * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ int Tree_ItemBbox( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item whose bbox is needed. */ int lock, int *x, int *y, /* Returned left and top. */ int *w, int *h /* Returned width and height. */ ) { Range *range; RItem *rItem; if (!TreeItem_ReallyVisible(tree, item)) return -1; /* Update columnCountVisXXX if needed */ (void) Tree_WidthOfColumns(tree); Range_RedoIfNeeded(tree); rItem = (RItem *) TreeItem_GetRInfo(tree, item); switch (lock) { case COLUMN_LOCK_LEFT: if (tree->columnCountVisLeft == 0) return -1; *x = Tree_BorderLeft(tree) + tree->xOrigin; /* window -> canvas */ *y = rItem->offset; *w = Tree_WidthOfLeftColumns(tree); *h = rItem->size; return 0; case COLUMN_LOCK_NONE: break; case COLUMN_LOCK_RIGHT: if (tree->columnCountVisRight == 0) return -1; *x = Tree_ContentRight(tree) + tree->xOrigin; /* window -> canvas */ *y = rItem->offset; *w = Tree_WidthOfRightColumns(tree); *h = rItem->size; return 0; } if (tree->columnCountVis < 1) return -1; range = rItem->range; if (tree->vertical) { (*x) = range->offset; (*w) = range->totalWidth; (*y) = rItem->offset; (*h) = rItem->size; } else { (*x) = rItem->offset; (*w) = rItem->size; (*y) = range->offset; (*h) = range->totalHeight; } return 0; } /* *-------------------------------------------------------------- * * Tree_ItemLARB -- * * Return an adjacent item above, below, to the left or to the * right of the given item. * * Results: * An adjacent item or NULL if there is no such item. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ TreeItem Tree_ItemLARB( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to use as a reference. */ int vertical, /* TRUE if items are arranged * from top-to-bottom in each Range. */ int prev /* TRUE for above/left, * FALSE for below/right. */ ) { RItem *rItem, *rItem2; Range *range; int i, l, u; if (!TreeItem_ReallyVisible(tree, item) || (tree->columnCountVis < 1)) return NULL; Range_RedoIfNeeded(tree); rItem = (RItem *) TreeItem_GetRInfo(tree, item); if (vertical) { if (prev) { if (rItem == rItem->range->first) return NULL; rItem--; } else { if (rItem == rItem->range->last) return NULL; rItem++; } return rItem->item; } else { /* Find the previous range */ range = prev ? rItem->range->prev : rItem->range->next; if (range == NULL) return NULL; /* Find item with same index */ /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem2 = range->first + i; if (rItem2->index == rItem->index) return rItem2->item; if (rItem->index < rItem2->index) u = i - 1; else l = i + 1; } } return NULL; } TreeItem Tree_ItemLeft(TreeCtrl *tree, TreeItem item) { return Tree_ItemLARB(tree, item, !tree->vertical, TRUE); } TreeItem Tree_ItemAbove(TreeCtrl *tree, TreeItem item) { return Tree_ItemLARB(tree, item, tree->vertical, TRUE); } TreeItem Tree_ItemRight(TreeCtrl *tree, TreeItem item) { return Tree_ItemLARB(tree, item, !tree->vertical, FALSE); } TreeItem Tree_ItemBelow(TreeCtrl *tree, TreeItem item) { return Tree_ItemLARB(tree, item, tree->vertical, FALSE); } /* *-------------------------------------------------------------- * * Tree_ItemFL -- * * Return the first or last item in the same row or column * as the given item. * * Results: * First/last item or NULL if there is no such item. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ TreeItem Tree_ItemFL( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to use as a reference. */ int vertical, /* TRUE if items are arranged * from top-to-bottom in each Range. */ int first /* TRUE for top/left, * FALSE for bottom/right. */ ) { TreeDInfo dInfo = tree->dInfo; RItem *rItem, *rItem2; Range *range; int i, l, u; if (!TreeItem_ReallyVisible(tree, item) || (tree->columnCountVis < 1)) { return NULL; } Range_RedoIfNeeded(tree); rItem = (RItem *) TreeItem_GetRInfo(tree, item); if (vertical) { return (first ? rItem->range->first->item : rItem->range->last->item); } else { /* Find the first/last range */ range = first ? dInfo->rangeFirst : dInfo->rangeLast; /* Check next/prev range until happy */ while (1) { if (range == rItem->range) return item; /* Find item with same index */ /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem2 = range->first + i; if (rItem2->index == rItem->index) return rItem2->item; if (rItem->index < rItem2->index) u = i - 1; else l = i + 1; } range = first ? range->next : range->prev; } } /* return NULL; */ /* not reached */ } TreeItem Tree_ItemTop(TreeCtrl *tree, TreeItem item) { return Tree_ItemFL(tree, item, tree->vertical, TRUE); } TreeItem Tree_ItemBottom(TreeCtrl *tree, TreeItem item) { return Tree_ItemFL(tree, item, tree->vertical, FALSE); } TreeItem Tree_ItemLeftMost(TreeCtrl *tree, TreeItem item) { return Tree_ItemFL(tree, item, !tree->vertical, TRUE); } TreeItem Tree_ItemRightMost(TreeCtrl *tree, TreeItem item) { return Tree_ItemFL(tree, item, !tree->vertical, FALSE); } /* *-------------------------------------------------------------- * * Tree_ItemToRNC -- * * Return the row and column for the given item. * * Results: * A standard Tcl result. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ int Tree_ItemToRNC( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to get row n' column of. */ int *row, int *col /* Returned row and column. */ ) { RItem *rItem; if (!TreeItem_ReallyVisible(tree, item) || (tree->columnCountVis < 1)) return TCL_ERROR; Range_RedoIfNeeded(tree); rItem = (RItem *) TreeItem_GetRInfo(tree, item); if (tree->vertical) { (*row) = rItem->index; (*col) = rItem->range->index; } else { (*row) = rItem->range->index; (*col) = rItem->index; } return TCL_OK; } /* *-------------------------------------------------------------- * * Tree_RNCToItem -- * * Return the item at a given row and column. * * Results: * Token for the item. Never returns NULL unless there are no * Ranges. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ TreeItem Tree_RNCToItem( TreeCtrl *tree, /* Widget info. */ int row, int col /* Row and column. These values are * clipped to valid values. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range; RItem *rItem; int i, l, u; Range_RedoIfNeeded(tree); range = dInfo->rangeFirst; if (range == NULL) return NULL; if (row < 0) row = 0; if (col < 0) col = 0; if (tree->vertical) { if (col > dInfo->rangeLast->index) col = dInfo->rangeLast->index; while (range->index != col) range = range->next; rItem = range->last; if (row > rItem->index) row = rItem->index; /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem = range->first + i; if (rItem->index == row) break; if (row < rItem->index) u = i - 1; else l = i + 1; } } else { if (row > dInfo->rangeLast->index) row = dInfo->rangeLast->index; while (range->index != row) range = range->next; rItem = range->last; if (col > rItem->index) col = rItem->index; /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem = range->first + i; if (rItem->index == col) break; if (col < rItem->index) u = i - 1; else l = i + 1; } } return rItem->item; } /*=============*/ static void DisplayDelay(TreeCtrl *tree) { if (tree->debug.enable && tree->debug.display && tree->debug.displayDelay > 0) { #if !defined(WIN32) && !defined(MAC_TCL) && !defined(MAC_OSX_TK) XSync(tree->display, False); #endif Tcl_Sleep(tree->debug.displayDelay); } } /* *-------------------------------------------------------------- * * DItem_Alloc -- * * Allocate and initialize a new DItem, and store a pointer to it * in the given item. * * Results: * Pointer to the DItem which may come from an existing pool of * unused DItems. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static DItem * DItem_Alloc( TreeCtrl *tree, /* Widget info. */ RItem *rItem /* Range info for the item. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; dItem = (DItem *) TreeItem_GetDInfo(tree, rItem->item); if (dItem != NULL) panic("tried to allocate duplicate DItem"); /* Pop unused DItem from stack */ if (dInfo->dItemFree != NULL) { dItem = dInfo->dItemFree; dInfo->dItemFree = dItem->next; /* No free DItems, alloc a new one */ } else { dItem = (DItem *) ckalloc(sizeof(DItem)); } memset(dItem, '\0', sizeof(DItem)); #ifdef TREECTRL_DEBUG strncpy(dItem->magic, "MAGC", 4); #endif dItem->item = rItem->item; dItem->area.flags = DITEM_DIRTY | DITEM_ALL_DIRTY; dItem->left.flags = DITEM_DIRTY | DITEM_ALL_DIRTY; dItem->right.flags = DITEM_DIRTY | DITEM_ALL_DIRTY; TreeItem_SetDInfo(tree, rItem->item, (TreeItemDInfo) dItem); return dItem; } /* *-------------------------------------------------------------- * * DItem_Unlink -- * * Remove a DItem from a linked list of DItems. * * Results: * Pointer to the given list of DItems. * * Side effects: * None. * *-------------------------------------------------------------- */ static DItem * DItem_Unlink( DItem *head, /* First in linked list. */ DItem *dItem /* DItem to remove from list. */ ) { DItem *prev; if (head == dItem) head = dItem->next; else { for (prev = head; prev->next != dItem; prev = prev->next) { /* nothing */ } prev->next = dItem->next; } dItem->next = NULL; return head; } /* *-------------------------------------------------------------- * * DItem_Free -- * * Add a DItem to the pool of unused DItems. If the DItem belongs * to a TreeItem the pointer to the DItem is set to NULL in that * TreeItem. * * Results: * Pointer to the next DItem. * * Side effects: * None. * *-------------------------------------------------------------- */ static DItem * DItem_Free( TreeCtrl *tree, /* Widget info. */ DItem *dItem /* DItem to free. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *next = dItem->next; #ifdef TREECTRL_DEBUG if (strncmp(dItem->magic, "MAGC", 4) != 0) panic("DItem_Free: dItem.magic != MAGC"); #endif if (dItem->item != NULL) { TreeItem_SetDInfo(tree, dItem->item, (TreeItemDInfo) NULL); dItem->item = NULL; } /* Push unused DItem on the stack */ dItem->next = dInfo->dItemFree; dInfo->dItemFree = dItem; return next; } /* *-------------------------------------------------------------- * * FreeDItems -- * * Add a list of DItems to the pool of unused DItems, * optionally removing the DItems from the DInfo.dItem list. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void FreeDItems( TreeCtrl *tree, /* Widget info. */ DItem *first, /* First DItem to free. */ DItem *last, /* DItem after the last one to free. */ int unlink /* TRUE if the DItems should be removed * from the DInfo.dItem list. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *prev; if (unlink) { if (dInfo->dItem == first) dInfo->dItem = last; else { for (prev = dInfo->dItem; prev->next != first; prev = prev->next) { /* nothing */ } prev->next = last; } } while (first != last) first = DItem_Free(tree, first); } /* *-------------------------------------------------------------- * * Tree_ItemsInArea -- * * Return a list of items overlapping the given area. * * Results: * Initializes the given TreeItemList and appends any items * in the given area. * * Side effects: * The list of Ranges will be recalculated if needed. Memory may * be allocated. * *-------------------------------------------------------------- */ void Tree_ItemsInArea( TreeCtrl *tree, /* Widget info. */ TreeItemList *items, /* Uninitialized list. The caller must free * it with TreeItemList_Free. */ int minX, int minY, /* Left, top in canvas coordinates. */ int maxX, int maxY /* Right, bottom in canvas coordinates. * Points on the right/bottom edge are not * included in the area. */ ) { TreeDInfo dInfo = tree->dInfo; int x, y, rx = 0, ry = 0, ix, iy, dx, dy; Range *range; RItem *rItem; TreeItemList_Init(tree, items, 0); Range_RedoIfNeeded(tree); range = dInfo->rangeFirst; if (tree->vertical) { /* Find the first range which could be in the area horizontally */ while (range != NULL) { if ((range->offset < maxX) && (range->offset + range->totalWidth >= minX)) { rx = range->offset; ry = 0; break; } range = range->next; } } else { /* Find the first range which could be in the area vertically */ while (range != NULL) { if ((range->offset < maxY) && (range->offset + range->totalHeight >= minY)) { rx = 0; ry = range->offset; break; } range = range->next; } } if (range == NULL) return; while (range != NULL) { if ((rx + range->totalWidth > minX) && (ry + range->totalHeight > minY)) { if (tree->vertical) { /* Range coords */ dx = MAX(minX - rx, 0); dy = minY; } else { dx = minX; dy = MAX(minY - ry, 0); } ix = dx; iy = dy; rItem = Range_ItemUnderPoint(tree, range, &ix, &iy); /* Canvas coords of top-left of item */ x = rx + dx - ix; y = ry + dy - iy; while (1) { TreeItemList_Append(items, rItem->item); if (tree->vertical) { y += rItem->size; if (y >= maxY) break; } else { x += rItem->size; if (x >= maxX) break; } if (rItem == range->last) break; rItem++; } } if (tree->vertical) { if (rx + range->totalWidth >= maxX) break; rx += range->totalWidth; } else { if (ry + range->totalHeight >= maxY) break; ry += range->totalHeight; } range = range->next; } } #define DCOLUMN #ifdef DCOLUMN /* *-------------------------------------------------------------- * * GetOnScreenColumnsForItemAux -- * * Determine which columns of an item are onscreen. * * Results: * Sets the column list. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static void GetOnScreenColumnsForItemAux( TreeCtrl *tree, /* Widget info. */ DItem *dItem, /* Display info for an item. */ DItemArea *area, /* Layout info. */ int bounds[4], /* TREE_AREA_xxx bounds. */ int lock, /* Set of columns we care about. */ TreeColumnList *columns /* Initialized list to append to. */ ) { TreeDInfo dInfo = tree->dInfo; int minX, maxX, columnIndex = 0, x = 0, i, width; TreeColumn column; minX = MAX(area->x, bounds[0]); maxX = MIN(area->x + area->width, bounds[2]); minX -= area->x; maxX -= area->x; switch (lock) { case COLUMN_LOCK_LEFT: columnIndex = TreeColumn_Index(tree->columnLockLeft); break; case COLUMN_LOCK_NONE: columnIndex = TreeColumn_Index(tree->columnLockNone); break; case COLUMN_LOCK_RIGHT: columnIndex = TreeColumn_Index(tree->columnLockRight); break; } for (/* nothing */; columnIndex < tree->columnCount; columnIndex++) { column = dInfo->columns[columnIndex].column; if (TreeColumn_Lock(column) != lock) break; if (!TreeColumn_Visible(column)) continue; width = dInfo->columns[columnIndex].width; if (dItem->spans != NULL) { if (dItem->spans[columnIndex] != columnIndex) goto next; /* Start of a span */ for (i = columnIndex + 1; i < tree->columnCount && dItem->spans[i] == columnIndex; i++) { width += dInfo->columns[i].width; } columnIndex = i - 1; } if (x < maxX && x + width > minX) { TreeColumnList_Append(columns, column); } next: x += width; if (x >= maxX) break; } } /* *-------------------------------------------------------------- * * GetOnScreenColumnsForItem -- * * Determine which columns of an item are onscreen. * * Results: * Sets the column list. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static int GetOnScreenColumnsForItem( TreeCtrl *tree, /* Widget info. */ DItem *dItem, /* Display info for an item. */ TreeColumnList *columns /* Initialized list to append to. */ ) { TreeDInfo dInfo = tree->dInfo; if (!dInfo->emptyL) { GetOnScreenColumnsForItemAux(tree, dItem, &dItem->left, dInfo->boundsL, COLUMN_LOCK_LEFT, columns); } if (!dInfo->empty && dInfo->rangeFirst != NULL) { GetOnScreenColumnsForItemAux(tree, dItem, &dItem->area, dInfo->bounds, COLUMN_LOCK_NONE, columns); } if (!dInfo->emptyR) { GetOnScreenColumnsForItemAux(tree, dItem, &dItem->right, dInfo->boundsR, COLUMN_LOCK_RIGHT, columns); } return TreeColumnList_Count(columns); } /* *-------------------------------------------------------------- * * TrackOnScreenColumnsForItem -- * * Compares the list of onscreen columns for an item to the * list of previously-onscreen columns for the item. * * Results: * Hides window elements for columns that are no longer * onscreen. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static void TrackOnScreenColumnsForItem( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ Tcl_HashEntry *hPtr /* DInfo.itemVisHash entry. */ ) { TreeColumnList columns; TreeColumn column, *value; DItem *dItem; int i, j, count = 0, n = 0; Tcl_DString dString; TreeColumnList_Init(tree, &columns, 0); Tcl_DStringInit(&dString); /* dItem is NULL if the item just went offscreen. */ dItem = (DItem *) TreeItem_GetDInfo(tree, item); if (dItem != NULL) count = GetOnScreenColumnsForItem(tree, dItem, &columns); if (tree->debug.enable && tree->debug.display) DStringAppendf(&dString, "onscreen columns for item %d:", TreeItem_GetID(tree, item)); /* value is NULL if the item just came onscreen. */ value = (TreeColumn *) Tcl_GetHashValue(hPtr); if (value == NULL) { value = (TreeColumn *) ckalloc(sizeof(TreeColumn) * (count + 1)); value[0] = NULL; } /* Track newly-visible columns */ for (i = 0; i < count; i++) { column = TreeColumnList_Nth(&columns, i); for (j = 0; value[j] != NULL; j++) { if (column == value[j]) break; } if (value[j] == NULL) { if (tree->debug.enable && tree->debug.display) DStringAppendf(&dString, " +%d", TreeColumn_GetID(column)); n++; } } /* Track newly-hidden columns */ for (j = 0; value[j] != NULL; j++) { column = value[j]; for (i = 0; i < count; i++) { if (TreeColumnList_Nth(&columns, i) == column) break; } if (i == count) { TreeItemColumn itemColumn = TreeItem_FindColumn(tree, item, TreeColumn_Index(column)); if (itemColumn != NULL) { TreeStyle style = TreeItemColumn_GetStyle(tree, itemColumn); if (style != NULL) TreeStyle_OnScreen(tree, style, FALSE); } if (tree->debug.enable && tree->debug.display) DStringAppendf(&dString, " -%d", TreeColumn_GetID(column)); n++; } } if (FALSE && n && tree->debug.enable && tree->debug.display) dbwin("%s\n", Tcl_DStringValue(&dString)); /* Set the list of onscreen columns unless it is the same or the item * is hidden. */ if (n > 0 && dItem != NULL) { value = (TreeColumn *) ckrealloc((char *) value, sizeof(TreeColumn) * (count + 1)); memcpy(value, (TreeColumn *) columns.pointers, sizeof(TreeColumn) * count); value[count] = NULL; Tcl_SetHashValue(hPtr, (ClientData) value); } Tcl_DStringFree(&dString); TreeColumnList_Free(&columns); } #endif /* DCOLUMN */ /* *-------------------------------------------------------------- * * UpdateDInfoForRange -- * * Allocates or updates a DItem for every on-screen item in a Range. * If an item already has a DItem (because the item was previously * displayed), then the DItem may be marked dirty if there were * changes to the item's on-screen size or position. * * Results: * The return value is the possibly-updated dItemHead. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static DItem * UpdateDInfoForRange( TreeCtrl *tree, /* Widget info. */ DItem *dItemHead, /* Linked list of used DItems. */ Range *range, /* Range to update DItems for. */ RItem *rItem, /* First item in the Range we care about. */ int x, int y /* Left & top window coordinates of rItem. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; DItemArea *area; TreeItem item; int maxX, maxY; int index, indexVis; int bgImgWidth, bgImgHeight; if (tree->backgroundImage != NULL) Tk_SizeOfImage(tree->backgroundImage, &bgImgWidth, &bgImgHeight); maxX = Tree_ContentRight(tree); maxY = Tree_ContentBottom(tree); /* Top-to-bottom */ if (tree->vertical) { while (1) { item = rItem->item; /* Update item/style layout. This can be needed when using fixed * column widths. */ (void) TreeItem_Height(tree, item); TreeItem_ToIndex(tree, item, &index, &indexVis); switch (tree->backgroundMode) { #ifdef DEPRECATED case BG_MODE_INDEX: #endif case BG_MODE_ORDER: break; #ifdef DEPRECATED case BG_MODE_VISINDEX: #endif case BG_MODE_ORDERVIS: index = indexVis; break; case BG_MODE_COLUMN: index = range->index; break; case BG_MODE_ROW: index = rItem->index; break; } dItem = (DItem *) TreeItem_GetDInfo(tree, item); /* Re-use a previously allocated DItem */ if (dItem != NULL) { dItemHead = DItem_Unlink(dItemHead, dItem); area = &dItem->area; /* This item is already marked for total redraw */ if (area->flags & DITEM_ALL_DIRTY) ; /* nothing */ /* All display info is marked as invalid */ else if (dInfo->flags & DINFO_INVALIDATE) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* The range may have changed size */ else if ((area->width != range->totalWidth) || (dItem->height != rItem->size)) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* Items may have alternating background colors. */ else if ((tree->columnBgCnt > 1) && ((index % tree->columnBgCnt) != (dItem->index % tree->columnBgCnt))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We don't copy items horizontally to their new position, * except for horizontal scrolling which moves the whole * range */ else if (x != dItem->oldX + (dInfo->xOrigin - tree->xOrigin)) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* If we are displaying dotted lines and the item has moved * from odd-top to non-odd-top or vice versa, must redraw * the lines for this item. */ else if (tree->showLines && (tree->lineStyle == LINE_STYLE_DOT) && tree->columnTreeVis && (TreeColumn_Lock(tree->columnTree) == COLUMN_LOCK_NONE) && ((DW2Cy(dItem->oldY) & 1) != (W2Cy(y) & 1))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We can't copy the item to its new position unless it * has the same part of the background image behind it */ else if ((tree->backgroundImage != NULL) && (((dItem->oldY + dInfo->yOrigin) % bgImgHeight) != ((y + tree->yOrigin) % bgImgHeight))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; } /* Make a new DItem */ else { dItem = DItem_Alloc(tree, rItem); area = &dItem->area; } area->x = x; dItem->y = y; area->width = Range_TotalWidth(tree, range); dItem->height = rItem->size; dItem->range = range; dItem->index = index; dItem->spans = TreeItem_GetSpans(tree, dItem->item); /* Keep track of the maximum item size */ if (area->width > dInfo->itemWidth) dInfo->itemWidth = area->width; if (dItem->height > dInfo->itemHeight) dInfo->itemHeight = dItem->height; /* Linked list of DItems */ if (dInfo->dItem == NULL) dInfo->dItem = dItem; else dInfo->dItemLast->next = dItem; dInfo->dItemLast = dItem; if (rItem == range->last) break; /* Advance to next TreeItem */ rItem++; /* Stop when out of bounds */ y += dItem->height; if (y >= maxY) break; } } /* Left-to-right */ else { while (1) { item = rItem->item; /* Update item/style layout. This can be needed when using fixed * column widths. */ (void) TreeItem_Height(tree, item); TreeItem_ToIndex(tree, item, &index, &indexVis); switch (tree->backgroundMode) { #ifdef DEPRECATED case BG_MODE_INDEX: #endif case BG_MODE_ORDER: break; #ifdef DEPRECATED case BG_MODE_VISINDEX: #endif case BG_MODE_ORDERVIS: index = indexVis; break; case BG_MODE_COLUMN: index = rItem->index; break; case BG_MODE_ROW: index = range->index; break; } dItem = (DItem *) TreeItem_GetDInfo(tree, item); /* Re-use a previously allocated DItem */ if (dItem != NULL) { dItemHead = DItem_Unlink(dItemHead, dItem); area = &dItem->area; /* This item is already marked for total redraw */ if (area->flags & DITEM_ALL_DIRTY) ; /* nothing */ /* All display info is marked as invalid */ else if (dInfo->flags & DINFO_INVALIDATE) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* The range may have changed size */ else if ((area->width != rItem->size) || (dItem->height != range->totalHeight)) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* Items may have alternating background colors. */ else if ((tree->columnBgCnt > 1) && ((index % tree->columnBgCnt) != (dItem->index % tree->columnBgCnt))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We don't copy items vertically to their new position, * except for vertical scrolling which moves the whole range */ else if (y != dItem->oldY + (dInfo->yOrigin - tree->yOrigin)) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* If we are displaying dotted lines and the item has moved * from odd-top to non-odd-top or vice versa, must redraw * the lines for this item. */ else if (tree->showLines && (tree->lineStyle == LINE_STYLE_DOT) && tree->columnTreeVis && ((DW2Cy(dItem->oldY) & 1) != (W2Cy(y) & 1))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We can't copy the item to its new position unless it * has the same part of the background image behind it */ else if ((tree->backgroundImage != NULL) && (((dItem->oldX + dInfo->xOrigin) % bgImgWidth) != ((x + tree->xOrigin) % bgImgWidth))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; } /* Make a new DItem */ else { dItem = DItem_Alloc(tree, rItem); area = &dItem->area; } area->x = x; dItem->y = y; area->width = rItem->size; dItem->height = Range_TotalHeight(tree, range); dItem->range = range; dItem->index = index; dItem->spans = TreeItem_GetSpans(tree, dItem->item); /* Keep track of the maximum item size */ if (area->width > dInfo->itemWidth) dInfo->itemWidth = area->width; if (dItem->height > dInfo->itemHeight) dInfo->itemHeight = dItem->height; /* Linked list of DItems */ if (dInfo->dItem == NULL) dInfo->dItem = dItem; else dInfo->dItemLast->next = dItem; dInfo->dItemLast = dItem; if (rItem == range->last) break; /* Advance to next TreeItem */ rItem++; /* Stop when out of bounds */ x += area->width; if (x >= maxX) break; } } return dItemHead; } /* *-------------------------------------------------------------- * * Tree_UpdateDInfo -- * * At the finish of this procedure every on-screen item will have * a DItem associated with it and no off-screen item will have * a DItem. * * Results: * None. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ void Tree_UpdateDInfo( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItemHead = dInfo->dItem; int x, y, rx = 0, ry = 0, ix, iy, dx, dy; int minX, minY, maxX, maxY; Range *range; RItem *rItem; DItem *dItem; if (tree->debug.enable && tree->debug.display) dbwin("Tree_UpdateDInfo %s\n", Tk_PathName(tree->tkwin)); dInfo->dItem = dInfo->dItemLast = NULL; dInfo->rangeFirstD = dInfo->rangeLastD = NULL; dInfo->itemWidth = dInfo->itemHeight = 0; dInfo->empty = !Tree_AreaBbox(tree, TREE_AREA_CONTENT, &dInfo->bounds[0], &dInfo->bounds[1], &dInfo->bounds[2], &dInfo->bounds[3]); dInfo->emptyL = !Tree_AreaBbox(tree, TREE_AREA_LEFT, &dInfo->boundsL[0], &dInfo->boundsL[1], &dInfo->boundsL[2], &dInfo->boundsL[3]); dInfo->emptyR = !Tree_AreaBbox(tree, TREE_AREA_RIGHT, &dInfo->boundsR[0], &dInfo->boundsR[1], &dInfo->boundsR[2], &dInfo->boundsR[3]); if (dInfo->empty) goto done; minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; range = dInfo->rangeFirst; if (tree->vertical) { /* Find the first range which could be onscreen horizontally. * It may not be onscreen if it has less height than other ranges. */ while (range != NULL) { if ((range->offset < maxX + tree->xOrigin) && (range->offset + range->totalWidth >= minX + tree->xOrigin)) { rx = range->offset; ry = 0; break; } range = range->next; } } else { /* Find the first range which could be onscreen vertically. * It may not be onscreen if it has less width than other ranges. */ while (range != NULL) { if ((range->offset < maxY + tree->yOrigin) && (range->offset + range->totalHeight >= minY + tree->yOrigin)) { rx = 0; ry = range->offset; break; } range = range->next; } } while (range != NULL) { if ((rx + range->totalWidth > minX + tree->xOrigin) && (ry + range->totalHeight > minY + tree->yOrigin)) { if (tree->vertical) { /* Range coords */ dx = MAX(minX + tree->xOrigin - rx, 0); dy = minY + tree->yOrigin; } else { dx = minX + tree->xOrigin; dy = MAX(minY + tree->yOrigin - ry, 0); } ix = dx; iy = dy; rItem = Range_ItemUnderPoint(tree, range, &ix, &iy); /* Window coords of top-left of item */ x = (rx - tree->xOrigin) + dx - ix; y = (ry - tree->yOrigin) + dy - iy; dItemHead = UpdateDInfoForRange(tree, dItemHead, range, rItem, x, y); } /* Track this range even if it has no DItems, so whitespace is * erased */ if (dInfo->rangeFirstD == NULL) dInfo->rangeFirstD = range; dInfo->rangeLastD = range; if (tree->vertical) { rx += range->totalWidth; if (rx >= maxX + tree->xOrigin) break; } else { ry += range->totalHeight; if (ry >= maxY + tree->yOrigin) break; } range = range->next; } if (dInfo->dItemLast != NULL) dInfo->dItemLast->next = NULL; done: if (dInfo->dItem != NULL) goto skipLock; if (!tree->itemVisCount) goto skipLock; if (dInfo->emptyL && dInfo->emptyR) goto skipLock; range = dInfo->rangeFirst; if ((range != NULL) && !range->totalHeight) goto skipLock; { int y = Tree_ContentTop(tree) + tree->yOrigin; /* Window -> Canvas */ int index, indexVis; /* If no non-locked columns are displayed, we have no Range and * must use dInfo->rangeLock. */ if (range == NULL) { range = dInfo->rangeLock; } /* Find the first item on-screen vertically. */ rItem = Range_ItemUnderPoint(tree, range, NULL, &y); y = rItem->offset; /* Top of the item */ y -= tree->yOrigin; /* Canvas -> Window */ while (1) { DItem *dItem = (DItem *) TreeItem_GetDInfo(tree, rItem->item); /* Re-use a previously allocated DItem */ if (dItem != NULL) { dItemHead = DItem_Unlink(dItemHead, dItem); } else { dItem = DItem_Alloc(tree, rItem); } TreeItem_ToIndex(tree, rItem->item, &index, &indexVis); switch (tree->backgroundMode) { #ifdef DEPRECATED case BG_MODE_INDEX: #endif case BG_MODE_ORDER: break; #ifdef DEPRECATED case BG_MODE_VISINDEX: #endif case BG_MODE_ORDERVIS: index = indexVis; break; case BG_MODE_COLUMN: index = range->index; break; case BG_MODE_ROW: index = rItem->index; break; } dItem->y = y; dItem->height = rItem->size; dItem->range = range; dItem->index = index; dItem->spans = TreeItem_GetSpans(tree, dItem->item); /* Keep track of the maximum item size */ if (dItem->height > dInfo->itemHeight) dInfo->itemHeight = dItem->height; /* Linked list of DItems */ if (dInfo->dItem == NULL) dInfo->dItem = dItem; else dInfo->dItemLast->next = dItem; dInfo->dItemLast = dItem; if (rItem == range->last) break; y += rItem->size; if (y >= Tree_ContentBottom(tree)) break; rItem++; } } skipLock: if (!dInfo->emptyL || !dInfo->emptyR) { int bgImgWidth, bgImgHeight; DItemArea *area; if (!dInfo->emptyL) { /* Keep track of the maximum item size */ if (dInfo->widthOfColumnsLeft > dInfo->itemWidth) dInfo->itemWidth = dInfo->widthOfColumnsLeft; } if (!dInfo->emptyR) { /* Keep track of the maximum item size */ if (dInfo->widthOfColumnsRight > dInfo->itemWidth) dInfo->itemWidth = dInfo->widthOfColumnsRight; } if (tree->backgroundImage != NULL) Tk_SizeOfImage(tree->backgroundImage, &bgImgWidth, &bgImgHeight); for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { if (!dInfo->emptyL) { area = &dItem->left; area->x = Tree_BorderLeft(tree); area->width = dInfo->widthOfColumnsLeft; /* This item is already marked for total redraw */ if (area->flags & DITEM_ALL_DIRTY) { ; /* nothing */ /* All display info is marked as invalid */ } else if (dInfo->flags & DINFO_INVALIDATE) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* Items may have alternating background colors. */ } else if ((tree->columnBgCnt > 1) && ((dItem->oldIndex % tree->columnBgCnt) != (dItem->index % tree->columnBgCnt))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* If we are displaying dotted lines and the item has moved * from odd-top to non-odd-top or vice versa, must redraw * the lines for this item. */ } else if (tree->showLines && (tree->lineStyle == LINE_STYLE_DOT) && tree->columnTreeVis && (TreeColumn_Lock(tree->columnTree) == COLUMN_LOCK_LEFT) && ((DW2Cy(dItem->oldY) & 1) != (W2Cy(dItem->y) & 1))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We can't copy the item to its new position unless it * has the same part of the background image behind it */ } else if ((tree->backgroundImage != NULL) && ((dInfo->xOrigin % bgImgWidth) != (tree->xOrigin % bgImgWidth))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; } } if (!dInfo->emptyR) { area = &dItem->right; area->x = Tree_ContentRight(tree); area->width = dInfo->widthOfColumnsRight; /* This item is already marked for total redraw */ if (area->flags & DITEM_ALL_DIRTY) { ; /* nothing */ /* All display info is marked as invalid */ } else if (dInfo->flags & DINFO_INVALIDATE) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* Items may have alternating background colors. */ } else if ((tree->columnBgCnt > 1) && ((dItem->oldIndex % tree->columnBgCnt) != (dItem->index % tree->columnBgCnt))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* If we are displaying dotted lines and the item has moved * from odd-top to non-odd-top or vice versa, must redraw * the lines for this item. */ } else if (tree->showLines && (tree->lineStyle == LINE_STYLE_DOT) && tree->columnTreeVis && (TreeColumn_Lock(tree->columnTree) == COLUMN_LOCK_RIGHT) && ((DW2Cy(dItem->oldY) & 1) != (W2Cy(dItem->y) & 1))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We can't copy the item to its new position unless it * has the same part of the background image behind it */ } else if ((tree->backgroundImage != NULL) && ((dInfo->xOrigin % bgImgWidth) != (tree->xOrigin % bgImgWidth))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; } } } } while (dItemHead != NULL) dItemHead = DItem_Free(tree, dItemHead); dInfo->flags &= ~DINFO_INVALIDATE; } /* *-------------------------------------------------------------- * * InvalidateDItemX -- * * Mark a horizontal span of a DItem as dirty (needing to be * redrawn). The caller must set the DITEM_DIRTY flag afterwards. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void InvalidateDItemX( DItem *dItem, /* Item to mark dirty. */ DItemArea *area, int itemX, /* x-coordinate of item. */ int dirtyX, /* Left edge of area to mark as dirty. */ int dirtyWidth /* Width of area to mark as dirty. */ ) { int x1, x2; if (dirtyX <= itemX) area->dirty[LEFT] = 0; else { x1 = dirtyX - itemX; if (!(area->flags & DITEM_DIRTY) || (x1 < area->dirty[LEFT])) area->dirty[LEFT] = x1; } if (dirtyX + dirtyWidth >= itemX + area->width) area->dirty[RIGHT] = area->width; else { x2 = dirtyX + dirtyWidth - itemX; if (!(area->flags & DITEM_DIRTY) || (x2 > area->dirty[RIGHT])) area->dirty[RIGHT] = x2; } } /* *-------------------------------------------------------------- * * InvalidateDItemY -- * * Mark a vertical span of a DItem as dirty (needing to be * redrawn). The caller must set the DITEM_DIRTY flag afterwards. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void InvalidateDItemY( DItem *dItem, /* Item to mark dirty. */ DItemArea *area, int itemY, /* y-coordinate of item. */ int dirtyY, /* Top edge of area to mark as dirty. */ int dirtyHeight /* Height of area to mark as dirty. */ ) { int y1, y2; if (dirtyY <= itemY) area->dirty[TOP] = 0; else { y1 = dirtyY - itemY; if (!(area->flags & DITEM_DIRTY) || (y1 < area->dirty[TOP])) area->dirty[TOP] = y1; } if (dirtyY + dirtyHeight >= itemY + dItem->height) area->dirty[BOTTOM] = dItem->height; else { y2 = dirtyY + dirtyHeight - itemY; if (!(area->flags & DITEM_DIRTY) || (y2 > area->dirty[BOTTOM])) area->dirty[BOTTOM] = y2; } } /* *-------------------------------------------------------------- * * Range_RedoIfNeeded -- * * Recalculate the list of Ranges if they are marked out-of-date. * Also calculate the height and width of the canvas based on the * list of Ranges. * * Results: * None. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static void Range_RedoIfNeeded( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; if (dInfo->flags & DINFO_REDO_RANGES) { dInfo->rangeFirstD = dInfo->rangeLastD = NULL; dInfo->flags |= DINFO_OUT_OF_DATE; Range_Redo(tree); dInfo->flags &= ~DINFO_REDO_RANGES; #ifdef COMPLEX_WHITESPACE if (ComplexWhitespace(tree)) { dInfo->flags |= DINFO_DRAW_WHITESPACE; } #endif /* Do this after clearing REDO_RANGES to prevent infinite loop */ tree->totalWidth = tree->totalHeight = -1; (void) Tree_TotalWidth(tree); (void) Tree_TotalHeight(tree); dInfo->flags |= DINFO_REDO_INCREMENTS; } } static int DItemAllDirty( TreeCtrl *tree, DItem *dItem ) { TreeDInfo dInfo = tree->dInfo; if ((!dInfo->empty && dInfo->rangeFirst != NULL) && !(dItem->area.flags & DITEM_ALL_DIRTY)) return 0; if (!dInfo->emptyL && !(dItem->left.flags & DITEM_ALL_DIRTY)) return 0; if (!dInfo->emptyR && !(dItem->right.flags & DITEM_ALL_DIRTY)) return 0; return 1; } /* *-------------------------------------------------------------- * * ScrollVerticalComplex -- * * Perform scrolling by copying the pixels of items from the * previous display position to the current position. Any areas * of items copied over by the moved items are marked dirty. * * Results: * The number of items whose pixels were copied. * * Side effects: * Pixels are copied in the TreeCtrl window or in the * offscreen pixmap (if double-buffering is used). * *-------------------------------------------------------------- */ static int ScrollVerticalComplex( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem, *dItem2; Range *range; TkRegion damageRgn; int minX, minY, maxX, maxY; int oldX, oldY, width, height, offset; int y; int numCopy = 0; if (dInfo->empty && dInfo->emptyL && dInfo->emptyR) return 0; minX = Tree_BorderLeft(tree); minY = Tree_ContentTop(tree); maxX = Tree_BorderRight(tree); maxY = Tree_ContentBottom(tree); /* Try updating the display by copying items on the screen to their * new location */ for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { /* Copy an item to its new location unless: * (a) item display info is invalid * (b) item is in same location as last draw */ if (DItemAllDirty(tree, dItem) || (dItem->oldY == dItem->y)) continue; numCopy++; range = dItem->range; /* This item was previously displayed so it only needs to be * copied to the new location. Copy all such items as one */ offset = dItem->y - dItem->oldY; height = dItem->height; for (dItem2 = dItem->next; dItem2 != NULL; dItem2 = dItem2->next) { if ((dItem2->range != range) || DItemAllDirty(tree, dItem2) || (dItem2->oldY + offset != dItem2->y)) break; numCopy++; height += dItem2->height; } y = dItem->y; oldY = dItem->oldY; /* Don't copy part of the window border */ if (oldY < minY) { height -= minY - oldY; oldY = minY; } if (oldY + height > maxY) height = maxY - oldY; /* Don't copy over the window border */ if (oldY + offset < minY) { height -= minY - (oldY + offset); oldY += minY - (oldY + offset); } if (oldY + offset + height > maxY) height = maxY - (oldY + offset); if (!dInfo->emptyL || !dInfo->emptyR) { oldX = minX; width = maxX - minX; } else { oldX = dItem->oldX; width = dItem->area.width; } if (oldX < minX) { width -= minX - oldX; oldX = minX; } if (oldX + width > maxX) width = maxX - oldX; /* Update oldY of copied items */ while (1) { /* If an item was partially visible, invalidate the exposed area */ if ((dItem->oldY < minY) && (offset > 0)) { if (!dInfo->empty && dInfo->rangeFirst != NULL) { InvalidateDItemX(dItem, &dItem->area, dItem->oldX, oldX, width); InvalidateDItemY(dItem, &dItem->area, dItem->oldY, dItem->oldY, minY - dItem->oldY); dItem->area.flags |= DITEM_DIRTY; } if (!dInfo->emptyL) { InvalidateDItemX(dItem, &dItem->left, dItem->left.x, oldX, width); InvalidateDItemY(dItem, &dItem->left, dItem->oldY, dItem->oldY, minY - dItem->oldY); dItem->left.flags |= DITEM_DIRTY; } if (!dInfo->emptyR) { InvalidateDItemX(dItem, &dItem->right, dItem->right.x, oldX, width); InvalidateDItemY(dItem, &dItem->right, dItem->oldY, dItem->oldY, minY - dItem->oldY); dItem->right.flags |= DITEM_DIRTY; } } if ((dItem->oldY + dItem->height > maxY) && (offset < 0)) { if (!dInfo->empty && dInfo->rangeFirst != NULL) { InvalidateDItemX(dItem, &dItem->area, dItem->oldX, oldX, width); InvalidateDItemY(dItem, &dItem->area, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height); dItem->area.flags |= DITEM_DIRTY; } if (!dInfo->emptyL) { InvalidateDItemX(dItem, &dItem->left, dItem->left.x, oldX, width); InvalidateDItemY(dItem, &dItem->left, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height); dItem->left.flags |= DITEM_DIRTY; } if (!dInfo->emptyR) { InvalidateDItemX(dItem, &dItem->right, dItem->right.x, oldX, width); InvalidateDItemY(dItem, &dItem->right, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height); dItem->right.flags |= DITEM_DIRTY; } } dItem->oldY = dItem->y; if (dItem->next == dItem2) break; dItem = dItem->next; } /* Invalidate parts of items being copied over */ for ( ; dItem2 != NULL; dItem2 = dItem2->next) { if (dItem2->range != range) break; if (!DItemAllDirty(tree, dItem2) && (dItem2->oldY + dItem2->height > y) && (dItem2->oldY < y + height)) { if (!dInfo->empty && dInfo->rangeFirst != NULL) { InvalidateDItemX(dItem2, &dItem2->area, dItem2->oldX, oldX, width); InvalidateDItemY(dItem2, &dItem2->area, dItem2->oldY, y, height); dItem2->area.flags |= DITEM_DIRTY; } if (!dInfo->emptyL) { InvalidateDItemX(dItem2, &dItem2->left, dItem2->left.x, oldX, width); InvalidateDItemY(dItem2, &dItem2->left, dItem2->oldY, y, height); dItem2->left.flags |= DITEM_DIRTY; } if (!dInfo->emptyR) { InvalidateDItemX(dItem2, &dItem2->right, dItem2->right.x, oldX, width); InvalidateDItemY(dItem2, &dItem2->right, dItem2->oldY, y, height); dItem2->right.flags |= DITEM_DIRTY; } } } if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { int dirtyMin, dirtyMax; XCopyArea(tree->display, dInfo->pixmap, dInfo->pixmap, tree->copyGC, oldX, oldY, width, height, oldX, oldY + offset); if (offset < 0) { dirtyMin = oldY + offset + height; dirtyMax = oldY + height; } else { dirtyMin = oldY; dirtyMax = oldY + offset; } Tree_InvalidateArea(tree, oldX, dirtyMin, oldX + width, dirtyMax); dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], oldX); dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], oldY + offset); dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], oldX + width); dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], oldY + offset + height); continue; } /* Copy */ damageRgn = TkCreateRegion(); if (Tree_ScrollWindow(tree, dInfo->scrollGC, oldX, oldY, width, height, 0, offset, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } TkDestroyRegion(damageRgn); } return numCopy; } /* *-------------------------------------------------------------- * * ScrollHorizontalSimple -- * * Perform scrolling by shifting the pixels in the content area of * the list to the left or right. * * Results: * None. * * Side effects: * Stuff is copied/scrolled in the TreeCtrl window or in the * offscreen pixmap (if double-buffering is used). * *-------------------------------------------------------------- */ static void ScrollHorizontalSimple( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; TkRegion damageRgn; int minX, minY, maxX, maxY; int width, offset; int x, y; int dirtyMin, dirtyMax; if (dInfo->xOrigin == tree->xOrigin) return; /* Only column headers are visible. */ if (dInfo->rangeFirst == NULL) return; if (dInfo->empty) return; minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; /* Update oldX */ for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { dItem->oldX = dItem->area.x; } offset = dInfo->xOrigin - tree->xOrigin; /* We only scroll the content, not the whitespace */ y = 0 - tree->yOrigin + Tree_TotalHeight(tree); if (y < maxY) maxY = y; /* Simplify if a whole screen was scrolled. */ if (abs(offset) >= maxX - minX) { Tree_InvalidateArea(tree, minX, minY, maxX, maxY); return; } /* We only scroll the content, not the whitespace */ x = 0 - tree->xOrigin + Tree_TotalWidth(tree); if (x < maxX) maxX = x; width = maxX - minX - abs(offset); /* Move pixels right */ if (offset > 0) { x = minX; } /* Move pixels left */ else { x = maxX - width; } dirtyMin = minX + width; dirtyMax = maxX - width; damageRgn = TkCreateRegion(); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { XCopyArea(tree->display, dInfo->pixmap, dInfo->pixmap, tree->copyGC, x, minY, width, maxY - minY, x + offset, minY); if (offset < 0) dirtyMax = maxX; else dirtyMin = minX; Tree_InvalidateArea(tree, dirtyMin, minY, dirtyMax, maxY); TkDestroyRegion(damageRgn); return; } if (Tree_ScrollWindow(tree, dInfo->scrollGC, x, minY, width, maxY - minY, offset, 0, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } TkDestroyRegion(damageRgn); #ifndef WIN32 if (offset < 0) dirtyMax = maxX; else dirtyMin = minX; #endif if (dirtyMin < dirtyMax) Tree_InvalidateArea(tree, dirtyMin, minY, dirtyMax, maxY); } /* *-------------------------------------------------------------- * * ScrollVerticalSimple -- * * Perform scrolling by shifting the pixels in the content area of * the list up or down. * * Results: * None. * * Side effects: * Stuff is copied/scrolled in the TreeCtrl window or in the * offscreen pixmap (if double-buffering is used). * *-------------------------------------------------------------- */ static void ScrollVerticalSimple( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; TkRegion damageRgn; int minX, minY, maxX, maxY; int height, offset; int x, y; int dirtyMin, dirtyMax; if (dInfo->yOrigin == tree->yOrigin) return; /* Update oldY */ for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { dItem->oldY = dItem->y; } if (dInfo->empty) return; minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; offset = dInfo->yOrigin - tree->yOrigin; /* We only scroll the content, not the whitespace */ x = 0 - tree->xOrigin + Tree_TotalWidth(tree); if (x < maxX) maxX = x; /* Simplify if a whole screen was scrolled. */ if (abs(offset) > maxY - minY) { Tree_InvalidateArea(tree, minX, minY, maxX, maxY); return; } height = maxY - minY - abs(offset); /* Move pixels down */ if (offset > 0) { y = minY; } /* Move pixels up */ else { y = maxY - height; } dirtyMin = minY + height; dirtyMax = maxY - height; damageRgn = TkCreateRegion(); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { XCopyArea(tree->display, dInfo->pixmap, dInfo->pixmap, tree->copyGC, minX, y, maxX - minX, height, minX, y + offset); if (offset < 0) dirtyMax = maxY; else dirtyMin = minY; Tree_InvalidateArea(tree, minX, dirtyMin, maxX, dirtyMax); TkDestroyRegion(damageRgn); return; } if (Tree_ScrollWindow(tree, dInfo->scrollGC, minX, y, maxX - minX, height, 0, offset, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } TkDestroyRegion(damageRgn); #ifndef WIN32 if (offset < 0) dirtyMax = maxY; else dirtyMin = minY; #endif if (dirtyMin < dirtyMax) Tree_InvalidateArea(tree, minX, dirtyMin, maxX, dirtyMax); } /* *-------------------------------------------------------------- * * ScrollHorizontalComplex -- * * Perform scrolling by copying the pixels of items from the * previous display position to the current position. Any areas * of items copied over by the moved items are marked dirty. * * Results: * The number of items whose pixels were copied. * * Side effects: * Pixels are copied in the TreeCtrl window or in the * offscreen pixmap (if double-buffering is used). * *-------------------------------------------------------------- */ static int ScrollHorizontalComplex( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem, *dItem2; Range *range; TkRegion damageRgn; int minX, minY, maxX, maxY; int oldX, oldY, width, height, offset; int x; int numCopy = 0; if (!Tree_AreaBbox(tree, TREE_AREA_CONTENT, &minX, &minY, &maxX, &maxY)) return 0; /* Try updating the display by copying items on the screen to their * new location */ for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { /* Copy an item to its new location unless: * (a) item display info is invalid * (b) item is in same location as last draw */ if ((dItem->area.flags & DITEM_ALL_DIRTY) || (dItem->oldX == dItem->area.x)) continue; numCopy++; range = dItem->range; /* This item was previously displayed so it only needs to be * copied to the new location. Copy all such items as one */ offset = dItem->area.x - dItem->oldX; width = dItem->area.width; for (dItem2 = dItem->next; dItem2 != NULL; dItem2 = dItem2->next) { if ((dItem2->range != range) || (dItem2->area.flags & DITEM_ALL_DIRTY) || (dItem2->oldX + offset != dItem2->area.x)) break; numCopy++; width += dItem2->area.width; } x = dItem->area.x; oldX = dItem->oldX; /* Don't copy part of the window border */ if (oldX < minX) { width -= minX - oldX; oldX = minX; } if (oldX + width > maxX) width = maxX - oldX; /* Don't copy over the window border */ if (oldX + offset < minX) { width -= minX - (oldX + offset); oldX += minX - (oldX + offset); } if (oldX + offset + width > maxX) width = maxX - (oldX + offset); oldY = dItem->oldY; height = dItem->height; /* range->totalHeight */ if (oldY < minY) { height -= minY - oldY; oldY = minY; } if (oldY + height > maxY) height = maxY - oldY; /* Update oldX of copied items */ while (1) { /* If an item was partially visible, invalidate the exposed area */ if ((dItem->oldX < minX) && (offset > 0)) { InvalidateDItemX(dItem, &dItem->area, dItem->oldX, dItem->oldX, minX - dItem->oldX); InvalidateDItemY(dItem, &dItem->area, oldY, oldY, height); dItem->area.flags |= DITEM_DIRTY; } if ((dItem->oldX + dItem->area.width > maxX) && (offset < 0)) { InvalidateDItemX(dItem, &dItem->area, dItem->oldX, maxX, maxX - dItem->oldX + dItem->area.width); InvalidateDItemY(dItem, &dItem->area, oldY, oldY, height); dItem->area.flags |= DITEM_DIRTY; } dItem->oldX = dItem->area.x; if (dItem->next == dItem2) break; dItem = dItem->next; } /* Invalidate parts of items being copied over */ for ( ; dItem2 != NULL; dItem2 = dItem2->next) { if (dItem2->range != range) break; if (!(dItem2->area.flags & DITEM_ALL_DIRTY) && (dItem2->oldX + dItem2->area.width > x) && (dItem2->oldX < x + width)) { InvalidateDItemX(dItem2, &dItem2->area, dItem2->oldX, x, width); InvalidateDItemY(dItem2, &dItem2->area, oldY, oldY, height); dItem2->area.flags |= DITEM_DIRTY; } } if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { int dirtyMin, dirtyMax; XCopyArea(tree->display, dInfo->pixmap, dInfo->pixmap, tree->copyGC, oldX, oldY, width, height, oldX + offset, oldY); if (offset < 0) { dirtyMin = oldX + offset + width; dirtyMax = oldX + width; } else { dirtyMin = oldX; dirtyMax = oldX + offset; } Tree_InvalidateArea(tree, dirtyMin, oldY, dirtyMax, oldY + height); dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], oldX + offset); dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], oldY); dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], oldX + offset + width); dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], oldY + height); continue; } /* Copy */ damageRgn = TkCreateRegion(); if (Tree_ScrollWindow(tree, dInfo->scrollGC, oldX, oldY, width, height, offset, 0, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } TkDestroyRegion(damageRgn); } return numCopy; } /* *-------------------------------------------------------------- * * Proxy_Draw -- * * Draw (or erase) the visual indicator used when the user is * resizing a column or row (and -columnresizemode is "proxy"). * * Results: * None. * * Side effects: * Stuff is drawn in the TreeCtrl window (or erased, since this * is XOR drawing). * *-------------------------------------------------------------- */ static void Proxy_Draw( TreeCtrl *tree, /* Widget info. */ int x1, /* Vertical or horizontal line window coords. */ int y1, int x2, int y2 ) { #if defined(MAC_OSX_TK) DrawXORLine(tree->display, Tk_WindowId(tree->tkwin), x1, y1, x2, y2); #else XGCValues gcValues; unsigned long gcMask; GC gc; #if defined(MAC_TCL) gcValues.function = GXxor; #else gcValues.function = GXinvert; #endif gcValues.graphics_exposures = False; gcMask = GCFunction | GCGraphicsExposures; gc = Tk_GetGC(tree->tkwin, gcMask, &gcValues); /* GXinvert doesn't work with XFillRectangle() on Win32 or Mac */ #if defined(WIN32) || defined(MAC_TCL) XDrawLine(tree->display, Tk_WindowId(tree->tkwin), gc, x1, y1, x2, y2); #else XFillRectangle(tree->display, Tk_WindowId(tree->tkwin), gc, x1, y1, MAX(x2 - x1, 1), MAX(y2 - y1, 1)); #endif Tk_FreeGC(tree->display, gc); #endif } /* *-------------------------------------------------------------- * * TreeColumnProxy_Undisplay -- * * Hide the visual indicator used when the user is * resizing a column (if it is displayed). * * Results: * None. * * Side effects: * Stuff is erased in the TreeCtrl window. * *-------------------------------------------------------------- */ void TreeColumnProxy_Undisplay( TreeCtrl *tree /* Widget info. */ ) { if (tree->columnProxy.onScreen) { Proxy_Draw(tree, tree->columnProxy.sx, Tree_BorderTop(tree), tree->columnProxy.sx, Tree_BorderBottom(tree)); tree->columnProxy.onScreen = FALSE; } } /* *-------------------------------------------------------------- * * TreeColumnProxy_Display -- * * Display the visual indicator used when the user is * resizing a column (if it isn't displayed and should be * displayed). * * Results: * None. * * Side effects: * Stuff is drawn in the TreeCtrl window. * *-------------------------------------------------------------- */ void TreeColumnProxy_Display( TreeCtrl *tree /* Widget info. */ ) { if (!tree->columnProxy.onScreen && (tree->columnProxy.xObj != NULL)) { tree->columnProxy.sx = tree->columnProxy.x; Proxy_Draw(tree, tree->columnProxy.x, Tree_BorderTop(tree), tree->columnProxy.x, Tree_BorderBottom(tree)); tree->columnProxy.onScreen = TRUE; } } /* *-------------------------------------------------------------- * * TreeRowProxy_Display -- * * Display the visual indicator used when the user is * resizing a row (if it isn't displayed and should be * displayed). * * Results: * None. * * Side effects: * Stuff is drawn in the TreeCtrl window. * *-------------------------------------------------------------- */ void TreeRowProxy_Display( TreeCtrl *tree /* Widget info. */ ) { if (!tree->rowProxy.onScreen && (tree->rowProxy.yObj != NULL)) { tree->rowProxy.sy = tree->rowProxy.y; Proxy_Draw(tree, Tree_BorderLeft(tree), tree->rowProxy.y, Tree_BorderRight(tree), tree->rowProxy.y); tree->rowProxy.onScreen = TRUE; } } /* *-------------------------------------------------------------- * * TreeRowProxy_Undisplay -- * * Hide the visual indicator used when the user is * resizing a row (if it is displayed). * * Results: * None. * * Side effects: * Stuff is erased in the TreeCtrl window. * *-------------------------------------------------------------- */ void TreeRowProxy_Undisplay( TreeCtrl *tree /* Widget info. */ ) { if (tree->rowProxy.onScreen) { Proxy_Draw(tree, Tree_BorderLeft(tree), tree->rowProxy.sy, Tree_BorderRight(tree), tree->rowProxy.sy); tree->rowProxy.onScreen = FALSE; } } /* *-------------------------------------------------------------- * * CalcWhiteSpaceRegion -- * * Create a new region containing all the whitespace of the list * The whitespace is the area inside the borders/header where items * are not displayed. * * Results: * The new whitespace region, which may be empty. * * Side effects: * A new region is allocated. * *-------------------------------------------------------------- */ static TkRegion CalcWhiteSpaceRegion( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; int x, y, minX, minY, maxX, maxY; int left, right, top, bottom; TkRegion wsRgn; XRectangle rect; Range *range; x = 0 - tree->xOrigin; y = 0 - tree->yOrigin; wsRgn = TkCreateRegion(); /* Erase area below left columns */ if (!dInfo->emptyL) { minX = dInfo->boundsL[0]; minY = dInfo->boundsL[1]; maxX = dInfo->boundsL[2]; maxY = dInfo->boundsL[3]; if (y + Tree_TotalHeight(tree) < maxY) { rect.x = minX; rect.y = y + Tree_TotalHeight(tree); rect.width = maxX - minX; rect.height = maxY - (y + Tree_TotalHeight(tree)); TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } /* Erase area below right columns */ if (!dInfo->emptyR) { minX = dInfo->boundsR[0]; minY = dInfo->boundsR[1]; maxX = dInfo->boundsR[2]; maxY = dInfo->boundsR[3]; if (y + Tree_TotalHeight(tree) < maxY) { rect.x = minX; rect.y = y + Tree_TotalHeight(tree); rect.width = maxX - minX; rect.height = maxY - (y + Tree_TotalHeight(tree)); TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } if (dInfo->empty) return wsRgn; minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; /* Only the header is visible. */ if (dInfo->rangeFirst == NULL) { rect.x = minX; rect.y = minY; rect.width = maxX - rect.x; rect.height = maxY - rect.y; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); return wsRgn; } if (tree->vertical) { /* Erase area to right of last Range */ if (x + Tree_TotalWidth(tree) < maxX) { rect.x = x + Tree_TotalWidth(tree); rect.y = minY; rect.width = maxX - rect.x; rect.height = maxY - rect.y; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } else { /* Erase area below last Range */ if (y + Tree_TotalHeight(tree) < maxY) { rect.x = minX; rect.y = y + Tree_TotalHeight(tree); rect.width = maxX - rect.x; rect.height = maxY - rect.y; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } for (range = dInfo->rangeFirstD; range != NULL; range = range->next) { if (tree->vertical) { left = MAX(x + range->offset, minX); right = MIN(x + range->offset + range->totalWidth, maxX); top = MAX(y + range->totalHeight, minY); bottom = maxY; /* Erase area below Range */ if (top < bottom) { rect.x = left; rect.y = top; rect.width = right - left; rect.height = bottom - top; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } else { left = MAX(x + range->totalWidth, minX); right = maxX; top = MAX(y + range->offset, minY); bottom = MIN(y + range->offset + range->totalHeight, maxY); /* Erase area to right of Range */ if (left < right) { rect.x = left; rect.y = top; rect.width = right - left; rect.height = bottom - top; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } if (range == dInfo->rangeLastD) break; } return wsRgn; } #ifdef COMPLEX_WHITESPACE /* *-------------------------------------------------------------- * * Tree_IntersectRect -- * * Determine the area of overlap between two rectangles. * * Results: * If the rectangles have non-zero size and overlap, resultPtr * holds the area of overlap, and the return value is 1. * Otherwise 0 is returned and resultPtr is untouched. * * Side effects: * None. * *-------------------------------------------------------------- */ static int Tree_IntersectRect( XRectangle *resultPtr, /* Out: area of overlap. May be the same * as r1 or r2. */ CONST XRectangle *r1, /* First rectangle. */ CONST XRectangle *r2 /* Second rectangle. */ ) { XRectangle result; if (r1->width == 0 || r1->height == 0) return 0; if (r2->width == 0 || r2->height == 0) return 0; if (r1->x >= r2->x + r2->width) return 0; if (r2->x >= r1->x + r1->width) return 0; if (r1->y >= r2->y + r2->height) return 0; if (r2->y >= r1->y + r1->height) return 0; result.x = MAX(r1->x, r2->x); result.width = MIN(r1->x + r1->width, r2->x + r2->width) - result.x; result.y = MAX(r1->y, r2->y); result.height = MIN(r1->y + r1->height, r2->y + r2->height) - result.y; *resultPtr = result; return 1; } /* *-------------------------------------------------------------- * * GetItemBgIndex -- * * Determine the index used to pick an -itembackground color * for a displayed item. * This is only valid for tree->vertical=1. * * Results: * Integer index. * * Side effects: * None. * *-------------------------------------------------------------- */ static int GetItemBgIndex( TreeCtrl *tree, /* Widget info. */ RItem *rItem /* Range info for an item. */ ) { Range *range = rItem->range; int index, indexVis; TreeItem_ToIndex(tree, rItem->item, &index, &indexVis); switch (tree->backgroundMode) { #ifdef DEPRECATED case BG_MODE_INDEX: #endif case BG_MODE_ORDER: break; #ifdef DEPRECATED case BG_MODE_VISINDEX: #endif case BG_MODE_ORDERVIS: index = indexVis; break; case BG_MODE_COLUMN: index = range->index; /* always zero */ break; case BG_MODE_ROW: index = rItem->index; break; } return index; } /* *-------------------------------------------------------------- * * DrawColumnBackground -- * * Draws rows of -itembackground colors in a column in the * whitespace region. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void DrawColumnBackground( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ TreeColumn treeColumn, /* Column to get background colors from. */ TkRegion dirtyRgn, /* Area that needs painting. Will be * inside 'bounds' and inside borders. */ XRectangle *bounds, /* Window coords of column to paint. */ RItem *rItem, /* Item(s) to get row heights from when drawing * in the tail column, otherwise NULL. */ int height, /* Height of each row below actual items. */ int index /* Used for alternating background colors. */ ) { int bgCount = TreeColumn_BackgroundCount(treeColumn); GC gc = None, backgroundGC; XRectangle dirtyBox, drawBox, rowBox; int top, bottom; TkClipBox(dirtyRgn, &dirtyBox); if (!dirtyBox.width || !dirtyBox.height) return; backgroundGC = Tk_3DBorderGC(tree->tkwin, tree->border, TK_3D_FLAT_GC); /* If the column has zero -itembackground colors, paint with the * treectrl's -background color. If a single -itembackground color * is specified, then paint with it. */ if (bgCount < 2) { if (bgCount == 1) gc = TreeColumn_BackgroundGC(treeColumn, 0); if (gc == None) gc = backgroundGC; Tk_FillRegion(tree->display, drawable, gc, dirtyRgn); return; } top = bounds->y; bottom = dirtyBox.y + dirtyBox.height; while (top < bottom) { /* Can't use clipping regions with XFillRectangle * because the clip region is ignored on Win32. */ rowBox.x = bounds->x; rowBox.y = top; rowBox.width = bounds->width; rowBox.height = rItem ? rItem->size : height; if (Tree_IntersectRect(&drawBox, &rowBox, &dirtyBox)) { if (rItem != NULL) { index = GetItemBgIndex(tree, rItem); } gc = TreeColumn_BackgroundGC(treeColumn, index); if (gc == None) gc = backgroundGC; XFillRectangle(tree->display, drawable, gc, drawBox.x, drawBox.y, drawBox.width, drawBox.height); } if (rItem != NULL && rItem == rItem->range->last) { index = GetItemBgIndex(tree, rItem); rItem = NULL; } if (rItem != NULL) { rItem++; } index++; top += rowBox.height; } } /* *-------------------------------------------------------------- * * DrawWhitespaceBelowItem -- * * Draws rows of -itembackground colors in each column in the * whitespace region. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void DrawWhitespaceBelowItem( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ int lock, /* Which columns to draw. */ int bounds[4], /* TREE_AREA_xxx bounds. */ int left, /* Window coord of first column's left edge. */ int top, /* Window coord just below the last item. */ TkRegion dirtyRgn, /* Area of whitespace that needs painting. */ TkRegion columnRgn, /* Existing region to set and use. */ int height, /* Height of each row. */ int index /* Used for alternating background colors. */ ) { TreeDInfo dInfo = tree->dInfo; int i = 0; TreeColumn treeColumn; XRectangle boundsBox, columnBox; switch (lock) { case COLUMN_LOCK_LEFT: i = TreeColumn_Index(tree->columnLockLeft); break; case COLUMN_LOCK_NONE: i = TreeColumn_Index(tree->columnLockNone); break; case COLUMN_LOCK_RIGHT: i = TreeColumn_Index(tree->columnLockRight); break; } boundsBox.x = bounds[0]; boundsBox.y = bounds[1]; boundsBox.width = bounds[2] - bounds[0]; boundsBox.height = bounds[3] - bounds[1]; for (/*nothing*/; i < tree->columnCount; i++) { treeColumn = dInfo->columns[i].column; if (TreeColumn_Lock(treeColumn) != lock) break; if (dInfo->columns[i].width == 0) continue; columnBox.x = left; columnBox.y = top; columnBox.width = dInfo->columns[i].width; columnBox.height = bounds[3] - top; if (Tree_IntersectRect(&columnBox, &boundsBox, &columnBox)) { TkSubtractRegion(columnRgn, columnRgn, columnRgn); TkUnionRectWithRegion(&columnBox, columnRgn, columnRgn); TkIntersectRegion(dirtyRgn, columnRgn, columnRgn); DrawColumnBackground(tree, drawable, treeColumn, columnRgn, &columnBox, (RItem *) NULL, height, index); } left += dInfo->columns[i].width; } } /* *-------------------------------------------------------------- * * ComplexWhitespace -- * * Return 1 if -itembackground colors should be drawn into the * whitespace region. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static int ComplexWhitespace( TreeCtrl *tree ) { if (tree->columnBgCnt == 0 && TreeColumn_BackgroundCount(tree->columnTail) == 0) return 0; if (!tree->vertical || tree->wrapMode != TREE_WRAP_NONE) return 0; if (tree->itemHeight <= 0 && tree->minItemHeight <= 0) return 0; return 1; } /* *-------------------------------------------------------------- * * DrawWhitespace -- * * Paints part of the whitespace region. * * Results: * If -itembackground colors are not being drawn into the * whitespace region, the dirtyRgn is filled with the treectrl's * -background color. Otherwise rows of color are drawn below * the last item and in the tail column if those columns have * any -itembackground colors specified. * * Side effects: * None. * *-------------------------------------------------------------- */ static void DrawWhitespace( TreeCtrl *tree, Drawable drawable, TkRegion dirtyRgn ) { TreeDInfo dInfo = tree->dInfo; int x, y, minX, minY, maxX, maxY; int top, bottom; int height, index; XRectangle columnBox; TkRegion columnRgn; Range *range; RItem *rItem; /* If we aren't drawing -itembackground colors in the whitespace region, * then just paint the entire dirty area with the treectrl's -background * color. */ if (!ComplexWhitespace(tree)) { GC gc = Tk_3DBorderGC(tree->tkwin, tree->border, TK_3D_FLAT_GC); Tk_FillRegion(tree->display, drawable, gc, dirtyRgn); return; } x = 0 - tree->xOrigin; y = 0 - tree->yOrigin; top = MAX(y + Tree_TotalHeight(tree), Tree_ContentTop(tree)); bottom = Tree_ContentBottom(tree); /* Figure out the height of each row of color below the items. */ if (tree->backgroundMode == BG_MODE_COLUMN) height = bottom - top; /* solid block of color */ else if (tree->itemHeight > 0) height = tree->itemHeight; else height = tree->minItemHeight; columnRgn = TkCreateRegion(); range = dInfo->rangeFirst; if (range == NULL) range = dInfo->rangeLock; if (!dInfo->empty) { minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; /* Draw to the right of the items using the tail * column's -itembackground colors. The height of each row matches * the height of the adjacent item. */ if (x + Tree_TotalWidth(tree) < maxX) { columnBox.y = Tree_ContentTop(tree); if (range == NULL) { rItem = NULL; index = 0; } else { /* Get the item at the top of the screen. */ if (range->totalHeight == 0) { rItem = range->last; /* all items have zero height */ } else { int y2 = minY + tree->yOrigin; /* Window -> canvas */ rItem = Range_ItemUnderPoint(tree, range, NULL, &y2); columnBox.y -= y2; } index = GetItemBgIndex(tree, rItem); } columnBox.x = x + Tree_TotalWidth(tree); columnBox.width = maxX - columnBox.x; columnBox.height = maxY - columnBox.y; TkSubtractRegion(columnRgn, columnRgn, columnRgn); TkUnionRectWithRegion(&columnBox, columnRgn, columnRgn); TkIntersectRegion(dirtyRgn, columnRgn, columnRgn); DrawColumnBackground(tree, drawable, tree->columnTail, columnRgn, &columnBox, rItem, height, index); } } if (top < bottom) { /* Get the display index of the last visible item. */ if (range == NULL) { index = 0; } else { rItem = range->last; index = GetItemBgIndex(tree, rItem); if (tree->backgroundMode != BG_MODE_COLUMN) { index++; } } /* Draw below non-locked columns. */ if (!dInfo->empty && Tree_TotalWidth(tree)/* && dInfo->rangeFirst != NULL */) { DrawWhitespaceBelowItem(tree, drawable, COLUMN_LOCK_NONE, dInfo->bounds, x, top, dirtyRgn, columnRgn, height, index); } /* Draw below the left columns. */ if (!dInfo->emptyL) { minX = dInfo->boundsL[0]; DrawWhitespaceBelowItem(tree, drawable, COLUMN_LOCK_LEFT, dInfo->boundsL, minX, top, dirtyRgn, columnRgn, height, index); } /* Draw below the right columns. */ if (!dInfo->emptyR) { minX = dInfo->boundsR[0]; DrawWhitespaceBelowItem(tree, drawable, COLUMN_LOCK_RIGHT, dInfo->boundsR, minX, top, dirtyRgn, columnRgn, height, index); } } TkDestroyRegion(columnRgn); } #endif /* COMPLEX_WHITESPACE */ /* *---------------------------------------------------------------------- * * Tree_DrawTiledImage -- * * This procedure draws a tiled image in the indicated box. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_DrawTiledImage( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ Tk_Image image, /* The image to draw. */ int x1, int y1, /* Left & top of area to fill with the image. */ int x2, int y2, /* Right & bottom, of area to fill with the * image. */ int xOffset, int yOffset /* Used to keep the image aligned with an * origin. */ ) { int imgWidth, imgHeight; int srcX, srcY; int srcW, srcH; int dstX, dstY; Tk_SizeOfImage(image, &imgWidth, &imgHeight); /* xOffset can be < 0 for left-locked columns. */ if (xOffset < 0) xOffset = imgWidth + xOffset % imgWidth; srcX = (x1 + xOffset) % imgWidth; dstX = x1; while (dstX < x2) { srcW = imgWidth - srcX; if (dstX + srcW > x2) { srcW = x2 - dstX; } srcY = (y1 + yOffset) % imgHeight; dstY = y1; while (dstY < y2) { srcH = imgHeight - srcY; if (dstY + srcH > y2) { srcH = y2 - dstY; } Tk_RedrawImage(image, srcX, srcY, srcW, srcH, drawable, dstX, dstY); srcY = 0; dstY += srcH; } srcX = 0; /* the last tile gives dstX == x2 which ends the while loop; same * for dstY above */ dstX += srcW; }; } /* *---------------------------------------------------------------------- * * DisplayDItem -- * * Draw a single item. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ static int DisplayDItem( TreeCtrl *tree, /* Widget info. */ DItem *dItem, DItemArea *area, int lock, /* Which set of columns. */ int bounds[4], /* TREE_AREA_xxx bounds of drawing. */ Drawable pixmap, /* Where to draw. */ Drawable drawable /* Where to copy to. */ ) { TreeDInfo dInfo = tree->dInfo; Tk_Window tkwin = tree->tkwin; int left, top, right, bottom; left = area->x; right = left + area->width; top = dItem->y; bottom = top + dItem->height; if (!(area->flags & DITEM_ALL_DIRTY)) { left += area->dirty[LEFT]; right = area->x + area->dirty[RIGHT]; top += area->dirty[TOP]; bottom = dItem->y + area->dirty[BOTTOM]; } area->flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY); if (left < bounds[0]) left = bounds[0]; if (right > bounds[2]) right = bounds[2]; if (top < bounds[1]) top = bounds[1]; if (bottom > bounds[3]) bottom = bounds[3]; if (right <= left || bottom <= top) return 0; if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, left, top, right - left, bottom - top); DisplayDelay(tree); } if (tree->doubleBuffer != DOUBLEBUFFER_NONE) { if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], left); dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], top); dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], right); dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], bottom); } /* The top-left corner of the drawable is at this * point in the canvas */ tree->drawableXOrigin = left + tree->xOrigin; tree->drawableYOrigin = top + tree->yOrigin; TreeItem_Draw(tree, dItem->item, lock, area->x - left, dItem->y - top, area->width, dItem->height, pixmap, 0, right - left, dItem->index); XCopyArea(tree->display, pixmap, drawable, tree->copyGC, 0, 0, right - left, bottom - top, left, top); } else { /* The top-left corner of the drawable is at this * point in the canvas */ tree->drawableXOrigin = tree->xOrigin; tree->drawableYOrigin = tree->yOrigin; TreeItem_Draw(tree, dItem->item, lock, area->x, dItem->y, area->width, dItem->height, drawable, left, right, dItem->index); } return 1; } void DebugDrawBorder( TreeCtrl *tree, int inset, int left, int top, int right, int bottom ) { Tk_Window tkwin = tree->tkwin; if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { if (left > 0) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, inset, inset, left, Tk_Height(tkwin) - inset * 2); } if (top > 0) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, inset, inset, Tk_Width(tkwin) - inset * 2, top); } if (right > 0) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, Tk_Width(tkwin) - inset - right, inset, right, Tk_Height(tkwin) - inset * 2); } if (bottom > 0) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, inset, Tk_Height(tkwin) - inset - bottom, Tk_Width(tkwin) - inset * 2, bottom); } DisplayDelay(tree); } } /* *-------------------------------------------------------------- * * TreeDisplay_GetReadyForTrouble -- * TreeDisplay_WasThereTrouble -- * * These 2 procedures are used to detect when something happens * during a display update that requests another display update. * If that happens, then the current display is aborted and we * try again (unless the window was destroyed). * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void TreeDisplay_GetReadyForTrouble( TreeCtrl *tree, int *requestsPtr ) { TreeDInfo dInfo = tree->dInfo; *requestsPtr = dInfo->requests; } int TreeDisplay_WasThereTrouble( TreeCtrl *tree, int requests ) { TreeDInfo dInfo = tree->dInfo; if (tree->deleted || (requests != dInfo->requests)) { if (tree->debug.enable) dbwin("TreeDisplay_WasThereTrouble: %p\n", tree); return 1; } return 0; } /* *-------------------------------------------------------------- * * Tree_Display -- * * This procedure is called at idle time when something has happened * that might require the list to be redisplayed. An effort is made * to only redraw what is needed. * * Results: * None. * * Side effects: * Stuff is drawn in the TreeCtrl window. * *-------------------------------------------------------------- */ void Tree_Display( ClientData clientData /* Widget info. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; TreeDInfo dInfo = tree->dInfo; DItem *dItem; Tk_Window tkwin = tree->tkwin; Drawable drawable = Tk_WindowId(tkwin); int minX, minY, maxX, maxY, height, width; int count; int numCopy = 0, numDraw = 0; TkRegion wsRgnNew, wsRgnDif; #ifdef COMPLEX_WHITESPACE int complexWhitespace; #endif XRectangle wsBox; int requests; if (tree->debug.enable && tree->debug.display && 0) dbwin("Tree_Display %s\n", Tk_PathName(tkwin)); if (tree->deleted) { dInfo->flags &= ~(DINFO_REDRAW_PENDING); return; } /* */ Tcl_Preserve((ClientData) tree); Tree_PreserveItems(tree); displayRetry: /* Some change requires selection changes */ if (dInfo->flags & DINFO_REDO_SELECTION) { #ifdef SELECTION_VISIBLE /* Possible event. */ Tree_DeselectHidden(tree); if (tree->deleted) goto displayExit; #endif dInfo->flags &= ~(DINFO_REDO_SELECTION); } /* DINFO_REDO_COLUMN_WIDTH - A column was created or deleted. */ /* DINFO_CHECK_COLUMN_WIDTH - The width of one or more columns * *might* have changed. Column visibility might have changed. */ if (dInfo->flags & (DINFO_REDO_COLUMN_WIDTH | DINFO_CHECK_COLUMN_WIDTH)) { TreeColumn treeColumn = tree->columns; ColumnInfo *cinfo; int force = (dInfo->flags & DINFO_REDO_COLUMN_WIDTH) != 0; int changed = force; if (dInfo->columnsSize < tree->columnCount) { dInfo->columnsSize = tree->columnCount + 10; dInfo->columns = (ColumnInfo *) ckrealloc((char *) dInfo->columns, sizeof(ColumnInfo) * dInfo->columnsSize); } /* Set max -itembackground as well. */ tree->columnBgCnt = 0; cinfo = dInfo->columns; while (treeColumn != NULL) { cinfo->column = treeColumn; cinfo->offset = TreeColumn_Offset(treeColumn); if (force || (cinfo->width != TreeColumn_UseWidth(treeColumn))) { cinfo->width = TreeColumn_UseWidth(treeColumn); changed = TRUE; } if (TreeColumn_Visible(treeColumn) && (TreeColumn_BackgroundCount(treeColumn) > tree->columnBgCnt)) tree->columnBgCnt = TreeColumn_BackgroundCount(treeColumn); ++cinfo; treeColumn = TreeColumn_Next(treeColumn); } dInfo->flags &= ~(DINFO_REDO_COLUMN_WIDTH | DINFO_CHECK_COLUMN_WIDTH); if (changed) { dInfo->flags |= DINFO_INVALIDATE | DINFO_OUT_OF_DATE | DINFO_REDO_RANGES | DINFO_DRAW_HEADER; } } if (dInfo->headerHeight != Tree_HeaderHeight(tree)) { dInfo->headerHeight = Tree_HeaderHeight(tree); dInfo->flags |= DINFO_OUT_OF_DATE | DINFO_SET_ORIGIN_Y | DINFO_UPDATE_SCROLLBAR_Y | DINFO_DRAW_HEADER; if (tree->vertical && (tree->wrapMode == TREE_WRAP_WINDOW)) dInfo->flags |= DINFO_REDO_RANGES; } if (dInfo->widthOfColumnsLeft != Tree_WidthOfLeftColumns(tree) || dInfo->widthOfColumnsRight != Tree_WidthOfRightColumns(tree)) { dInfo->widthOfColumnsLeft = Tree_WidthOfLeftColumns(tree); dInfo->widthOfColumnsRight = Tree_WidthOfRightColumns(tree); dInfo->flags |= DINFO_SET_ORIGIN_X | DINFO_UPDATE_SCROLLBAR_X/* | DINFO_OUT_OF_DATE | DINFO_REDO_RANGES | DINFO_DRAW_HEADER*/; } Range_RedoIfNeeded(tree); Increment_RedoIfNeeded(tree); if (dInfo->xOrigin != tree->xOrigin) { dInfo->flags |= DINFO_UPDATE_SCROLLBAR_X | DINFO_OUT_OF_DATE | DINFO_DRAW_HEADER; } if (dInfo->yOrigin != tree->yOrigin) { dInfo->flags |= DINFO_UPDATE_SCROLLBAR_Y | DINFO_OUT_OF_DATE; } if (dInfo->totalWidth != Tree_TotalWidth(tree)) { dInfo->totalWidth = Tree_TotalWidth(tree); dInfo->flags |= DINFO_SET_ORIGIN_X | DINFO_UPDATE_SCROLLBAR_X | DINFO_OUT_OF_DATE; } if (dInfo->totalHeight != Tree_TotalHeight(tree)) { dInfo->totalHeight = Tree_TotalHeight(tree); dInfo->flags |= DINFO_SET_ORIGIN_Y | DINFO_UPDATE_SCROLLBAR_Y | DINFO_OUT_OF_DATE; } if (dInfo->flags & DINFO_SET_ORIGIN_X) { Tree_SetOriginX(tree, tree->xOrigin); dInfo->flags &= ~DINFO_SET_ORIGIN_X; } if (dInfo->flags & DINFO_SET_ORIGIN_Y) { Tree_SetOriginY(tree, tree->yOrigin); dInfo->flags &= ~DINFO_SET_ORIGIN_Y; } #ifdef COMPLEX_WHITESPACE /* If -itembackground colors are being drawn in the whitespace region, * then redraw all the whitespace if: * a) scrolling occurs, or * b) all the display info was marked as invalid (such as when * -itembackground colors change, or a column moves), or * c) item/column sizes change (handled by Range_RedoIfNeeded). */ complexWhitespace = ComplexWhitespace(tree); if (complexWhitespace) { if ((dInfo->xOrigin != tree->xOrigin) || (dInfo->yOrigin != tree->yOrigin) || (dInfo->flags & DINFO_INVALIDATE)) { dInfo->flags |= DINFO_DRAW_WHITESPACE; } } /* If tree->columnBgCnt was > 0 but is now 0, redraw whitespace. */ if (complexWhitespace != dInfo->complexWhitespace) { dInfo->complexWhitespace = complexWhitespace; dInfo->flags |= DINFO_DRAW_WHITESPACE; } #endif /* * dInfo->requests counts the number of calls to Tree_EventuallyRedraw(). * If binding scripts do something that causes a redraw to be requested, * then we abort the current draw and start again. */ TreeDisplay_GetReadyForTrouble(tree, &requests); if (dInfo->flags & DINFO_UPDATE_SCROLLBAR_X) { /* Possible event. */ Tree_UpdateScrollbarX(tree); dInfo->flags &= ~DINFO_UPDATE_SCROLLBAR_X; } if (dInfo->flags & DINFO_UPDATE_SCROLLBAR_Y) { /* Possible event. */ Tree_UpdateScrollbarY(tree); dInfo->flags &= ~DINFO_UPDATE_SCROLLBAR_Y; } if (tree->deleted || !Tk_IsMapped(tkwin)) goto displayExit; if (TreeDisplay_WasThereTrouble(tree, requests)) { goto displayRetry; } if (dInfo->flags & DINFO_OUT_OF_DATE) { Tree_UpdateDInfo(tree); dInfo->flags &= ~DINFO_OUT_OF_DATE; } /* * When an item goes from visible to hidden, "window" elements in the * item must be hidden. An item may become hidden because of scrolling, * or because an ancestor was collapsed, or because the -visible option * of the item changed. */ { Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeItemList newV, newH; TreeItem item; int isNew, i, count; TreeItemList_Init(tree, &newV, 0); TreeItemList_Init(tree, &newH, 0); for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { hPtr = Tcl_FindHashEntry(&dInfo->itemVisHash, (char *) dItem->item); if (hPtr == NULL) { /* This item is now visible, wasn't before */ TreeItemList_Append(&newV, dItem->item); TreeItem_OnScreen(tree, dItem->item, TRUE); } #ifdef DCOLUMN /* The item was onscreen and still is. Figure out which * item-columns have become visible or hidden. */ else { TrackOnScreenColumnsForItem(tree, dItem->item, hPtr); } #endif /* DCOLUMN */ } hPtr = Tcl_FirstHashEntry(&dInfo->itemVisHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&dInfo->itemVisHash, hPtr); if (TreeItem_GetDInfo(tree, item) == NULL) { /* This item was visible but isn't now */ TreeItemList_Append(&newH, item); TreeItem_OnScreen(tree, item, FALSE); } hPtr = Tcl_NextHashEntry(&search); } /* Remove newly-hidden items from itemVisHash */ count = TreeItemList_Count(&newH); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&newH, i); hPtr = Tcl_FindHashEntry(&dInfo->itemVisHash, (char *) item); #ifdef DCOLUMN TrackOnScreenColumnsForItem(tree, item, hPtr); ckfree((char *) Tcl_GetHashValue(hPtr)); #endif Tcl_DeleteHashEntry(hPtr); } /* Add newly-visible items to itemVisHash */ count = TreeItemList_Count(&newV); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&newV, i); hPtr = Tcl_CreateHashEntry(&dInfo->itemVisHash, (char *) item, &isNew); #ifdef DCOLUMN TrackOnScreenColumnsForItem(tree, item, hPtr); #endif /* DCOLUMN */ } /* * Generate an event here. This can be used to set * an item's styles when the item is about to be displayed, and to * clear an item's styles when the item is no longer displayed. */ if (TreeItemList_Count(&newV) || TreeItemList_Count(&newH)) { TreeNotify_ItemVisibility(tree, &newV, &newH); } TreeItemList_Free(&newV); TreeItemList_Free(&newH); if (tree->deleted || !Tk_IsMapped(tkwin)) goto displayExit; if (TreeDisplay_WasThereTrouble(tree, requests)) goto displayRetry; } if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { dInfo->dirty[LEFT] = dInfo->dirty[TOP] = 100000; dInfo->dirty[RIGHT] = dInfo->dirty[BOTTOM] = -100000; drawable = dInfo->pixmap; } /* XOR off */ TreeColumnProxy_Undisplay(tree); TreeRowProxy_Undisplay(tree); TreeDragImage_Undisplay(tree->dragImage); TreeMarquee_Undisplay(tree->marquee); if (dInfo->flags & DINFO_DRAW_HEADER) { if (Tree_AreaBbox(tree, TREE_AREA_HEADER, &minX, &minY, &maxX, &maxY)) { if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, minX, minY, maxX - minX, maxY - minY); DisplayDelay(tree); } Tree_DrawHeader(tree, drawable, 0 - tree->xOrigin, Tree_HeaderTop(tree)); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { dInfo->dirty[LEFT] = minX; dInfo->dirty[TOP] = minY; dInfo->dirty[RIGHT] = maxX; dInfo->dirty[BOTTOM] = maxY; } } dInfo->flags &= ~DINFO_DRAW_HEADER; } if (tree->vertical) { numCopy = ScrollVerticalComplex(tree); ScrollHorizontalSimple(tree); } else { ScrollVerticalSimple(tree); numCopy = ScrollHorizontalComplex(tree); } /* If we scrolled, then copy the entire pixmap, plus the header * if needed. */ if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { if ((dInfo->xOrigin != tree->xOrigin) || (dInfo->yOrigin != tree->yOrigin)) { dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], Tree_BorderLeft(tree)); /* might include header */ dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], Tree_ContentTop(tree)); dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], Tree_BorderRight(tree)); dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], Tree_ContentBottom(tree)); } } if (dInfo->flags & DINFO_DRAW_WHITESPACE) { TkSubtractRegion(dInfo->wsRgn, dInfo->wsRgn, dInfo->wsRgn); dInfo->flags &= ~DINFO_DRAW_WHITESPACE; } if (tree->backgroundImage != NULL) { wsRgnNew = CalcWhiteSpaceRegion(tree); /* If we scrolled, redraw entire whitespace area */ if (dInfo->xOrigin != tree->xOrigin || dInfo->yOrigin != tree->yOrigin) { wsRgnDif = wsRgnNew; } else { wsRgnDif = TkCreateRegion(); TkSubtractRegion(wsRgnNew, dInfo->wsRgn, wsRgnDif); } TkClipBox(wsRgnDif, &wsBox); if ((wsBox.width > 0) && (wsBox.height > 0)) { Drawable pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), wsBox.width, wsBox.height, Tk_Depth(tkwin)); GC gc = Tk_3DBorderGC(tkwin, tree->border, TK_3D_FLAT_GC); if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { Tk_FillRegion(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, wsRgnDif); DisplayDelay(tree); } /* FIXME: only if backgroundImage is transparent */ Tk_OffsetRegion(wsRgnDif, -wsBox.x, -wsBox.y); Tk_FillRegion(tree->display, pixmap, gc, wsRgnDif); Tk_OffsetRegion(wsRgnDif, wsBox.x, wsBox.y); /* tree->drawableXOrigin = tree->xOrigin + wsBox.x; tree->drawableYOrigin = tree->yOrigin + wsBox.y;*/ Tree_DrawTiledImage(tree, pixmap, tree->backgroundImage, 0, 0, wsBox.width, wsBox.height, tree->xOrigin + wsBox.x, tree->yOrigin + wsBox.y); TkSetRegion(tree->display, tree->copyGC, wsRgnNew); /* XSetClipOrigin(tree->display, tree->copyGC, 0, 0);*/ XCopyArea(tree->display, pixmap, drawable, tree->copyGC, 0, 0, wsBox.width, wsBox.height, wsBox.x, wsBox.y); XSetClipMask(tree->display, tree->copyGC, None); /* XSetClipOrigin(tree->display, tree->copyGC, 0, 0);*/ Tk_FreePixmap(tree->display, pixmap); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], wsBox.x); dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], wsBox.y); dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], wsBox.x + wsBox.width); dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], wsBox.y + wsBox.height); } } if (wsRgnDif != wsRgnNew) TkDestroyRegion(wsRgnDif); TkDestroyRegion(dInfo->wsRgn); dInfo->wsRgn = wsRgnNew; } dInfo->xOrigin = tree->xOrigin; dInfo->yOrigin = tree->yOrigin; /* Does this need to be here? */ dInfo->flags &= ~(DINFO_REDRAW_PENDING); if (tree->backgroundImage == NULL) { /* Calculate the current whitespace region, subtract the old whitespace * region, and fill the difference with the background color. */ wsRgnNew = CalcWhiteSpaceRegion(tree); wsRgnDif = TkCreateRegion(); TkSubtractRegion(wsRgnNew, dInfo->wsRgn, wsRgnDif); TkClipBox(wsRgnDif, &wsBox); if ((wsBox.width > 0) && (wsBox.height > 0)) { #ifndef COMPLEX_WHITESPACE GC gc = Tk_3DBorderGC(tkwin, tree->border, TK_3D_FLAT_GC); #endif if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { Tk_FillRegion(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, wsRgnDif); DisplayDelay(tree); } #ifdef COMPLEX_WHITESPACE DrawWhitespace(tree, drawable, wsRgnDif); #else Tk_FillRegion(tree->display, drawable, gc, wsRgnDif); #endif if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], wsBox.x); dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], wsBox.y); dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], wsBox.x + wsBox.width); dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], wsBox.y + wsBox.height); } } TkDestroyRegion(wsRgnDif); TkDestroyRegion(dInfo->wsRgn); dInfo->wsRgn = wsRgnNew; } /* See if there are any dirty items */ count = 0; for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { if ((!dInfo->empty && dInfo->rangeFirst != NULL) && (dItem->area.flags & DITEM_DIRTY)) { count++; break; } if (!dInfo->emptyL && (dItem->left.flags & DITEM_DIRTY)) { count++; break; } if (!dInfo->emptyR && (dItem->right.flags & DITEM_DIRTY)) { count++; break; } } /* Display dirty items */ if (count > 0) { Drawable pixmap = drawable; if (tree->doubleBuffer != DOUBLEBUFFER_NONE) { /* Allocate pixmap for largest item */ width = MIN(Tk_Width(tkwin), dInfo->itemWidth); height = MIN(Tk_Height(tkwin), dInfo->itemHeight); pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), width, height, Tk_Depth(tkwin)); } for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { int drawn = 0; if (!dInfo->empty && dInfo->rangeFirst != NULL) { tree->drawableXOrigin = tree->xOrigin; tree->drawableYOrigin = tree->yOrigin; TreeItem_UpdateWindowPositions(tree, dItem->item, COLUMN_LOCK_NONE, dItem->area.x, dItem->y, dItem->area.width, dItem->height); if (TreeDisplay_WasThereTrouble(tree, requests)) { if (tree->deleted || !Tk_IsMapped(tree->tkwin)) goto displayExit; goto displayRetry; } if (dItem->area.flags & DITEM_DIRTY) { drawn += DisplayDItem(tree, dItem, &dItem->area, COLUMN_LOCK_NONE, dInfo->bounds, pixmap, drawable); } } if (!dInfo->emptyL) { tree->drawableXOrigin = tree->xOrigin; tree->drawableYOrigin = tree->yOrigin; TreeItem_UpdateWindowPositions(tree, dItem->item, COLUMN_LOCK_LEFT, dItem->left.x, dItem->y, dItem->left.width, dItem->height); if (TreeDisplay_WasThereTrouble(tree, requests)) { if (tree->deleted || !Tk_IsMapped(tree->tkwin)) goto displayExit; goto displayRetry; } if (dItem->left.flags & DITEM_DIRTY) { drawn += DisplayDItem(tree, dItem, &dItem->left, COLUMN_LOCK_LEFT, dInfo->boundsL, pixmap, drawable); } } if (!dInfo->emptyR) { tree->drawableXOrigin = tree->xOrigin; tree->drawableYOrigin = tree->yOrigin; TreeItem_UpdateWindowPositions(tree, dItem->item, COLUMN_LOCK_RIGHT, dItem->right.x, dItem->y, dItem->right.width, dItem->height); if (TreeDisplay_WasThereTrouble(tree, requests)) { if (tree->deleted || !Tk_IsMapped(tree->tkwin)) goto displayExit; goto displayRetry; } if (dItem->right.flags & DITEM_DIRTY) { drawn += DisplayDItem(tree, dItem, &dItem->right, COLUMN_LOCK_RIGHT, dInfo->boundsR, pixmap, drawable); } } numDraw += drawn ? 1 : 0; dItem->oldX = dItem->area.x; /* FIXME: could have dInfo->empty */ dItem->oldY = dItem->y; dItem->oldIndex = dItem->index; } if (tree->doubleBuffer != DOUBLEBUFFER_NONE) Tk_FreePixmap(tree->display, pixmap); } if (tree->debug.enable && tree->debug.display) dbwin("copy %d draw %d %s\n", numCopy, numDraw, Tk_PathName(tkwin)); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { drawable = Tk_WindowId(tkwin); if (dInfo->dirty[LEFT] < dInfo->dirty[RIGHT]) { XCopyArea(tree->display, dInfo->pixmap, drawable, tree->copyGC, dInfo->dirty[LEFT], dInfo->dirty[TOP], dInfo->dirty[RIGHT] - dInfo->dirty[LEFT], dInfo->dirty[BOTTOM] - dInfo->dirty[TOP], dInfo->dirty[LEFT], dInfo-> dirty[TOP]); } } /* XOR on */ TreeMarquee_Display(tree->marquee); TreeDragImage_Display(tree->dragImage); TreeRowProxy_Display(tree); TreeColumnProxy_Display(tree); if (tree->doubleBuffer == DOUBLEBUFFER_NONE) dInfo->flags |= DINFO_DRAW_HIGHLIGHT | DINFO_DRAW_BORDER; /* Draw focus rectangle (outside of 3D-border) */ if ((dInfo->flags & DINFO_DRAW_HIGHLIGHT) && (tree->highlightWidth > 0)) { GC fgGC, bgGC; DebugDrawBorder(tree, 0, tree->highlightWidth, tree->highlightWidth, tree->highlightWidth, tree->highlightWidth); bgGC = Tk_GCForColor(tree->highlightBgColorPtr, drawable); if (tree->gotFocus) fgGC = Tk_GCForColor(tree->highlightColorPtr, drawable); else fgGC = bgGC; TkpDrawHighlightBorder(tkwin, fgGC, bgGC, tree->highlightWidth, drawable); dInfo->flags &= ~DINFO_DRAW_HIGHLIGHT; } /* Draw 3D-border (inside of focus rectangle) */ if ((dInfo->flags & DINFO_DRAW_BORDER) && (tree->borderWidth > 0)) { DebugDrawBorder(tree, tree->highlightWidth, tree->borderWidth, tree->borderWidth, tree->borderWidth, tree->borderWidth); Tk_Draw3DRectangle(tkwin, drawable, tree->border, tree->highlightWidth, tree->highlightWidth, Tk_Width(tkwin) - tree->highlightWidth * 2, Tk_Height(tkwin) - tree->highlightWidth * 2, tree->borderWidth, tree->relief); dInfo->flags &= ~DINFO_DRAW_BORDER; } displayExit: dInfo->flags &= ~(DINFO_REDRAW_PENDING); Tree_ReleaseItems(tree); Tcl_Release((ClientData) tree); } /* *-------------------------------------------------------------- * * A_IncrementFindX -- * * Return a horizontal scroll position nearest to the given * offset. * * Results: * Index of the nearest increment <= the given offset. * * Side effects: * None. * *-------------------------------------------------------------- */ static int A_IncrementFindX( TreeCtrl *tree, /* Widget info. */ int offset /* Canvas x-coordinate. */ ) { int totWidth = Tree_TotalWidth(tree); int xIncr = tree->xScrollIncrement; int index, indexMax; indexMax = totWidth / xIncr; if (totWidth % xIncr == 0) indexMax--; if (offset < 0) offset = 0; index = offset / xIncr; if (index > indexMax) index = indexMax; return index; } /* *-------------------------------------------------------------- * * A_IncrementFindY -- * * Return a vertical scroll position nearest to the given * offset. * * Results: * Index of the nearest increment <= the given offset. * * Side effects: * None. * *-------------------------------------------------------------- */ static int A_IncrementFindY( TreeCtrl *tree, /* Widget info. */ int offset /* Canvas y-coordinate. */ ) { int totHeight = Tree_TotalHeight(tree); int yIncr = tree->yScrollIncrement; int index, indexMax; indexMax = totHeight / yIncr; if (totHeight % yIncr == 0) indexMax--; if (offset < 0) offset = 0; index = offset / yIncr; if (index > indexMax) index = indexMax; return index; } /* *-------------------------------------------------------------- * * Increment_FindX -- * * Return a horizontal scroll position nearest to the given * offset. * * Results: * Index of the nearest increment <= the given offset. * * Side effects: * None. * *-------------------------------------------------------------- */ int Increment_FindX( TreeCtrl *tree, /* Widget info. */ int offset /* Canvas x-coordinate. */ ) { if (tree->xScrollIncrement <= 0) { Increment_RedoIfNeeded(tree); return B_IncrementFindX(tree, offset); } return A_IncrementFindX(tree, offset); } /* *-------------------------------------------------------------- * * Increment_FindY -- * * Return a vertical scroll position nearest to the given * offset. * * Results: * Index of the nearest increment <= the given offset. * * Side effects: * None. * *-------------------------------------------------------------- */ int Increment_FindY( TreeCtrl *tree, /* Widget info. */ int offset /* Canvas y-coordinate. */ ) { if (tree->yScrollIncrement <= 0) { Increment_RedoIfNeeded(tree); return B_IncrementFindY(tree, offset); } return A_IncrementFindY(tree, offset); } /* *-------------------------------------------------------------- * * Increment_ToOffsetX -- * * Return the canvas coordinate for a scroll position. * * Results: * Pixel distance. * * Side effects: * None. * *-------------------------------------------------------------- */ int Increment_ToOffsetX( TreeCtrl *tree, /* Widget info. */ int index /* Index of the increment. */ ) { TreeDInfo dInfo = tree->dInfo; if (tree->xScrollIncrement <= 0) { if (index < 0 || index >= dInfo->xScrollIncrementCount) panic("Increment_ToOffsetX: bad index %d (must be 0-%d)", index, dInfo->xScrollIncrementCount-1); return dInfo->xScrollIncrements[index]; } return index * tree->xScrollIncrement; } /* *-------------------------------------------------------------- * * Increment_ToOffsetY -- * * Return the canvas coordinate for a scroll position. * * Results: * Pixel distance. * * Side effects: * None. * *-------------------------------------------------------------- */ int Increment_ToOffsetY( TreeCtrl *tree, /* Widget info. */ int index /* Index of the increment. */ ) { TreeDInfo dInfo = tree->dInfo; if (tree->yScrollIncrement <= 0) { if (index < 0 || index >= dInfo->yScrollIncrementCount) { panic("Increment_ToOffsetY: bad index %d (must be 0-%d)\ntotHeight %d visHeight %d", index, dInfo->yScrollIncrementCount - 1, Tree_TotalHeight(tree), Tree_ContentHeight(tree)); } return dInfo->yScrollIncrements[index]; } return index * tree->yScrollIncrement; } /* *-------------------------------------------------------------- * * GetScrollFractions -- * * Return the fractions that may be passed to a scrollbar "set" * command. * * Results: * Two fractions from 0.0 to 1.0. * * Side effects: * None. * *-------------------------------------------------------------- */ static void GetScrollFractions( int screen1, int screen2, /* Min/max coordinates that are visible in * the window. */ int object1, int object2, /* Min/max coordinates of the scrollable * content (usually 0 to N where N is the * total width or height of the canvas). */ double fractions[2] /* Returned values. */ ) { double range, f1, f2; range = object2 - object1; if (range <= 0) { f1 = 0; f2 = 1.0; } else { f1 = (screen1 - object1) / range; if (f1 < 0) f1 = 0.0; f2 = (screen2 - object1) / range; if (f2 > 1.0) f2 = 1.0; if (f2 < f1) f2 = f1; } fractions[0] = f1; fractions[1] = f2; } /* *-------------------------------------------------------------- * * Tree_GetScrollFractionsX -- * * Return the fractions that may be passed to a scrollbar "set" * command for a horizontal scrollbar. * * Results: * Two fractions from 0 to 1.0. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_GetScrollFractionsX( TreeCtrl *tree, /* Widget info. */ double fractions[2] /* Returned values. */ ) { int left = tree->xOrigin + Tree_ContentLeft(tree); int visWidth = Tree_ContentWidth(tree); int totWidth = Tree_TotalWidth(tree); int index, offset; /* The tree is empty, or everything fits in the window */ if (visWidth < 0) visWidth = 0; if (totWidth <= visWidth) { fractions[0] = 0.0; fractions[1] = 1.0; return; } if (visWidth <= 1) { GetScrollFractions(left, left + 1, 0, totWidth, fractions); return; } /* Find incrementLeft when scrolled to extreme right */ index = Increment_FindX(tree, totWidth - visWidth); offset = Increment_ToOffsetX(tree, index); if (offset < totWidth - visWidth) { index++; offset = Increment_ToOffsetX(tree, index); } /* Add some fake content to right */ if (offset + visWidth > totWidth) totWidth = offset + visWidth; GetScrollFractions(left, left + visWidth, 0, totWidth, fractions); } /* *-------------------------------------------------------------- * * Tree_GetScrollFractionsY -- * * Return the fractions that may be passed to a scrollbar "set" * command for a vertical scrollbar. * * Results: * Two fractions from 0 to 1.0. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_GetScrollFractionsY( TreeCtrl *tree, /* Widget info. */ double fractions[2] /* Returned values. */ ) { int top = Tree_ContentTop(tree) + tree->yOrigin; /* canvas coords */ int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); int index, offset; /* The tree is empty, or everything fits in the window */ if (visHeight < 0) visHeight = 0; if (totHeight <= visHeight) { fractions[0] = 0.0; fractions[1] = 1.0; return; } if (visHeight <= 1) { GetScrollFractions(top, top + 1, 0, totHeight, fractions); return; } /* Find incrementTop when scrolled to bottom */ index = Increment_FindY(tree, totHeight - visHeight); offset = Increment_ToOffsetY(tree, index); if (offset < totHeight - visHeight) { index++; offset = Increment_ToOffsetY(tree, index); } /* Add some fake content to bottom */ if (offset + visHeight > totHeight) totHeight = offset + visHeight; GetScrollFractions(top, top + visHeight, 0, totHeight, fractions); } /* *-------------------------------------------------------------- * * Tree_SetOriginX -- * * Change the horizontal scroll position. * * Results: * None. * * Side effects: * If the horizontal scroll position changes, then the widget is * redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_SetOriginX( TreeCtrl *tree, /* Widget info. */ int xOrigin /* The desired offset from the left edge * of the window to the left edge of the * canvas. The actual value will be clipped * to the nearest scroll increment. */ ) { TreeDInfo dInfo = tree->dInfo; int totWidth = Tree_TotalWidth(tree); int visWidth = Tree_ContentWidth(tree); int index, indexMax, offset; /* The tree is empty, or everything fits in the window */ if (visWidth < 0) visWidth = 0; if (totWidth <= visWidth) { xOrigin = 0 - Tree_ContentLeft(tree); if (xOrigin != tree->xOrigin) { tree->xOrigin = xOrigin; dInfo->incrementLeft = 0; Tree_EventuallyRedraw(tree); } return; } if (visWidth > 1) { /* Find incrementLeft when scrolled to extreme right */ indexMax = Increment_FindX(tree, totWidth - visWidth); offset = Increment_ToOffsetX(tree, indexMax); if (offset < totWidth - visWidth) { indexMax++; offset = Increment_ToOffsetX(tree, indexMax); } /* Add some fake content to right */ if (offset + visWidth > totWidth) totWidth = offset + visWidth; } else indexMax = Increment_FindX(tree, totWidth); xOrigin += Tree_ContentLeft(tree); /* origin -> canvas */ index = Increment_FindX(tree, xOrigin); /* Don't scroll too far left */ if (index < 0) index = 0; /* Don't scroll too far right */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetX(tree, index); xOrigin = offset - Tree_ContentLeft(tree); if (xOrigin == tree->xOrigin) return; tree->xOrigin = xOrigin; dInfo->incrementLeft = index; Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * Tree_SetOriginY -- * * Change the vertical scroll position. * * Results: * None. * * Side effects: * If the vertical scroll position changes, then the widget is * redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_SetOriginY( TreeCtrl *tree, /* Widget info. */ int yOrigin /* The desired offset from the top edge * of the window to the top edge of the * canvas. The actual value will be clipped * to the nearest scroll increment. */ ) { TreeDInfo dInfo = tree->dInfo; int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); int index, indexMax, offset; /* The tree is empty, or everything fits in the window */ if (visHeight < 0) visHeight = 0; if (totHeight <= visHeight) { yOrigin = 0 - Tree_ContentTop(tree); if (yOrigin != tree->yOrigin) { tree->yOrigin = yOrigin; dInfo->incrementTop = 0; Tree_EventuallyRedraw(tree); } return; } if (visHeight > 1) { /* Find incrementTop when scrolled to bottom */ indexMax = Increment_FindY(tree, totHeight - visHeight); offset = Increment_ToOffsetY(tree, indexMax); if (offset < totHeight - visHeight) { indexMax++; offset = Increment_ToOffsetY(tree, indexMax); } /* Add some fake content to bottom */ if (offset + visHeight > totHeight) totHeight = offset + visHeight; } else indexMax = Increment_FindY(tree, totHeight); yOrigin += Tree_ContentTop(tree); /* origin -> canvas */ index = Increment_FindY(tree, yOrigin); /* Don't scroll too far left */ if (index < 0) index = 0; /* Don't scroll too far right */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetY(tree, index); yOrigin = offset - Tree_ContentTop(tree); if (yOrigin == tree->yOrigin) return; tree->yOrigin = yOrigin; dInfo->incrementTop = index; Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * Tree_EventuallyRedraw -- * * Schedule an idle task to redisplay the widget, if one is not * already scheduled and the widget is mapped and the widget * hasn't been deleted. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_EventuallyRedraw( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; dInfo->requests++; if ((dInfo->flags & DINFO_REDRAW_PENDING) || tree->deleted || !Tk_IsMapped(tree->tkwin)) { return; } dInfo->flags |= DINFO_REDRAW_PENDING; Tcl_DoWhenIdle(Tree_Display, (ClientData) tree); } /* *-------------------------------------------------------------- * * Tree_RelayoutWindow -- * * Invalidate all the layout info for the widget and schedule a * redisplay at idle time. This gets called when certain config * options change and when the size of the widget changes. * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_RelayoutWindow( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; FreeDItems(tree, dInfo->dItem, NULL, 0); dInfo->dItem = NULL; dInfo->flags |= DINFO_REDO_RANGES | DINFO_OUT_OF_DATE | DINFO_CHECK_COLUMN_WIDTH | DINFO_DRAW_HEADER | DINFO_SET_ORIGIN_X | DINFO_SET_ORIGIN_Y | DINFO_UPDATE_SCROLLBAR_X | DINFO_UPDATE_SCROLLBAR_Y; if (tree->highlightWidth > 0) dInfo->flags |= DINFO_DRAW_HIGHLIGHT; if (tree->borderWidth > 0) dInfo->flags |= DINFO_DRAW_BORDER; dInfo->xOrigin = tree->xOrigin; dInfo->yOrigin = tree->yOrigin; /* Needed if -background color changes. */ dInfo->flags |= DINFO_DRAW_WHITESPACE; if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { if (dInfo->pixmap == None) { dInfo->pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tree->tkwin), Tk_Width(tree->tkwin), Tk_Height(tree->tkwin), Tk_Depth(tree->tkwin)); } else if ((tree->prevWidth != Tk_Width(tree->tkwin)) || (tree->prevHeight != Tk_Height(tree->tkwin))) { Tk_FreePixmap(tree->display, dInfo->pixmap); dInfo->pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tree->tkwin), Tk_Width(tree->tkwin), Tk_Height(tree->tkwin), Tk_Depth(tree->tkwin)); } } else if (dInfo->pixmap != None) { Tk_FreePixmap(tree->display, dInfo->pixmap); dInfo->pixmap = None; } Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * Tree_FocusChanged -- * * This procedure handles the widget gaining or losing the input * focus. The state of every item has STATE_FOCUS toggled on or * off. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time if -highlightthickness * is > 0, or if any Elements change appearance because of the * state change. * *-------------------------------------------------------------- */ void Tree_FocusChanged( TreeCtrl *tree, /* Widget info. */ int gotFocus /* TRUE if the widget has the focus, * otherwise FALSE. */ ) { TreeDInfo dInfo = tree->dInfo; TreeItem item; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int stateOn, stateOff; tree->gotFocus = gotFocus; if (gotFocus) stateOff = 0, stateOn = STATE_FOCUS; else stateOff = STATE_FOCUS, stateOn = 0; /* Slow. Change state of every item */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_ChangeState(tree, item, stateOff, stateOn); hPtr = Tcl_NextHashEntry(&search); } if (tree->highlightWidth > 0) { dInfo->flags |= DINFO_DRAW_HIGHLIGHT; Tree_EventuallyRedraw(tree); } } /* *-------------------------------------------------------------- * * Tree_Activate -- * * This procedure handles the widget's toplevel being the "active" * foreground window (on Macintosh and Windows). Currently it just * redraws the header if -usetheme is TRUE and the header is * visible. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_Activate( TreeCtrl *tree, /* Widget info. */ int isActive /* TRUE if the widget's toplevel is the * active window, otherwise FALSE. */ ) { TreeDInfo dInfo = tree->dInfo; tree->isActive = isActive; /* TODO: Like Tree_FocusChanged, change state of every item. */ /* Would need a new item state STATE_ACTIVEWINDOW or something. */ /* Would want to merge this with Tree_FocusChanged code to avoid * double-iteration of items. */ /* Aqua column header looks different when window is not active */ if (tree->useTheme && tree->showHeader) { dInfo->flags |= DINFO_DRAW_HEADER; Tree_EventuallyRedraw(tree); } } /* *-------------------------------------------------------------- * * Tree_FreeItemDInfo -- * * Free any DItem associated with each item in a range of items. * This is called when the size of an item changed or an item is * deleted. * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_FreeItemDInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item1, /* First item in the range. */ TreeItem item2 /* Last item in the range, or NULL. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; TreeItem item = item1; int changed = 0; while (item != NULL) { dItem = (DItem *) TreeItem_GetDInfo(tree, item); if (dItem != NULL) { FreeDItems(tree, dItem, dItem->next, 1); changed = 1; } if (item == item2 || item2 == NULL) break; item = TreeItem_Next(tree, item); } changed = 1; if (changed) { dInfo->flags |= DINFO_OUT_OF_DATE; Tree_EventuallyRedraw(tree); } } /* *-------------------------------------------------------------- * * Tree_InvalidateItemDInfo -- * * Mark as dirty any DItem associated with each item in a range * of items. This is called when the appearance of an item changed * (but not its size). * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time if any of the items * had a DItem. * *-------------------------------------------------------------- */ void Tree_InvalidateItemDInfo( TreeCtrl *tree, /* Widget info. */ TreeColumn column, /* Column to invalidate, or NULL for all. */ TreeItem item1, /* First item in the range. */ TreeItem item2 /* Last item in the range, or NULL. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; TreeItem item = item1; int changed = 0; if (dInfo->flags & (DINFO_INVALIDATE | DINFO_REDO_COLUMN_WIDTH)) return; while (item != NULL) { dItem = (DItem *) TreeItem_GetDInfo(tree, item); if (dItem != NULL) { if (column == NULL) { dItem->area.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY); dItem->left.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY); dItem->right.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY); } else { /* Do NOT call TreeColumn_UseWidth() or another routine * that calls Tree_WidthOfColumns() because that may end * up recalculating the size of items whose display info * is currently being invalidated. */ int columnIndex = TreeColumn_Index(column); int i, left = dInfo->columns[columnIndex].offset; /* This may not be the actual display width if this is the * only visible non-locked column. */ int width = dInfo->columns[columnIndex].width; /* If a hidden column was moved we can't rely on * dInfo->columns[] being in the right order. */ if (dInfo->flags & DINFO_CHECK_COLUMN_WIDTH) { for (i = 0; i < tree->columnCount; i++) { if (dInfo->columns[i].column == column) break; } if (i == tree->columnCount) { panic("Tree_InvalidateItemDInfo: can't find a column"); } left = dInfo->columns[i].offset; width = dInfo->columns[i].width; } /* Calculate the width of the entire span. */ if (dItem->spans == NULL) { width = dInfo->columns[columnIndex].width; /* If the column being redrawn is not the first in the span, * then do nothing. */ } else if (columnIndex != dItem->spans[columnIndex]) { goto next; } else { width = 0; i = columnIndex; while (dItem->spans[i] == columnIndex) { width += dInfo->columns[i].width; if (++i == tree->columnCount) break; } } switch (TreeColumn_Lock(column)) { case COLUMN_LOCK_NONE: if (tree->columnCountVis == 1) width = dItem->area.width; InvalidateDItemX(dItem, &dItem->area, 0, left, width); InvalidateDItemY(dItem, &dItem->area, dItem->y, dItem->y, dItem->height); dItem->area.flags |= DITEM_DIRTY; break; case COLUMN_LOCK_LEFT: InvalidateDItemX(dItem, &dItem->left, 0, left, width); InvalidateDItemY(dItem, &dItem->left, 0, 0, dItem->height); dItem->left.flags |= DITEM_DIRTY; break; case COLUMN_LOCK_RIGHT: InvalidateDItemX(dItem, &dItem->right, 0, left, width); InvalidateDItemY(dItem, &dItem->right, 0, 0, dItem->height); dItem->right.flags |= DITEM_DIRTY; break; } } changed = 1; } next: if (item == item2 || item2 == NULL) break; item = TreeItem_Next(tree, item); } if (changed) { Tree_EventuallyRedraw(tree); } } /* *-------------------------------------------------------------- * * TreeDisplay_ItemDeleted -- * * Removes an item from the hash table of on-screen items. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void TreeDisplay_ItemDeleted( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item to remove. */ ) { TreeDInfo dInfo = tree->dInfo; Tcl_HashEntry *hPtr; hPtr = Tcl_FindHashEntry(&dInfo->itemVisHash, (char *) item); if (hPtr != NULL) { #ifdef DCOLUMN ckfree((char *) Tcl_GetHashValue(hPtr)); #endif Tcl_DeleteHashEntry(hPtr); } } /* *-------------------------------------------------------------- * * TreeDisplay_ColumnDeleted -- * * Removes a column from the list of on-screen columns for * all on-screen items. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void TreeDisplay_ColumnDeleted( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column to remove. */ ) { #ifdef DCOLUMN TreeDInfo dInfo = tree->dInfo; Tcl_HashSearch search; Tcl_HashEntry *hPtr; TreeColumn *value; int i; hPtr = Tcl_FirstHashEntry(&dInfo->itemVisHash, &search); while (hPtr != NULL) { value = (TreeColumn *) Tcl_GetHashValue(hPtr); for (i = 0; value[i] != NULL; i++) { if (value[i] == column) { while (value[i] != NULL) { value[i] = value[i + 1]; ++i; } if (tree->debug.enable && tree->debug.display) dbwin("TreeDisplay_ColumnDeleted item %d column %d\n", TreeItem_GetID(tree, (TreeItem) Tcl_GetHashKey(&dInfo->itemVisHash, hPtr)), TreeColumn_GetID(column)); break; } } hPtr = Tcl_NextHashEntry(&search); } #endif } /* *-------------------------------------------------------------- * * Tree_DInfoChanged -- * * Set some DINFO_xxx flags and schedule a redisplay. * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_DInfoChanged( TreeCtrl *tree, /* Widget info. */ int flags /* DINFO_xxx flags. */ ) { TreeDInfo dInfo = tree->dInfo; dInfo->flags |= flags; Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * Tree_InvalidateArea -- * * Mark as dirty parts of any DItems in the given area. If the given * area overlaps the borders they are marked as needing to be * redrawn. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_InvalidateArea( TreeCtrl *tree, /* Widget info. */ int x1, int y1, /* Left & top of dirty area in window * coordinates. */ int x2, int y2 /* Right & bottom of dirty area in window * coordinates. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; if (x1 >= x2 || y1 >= y2) return; if ((y2 > Tree_HeaderTop(tree)) && (y1 < Tree_HeaderBottom(tree))) dInfo->flags |= DINFO_DRAW_HEADER; dItem = dInfo->dItem; while (dItem != NULL) { if ((!dInfo->empty && dInfo->rangeFirst != NULL) && !(dItem->area.flags & DITEM_ALL_DIRTY) && (x2 > dItem->area.x) && (x1 < dItem->area.x + dItem->area.width) && (y2 > dItem->y) && (y1 < dItem->y + dItem->height)) { InvalidateDItemX(dItem, &dItem->area, dItem->area.x, x1, x2 - x1); InvalidateDItemY(dItem, &dItem->area, dItem->y, y1, y2 - y1); dItem->area.flags |= DITEM_DIRTY; } if (!dInfo->emptyL && !(dItem->left.flags & DITEM_ALL_DIRTY) && (x2 > dInfo->boundsL[0]) && (x1 < dInfo->boundsL[2]) && (y2 > dItem->y) && (y1 < dItem->y + dItem->height)) { InvalidateDItemX(dItem, &dItem->left, dItem->left.x, x1, x2 - x1); InvalidateDItemY(dItem, &dItem->left, dItem->y, y1, y2 - y1); dItem->left.flags |= DITEM_DIRTY; } if (!dInfo->emptyR && !(dItem->right.flags & DITEM_ALL_DIRTY) && (x2 > dInfo->boundsR[0]) && (x1 < dInfo->boundsR[2]) && (y2 > dItem->y) && (y1 < dItem->y + dItem->height)) { InvalidateDItemX(dItem, &dItem->right, dItem->right.x, x1, x2 - x1); InvalidateDItemY(dItem, &dItem->right, dItem->y, y1, y2 - y1); dItem->right.flags |= DITEM_DIRTY; } dItem = dItem->next; } /* Could check border and highlight separately */ if (tree->inset > 0) { if ((x1 < Tree_BorderLeft(tree)) || (y1 < Tree_BorderTop(tree)) || (x2 > Tree_BorderRight(tree)) || (y2 > Tree_BorderBottom(tree))) { if (tree->highlightWidth > 0) dInfo->flags |= DINFO_DRAW_HIGHLIGHT; if (tree->borderWidth > 0) dInfo->flags |= DINFO_DRAW_BORDER; } } /* Invalidate part of the whitespace */ if ((x1 < x2 && y1 < y2) && TkRectInRegion(dInfo->wsRgn, x1, y1, x2 - x1, y2 - y1)) { XRectangle rect; TkRegion rgn = TkCreateRegion(); rect.x = x1; rect.y = y1; rect.width = x2 - x1; rect.height = y2 - y1; TkUnionRectWithRegion(&rect, rgn, rgn); TkSubtractRegion(dInfo->wsRgn, rgn, dInfo->wsRgn); TkDestroyRegion(rgn); } if (tree->debug.enable && tree->debug.display && tree->debug.eraseColor) { XFillRectangle(tree->display, Tk_WindowId(tree->tkwin), tree->debug.gcErase, x1, y1, x2 - x1, y2 - y1); DisplayDelay(tree); } } /* *-------------------------------------------------------------- * * Tree_InvalidateRegion -- * * Mark as dirty parts of any DItems in the given area. If the given * area overlaps the borders they are marked as needing to be * redrawn. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_InvalidateRegion( TreeCtrl *tree, /* Widget info. */ TkRegion region /* Region to mark as dirty, in window * coordinates. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; int minX, minY, maxX, maxY; XRectangle rect; int x1, x2, y1, y2; TkRegion rgn; TkClipBox(region, &rect); if (!rect.width || !rect.height) return; if (Tree_AreaBbox(tree, TREE_AREA_HEADER, &minX, &minY, &maxX, &maxY) && TkRectInRegion(region, minX, minY, maxX - minX, maxY - minY) != RectangleOut) dInfo->flags |= DINFO_DRAW_HEADER; rgn = TkCreateRegion(); dItem = dInfo->dItem; while (dItem != NULL) { if ((!dInfo->empty && dInfo->rangeFirst != NULL) && !(dItem->area.flags & DITEM_ALL_DIRTY)) { rect.x = dItem->area.x; rect.y = dItem->y; rect.width = dItem->area.width; rect.height = dItem->height; TkSubtractRegion(rgn, rgn, rgn); TkUnionRectWithRegion(&rect, rgn, rgn); TkIntersectRegion(region, rgn, rgn); TkClipBox(rgn, &rect); if (rect.width > 0 && rect.height > 0) { InvalidateDItemX(dItem, &dItem->area, dItem->area.x, rect.x, rect.width); InvalidateDItemY(dItem, &dItem->area, dItem->y, rect.y, rect.height); dItem->area.flags |= DITEM_DIRTY; } } if (!dInfo->emptyL && !(dItem->left.flags & DITEM_ALL_DIRTY)) { rect.x = dItem->left.x; rect.y = dItem->y; rect.width = dItem->left.width; rect.height = dItem->height; TkSubtractRegion(rgn, rgn, rgn); TkUnionRectWithRegion(&rect, rgn, rgn); TkIntersectRegion(region, rgn, rgn); TkClipBox(rgn, &rect); if (rect.width > 0 && rect.height > 0) { InvalidateDItemX(dItem, &dItem->left, dItem->left.x, rect.x, rect.width); InvalidateDItemY(dItem, &dItem->left, dItem->y, rect.y, rect.height); dItem->left.flags |= DITEM_DIRTY; } } if (!dInfo->emptyR && !(dItem->right.flags & DITEM_ALL_DIRTY)) { rect.x = dItem->right.x; rect.y = dItem->y; rect.width = dItem->right.width; rect.height = dItem->height; TkSubtractRegion(rgn, rgn, rgn); TkUnionRectWithRegion(&rect, rgn, rgn); TkIntersectRegion(region, rgn, rgn); TkClipBox(rgn, &rect); if (rect.width > 0 && rect.height > 0) { InvalidateDItemX(dItem, &dItem->right, dItem->right.x, rect.x, rect.width); InvalidateDItemY(dItem, &dItem->right, dItem->y, rect.y, rect.height); dItem->right.flags |= DITEM_DIRTY; } } dItem = dItem->next; } /* Could check border and highlight separately */ if (tree->inset > 0) { TkClipBox(region, &rect); x1 = rect.x, x2 = rect.x + rect.width; y1 = rect.y, y2 = rect.y + rect.height; if ((x1 < Tree_BorderLeft(tree)) || (y1 < Tree_BorderTop(tree)) || (x2 > Tree_BorderRight(tree)) || (y2 > Tree_BorderBottom(tree))) { if (tree->highlightWidth > 0) dInfo->flags |= DINFO_DRAW_HIGHLIGHT; if (tree->borderWidth > 0) dInfo->flags |= DINFO_DRAW_BORDER; } } /* Invalidate part of the whitespace */ TkSubtractRegion(dInfo->wsRgn, region, dInfo->wsRgn); TkDestroyRegion(rgn); if (tree->debug.enable && tree->debug.display && tree->debug.eraseColor) { Tk_FillRegion(tree->display, Tk_WindowId(tree->tkwin), tree->debug.gcErase, region); DisplayDelay(tree); } } /* *-------------------------------------------------------------- * * Tree_InvalidateItemArea -- * * Mark as dirty parts of any DItems in the given area. This is * like Tree_InvalidateArea() but the given area is clipped inside * the borders/header. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_InvalidateItemArea( TreeCtrl *tree, /* Widget info. */ int x1, int y1, /* Left & top of dirty area in window * coordinates. */ int x2, int y2 /* Right & bottom of dirty area in window * coordinates. */ ) { if (x1 < Tree_ContentLeft(tree)) x1 = Tree_ContentLeft(tree); if (y1 < Tree_ContentTop(tree)) y1 = Tree_ContentTop(tree); if (x2 > Tree_ContentRight(tree)) x2 = Tree_ContentRight(tree); if (y2 > Tree_ContentBottom(tree)) y2 = Tree_ContentBottom(tree); Tree_InvalidateArea(tree, x1, y1, x2, y2); } /* *-------------------------------------------------------------- * * Tree_RedrawArea -- * * Mark as dirty parts of any DItems in the given area. If the given * area overlaps the borders they are marked as needing to be * redrawn. The given area is subtracted from the whitespace region * so that that part of the whitespace region will be redrawn. * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_RedrawArea( TreeCtrl *tree, /* Widget info. */ int x1, int y1, /* Left & top of dirty area in window * coordinates. */ int x2, int y2 /* Right & bottom of dirty area in window * coordinates. */ ) { Tree_InvalidateArea(tree, x1, y1, x2, y2); Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * TreeDInfo_Init -- * * Perform display-related initialization when a new TreeCtrl is * created. * * Results: * None. * * Side effects: * Memory is allocated. * *-------------------------------------------------------------- */ void TreeDInfo_Init( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo; XGCValues gcValues; dInfo = (TreeDInfo) ckalloc(sizeof(TreeDInfo_)); memset(dInfo, '\0', sizeof(TreeDInfo_)); gcValues.graphics_exposures = True; dInfo->scrollGC = Tk_GetGC(tree->tkwin, GCGraphicsExposures, &gcValues); dInfo->flags = DINFO_OUT_OF_DATE; dInfo->columnsSize = 10; dInfo->columns = (ColumnInfo *) ckalloc(sizeof(ColumnInfo) * dInfo->columnsSize); dInfo->wsRgn = TkCreateRegion(); Tcl_InitHashTable(&dInfo->itemVisHash, TCL_ONE_WORD_KEYS); tree->dInfo = dInfo; } /* *-------------------------------------------------------------- * * TreeDInfo_Free -- * * Free display-related resources for a deleted TreeCtrl. * * Results: * None. * * Side effects: * Memory is allocated. * *-------------------------------------------------------------- */ void TreeDInfo_Free( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range = dInfo->rangeFirst; Tcl_HashEntry *hPtr; Tcl_HashSearch search; if (dInfo->rItem != NULL) ckfree((char *) dInfo->rItem); if (dInfo->rangeLock != NULL) ckfree((char *) dInfo->rangeLock); while (dInfo->dItem != NULL) { DItem *next = dInfo->dItem->next; WFREE(dInfo->dItem, DItem); dInfo->dItem = next; } while (dInfo->dItemFree != NULL) { DItem *next = dInfo->dItemFree->next; WFREE(dInfo->dItemFree, DItem); dInfo->dItemFree = next; } while (range != NULL) range = Range_Free(tree, range); Tk_FreeGC(tree->display, dInfo->scrollGC); if (dInfo->flags & DINFO_REDRAW_PENDING) Tcl_CancelIdleCall(Tree_Display, (ClientData) tree); if (dInfo->pixmap != None) Tk_FreePixmap(tree->display, dInfo->pixmap); if (dInfo->xScrollIncrements != NULL) ckfree((char *) dInfo->xScrollIncrements); if (dInfo->yScrollIncrements != NULL) ckfree((char *) dInfo->yScrollIncrements); TkDestroyRegion(dInfo->wsRgn); #ifdef DCOLUMN hPtr = Tcl_FirstHashEntry(&dInfo->itemVisHash, &search); while (hPtr != NULL) { ckfree((char *) Tcl_GetHashValue(hPtr)); hPtr = Tcl_NextHashEntry(&search); } #endif Tcl_DeleteHashTable(&dInfo->itemVisHash); ckfree((char *) dInfo->columns); WFREE(dInfo, TreeDInfo_); } void DumpDInfo( TreeCtrl *tree, /* Widget info. */ int index ) { Tcl_DString dString; TreeDInfo dInfo = tree->dInfo; DItem *dItem; Range *range; RItem *rItem; Tcl_DStringInit(&dString); if (index == 0) { DStringAppendf(&dString, "DumpDInfo: itemW,H %d,%d totalW,H %d,%d flags 0x%0x vertical %d itemVisCount %d\n", dInfo->itemWidth, dInfo->itemHeight, dInfo->totalWidth, dInfo->totalHeight, dInfo->flags, tree->vertical, tree->itemVisCount); DStringAppendf(&dString, " empty=%d bounds=%d,%d,%d,%d\n", dInfo->empty, dInfo->bounds[0], dInfo->bounds[1], dInfo->bounds[2], dInfo->bounds[3]); DStringAppendf(&dString, " emptyL=%d boundsL=%d,%d,%d,%d\n", dInfo->emptyL, dInfo->boundsL[0], dInfo->boundsL[1], dInfo->boundsL[2], dInfo->boundsL[3]); DStringAppendf(&dString, " emptyR=%d boundsR=%d,%d,%d,%d\n", dInfo->emptyR, dInfo->boundsR[0], dInfo->boundsR[1], dInfo->boundsR[2], dInfo->boundsR[3]); dItem = dInfo->dItem; while (dItem != NULL) { if (dItem->item == NULL) { DStringAppendf(&dString, " item NULL\n"); } else { DStringAppendf(&dString, " item %d x,y,w,h %d,%d,%d,%d dirty %d,%d,%d,%d flags %0X\n", TreeItem_GetID(tree, dItem->item), dItem->area.x, dItem->y, dItem->area.width, dItem->height, dItem->area.dirty[LEFT], dItem->area.dirty[TOP], dItem->area.dirty[RIGHT], dItem->area.dirty[BOTTOM], dItem->area.flags); DStringAppendf(&dString, " left: dirty %d,%d,%d,%d flags %0X\n", dItem->left.dirty[LEFT], dItem->left.dirty[TOP], dItem->left.dirty[RIGHT], dItem->left.dirty[BOTTOM], dItem->left.flags); DStringAppendf(&dString, " right: dirty %d,%d,%d,%d flags %0X\n", dItem->right.dirty[LEFT], dItem->right.dirty[TOP], dItem->right.dirty[RIGHT], dItem->right.dirty[BOTTOM], dItem->right.flags); } dItem = dItem->next; } } if (index == 1) { dItem = dInfo->dItem; while (dItem != NULL) { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&dInfo->itemVisHash, (char *) dItem->item); TreeColumn *value = (TreeColumn *) Tcl_GetHashValue(hPtr); DStringAppendf(&dString, "item %d:", TreeItem_GetID(tree, dItem->item)); while (*value != NULL) { DStringAppendf(&dString, " %d", TreeColumn_GetID(*value)); ++value; } DStringAppendf(&dString, "\n"); dItem = dItem->next; } } if (index == 2) { DStringAppendf(&dString, " dInfo.rangeFirstD %p dInfo.rangeLastD %p\n", dInfo->rangeFirstD, dInfo->rangeLastD); for (range = dInfo->rangeFirstD; range != NULL; range = range->next) { DStringAppendf(&dString, " Range: totalW,H %d,%d offset %d\n", range->totalWidth, range->totalHeight, range->offset); if (range == dInfo->rangeLastD) break; } DStringAppendf(&dString, " dInfo.rangeFirst %p dInfo.rangeLast %p\n", dInfo->rangeFirst, dInfo->rangeLast); for (range = dInfo->rangeFirst; range != NULL; range = range->next) { DStringAppendf(&dString, " Range: first %p last %p totalW,H %d,%d offset %d\n", range->first, range->last, range->totalWidth, range->totalHeight, range->offset); rItem = range->first; while (1) { DStringAppendf(&dString, " RItem: item %d index %d offset %d size %d\n", TreeItem_GetID(tree, rItem->item), rItem->index, rItem->offset, rItem->size); if (rItem == range->last) break; rItem++; } } } Tcl_DStringResult(tree->interp, &dString); } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeStyle.c0000644000175000017500000054750110674273024025137 0ustar domibeldomibel/* * tkTreeStyle.c -- * * This module implements styles for treectrl widgets. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: tkTreeStyle.c,v 1.2 2007-09-19 19:18:44 barre Exp $ */ #include "tkTreeCtrl.h" #include "tkTreeElem.h" /* This is the roundUp argument to AllocHax_CAlloc. */ #define ELEMENT_LINK_ROUND 1 /* Define this for performance gain and increased memory usage. */ /* When undefined, there is quite a performance hit when elements are * squeezable and a style has less than its needed width. The memory * savings are not too great when undefined. */ #define CACHE_STYLE_SIZE /* Define this for performance gain and increased memory usage. */ #define CACHE_ELEM_SIZE typedef struct MStyle MStyle; typedef struct IStyle IStyle; typedef struct MElementLink MElementLink; typedef struct IElementLink IElementLink; /* * A data structure of the following type is kept for each master style. * Master styles are created by the [style create] widget command. */ struct MStyle { MStyle *master; /* Always NULL. Needed to distinguish between * an MStyle and IStyle. */ Tk_Uid name; int numElements; MElementLink *elements; /* Array of master elements. */ int vertical; /* -orient */ }; /* * A data structure of the following type is kept for each instance style. * Instance styles are created when a style is assigned to an item-column. */ struct IStyle { MStyle *master; IElementLink *elements; /* Array of master or instance elements. */ int neededWidth; int neededHeight; #ifdef TREECTRL_DEBUG int neededState; #endif #ifdef CACHE_STYLE_SIZE int minWidth; int minHeight; int layoutWidth; int layoutHeight; #endif }; #define ELF_eEXPAND_W 0x0001 /* expand Layout.ePadX[0] */ #define ELF_eEXPAND_N 0x0002 #define ELF_eEXPAND_E 0x0004 #define ELF_eEXPAND_S 0x0008 #define ELF_iEXPAND_W 0x0010 /* expand Layout.iPadX[0] */ #define ELF_iEXPAND_N 0x0020 #define ELF_iEXPAND_E 0x0040 #define ELF_iEXPAND_S 0x0080 #define ELF_SQUEEZE_X 0x0100 /* shrink Layout.useWidth if needed */ #define ELF_SQUEEZE_Y 0x0200 #define ELF_DETACH 0x0400 #define ELF_INDENT 0x0800 /* don't layout under button&line area */ #define ELF_STICKY_W 0x1000 #define ELF_STICKY_N 0x2000 #define ELF_STICKY_E 0x4000 #define ELF_STICKY_S 0x8000 #define ELF_iEXPAND_X 0x00010000 /* expand Layout.useWidth */ #define ELF_iEXPAND_Y 0x00020000 #define ELF_eEXPAND_WE (ELF_eEXPAND_W | ELF_eEXPAND_E) #define ELF_eEXPAND_NS (ELF_eEXPAND_N | ELF_eEXPAND_S) #define ELF_eEXPAND (ELF_eEXPAND_WE | ELF_eEXPAND_NS) #define ELF_iEXPAND_WE (ELF_iEXPAND_W | ELF_iEXPAND_E) #define ELF_iEXPAND_NS (ELF_iEXPAND_N | ELF_iEXPAND_S) #define ELF_iEXPAND (ELF_iEXPAND_WE | ELF_iEXPAND_NS) #define ELF_EXPAND_WE (ELF_eEXPAND_WE | ELF_iEXPAND_WE) #define ELF_EXPAND_NS (ELF_eEXPAND_NS | ELF_iEXPAND_NS) #define ELF_EXPAND_W (ELF_eEXPAND_W | ELF_iEXPAND_W) #define ELF_EXPAND_N (ELF_eEXPAND_N | ELF_iEXPAND_N) #define ELF_EXPAND_E (ELF_eEXPAND_E | ELF_iEXPAND_E) #define ELF_EXPAND_S (ELF_eEXPAND_S | ELF_iEXPAND_S) #define ELF_STICKY (ELF_STICKY_W | ELF_STICKY_N | ELF_STICKY_E | ELF_STICKY_S) /* * An array of these is kept for each master style, one per element. * Most of the fields are set by the [style layout] widget command. */ struct MElementLink { Element *elem; /* Master element. */ int ePadX[2]; /* external horizontal padding */ int ePadY[2]; /* external vertical padding */ int iPadX[2]; /* internal horizontal padding */ int iPadY[2]; /* internal vertical padding */ int flags; /* ELF_xxx */ int *onion, onionCount; /* -union option info */ int minWidth, fixedWidth, maxWidth; int minHeight, fixedHeight, maxHeight; }; /* * An array of these is kept for each instance style, one per element. */ struct IElementLink { Element *elem; /* Master or instance element. */ #ifdef CACHE_ELEM_SIZE int neededWidth; int neededHeight; int layoutWidth; int layoutHeight; #endif }; static CONST84 char *MStyleUid = "MStyle", *IStyleUid = "IStyle", *MElementLinkUid = "MElementLink", *IElementLinkUid = "IElementLink"; static char *orientStringTable[] = { "horizontal", "vertical", (char *) NULL }; static Tk_OptionSpec styleOptionSpecs[] = { {TK_OPTION_STRING_TABLE, "-orient", (char *) NULL, (char *) NULL, "horizontal", -1, Tk_Offset(MStyle, vertical), 0, (ClientData) orientStringTable, 0}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; /* * The following structure is used to hold layout information about a * single element. This information is not cached anywhere. */ struct Layout { MElementLink *master; IElementLink *eLink; int useWidth; int useHeight; #ifndef CACHE_ELEM_SIZE int neededWidth; int neededHeight; #endif int x; /* left of ePad */ int y; /* above ePad */ int eWidth; /* ePad + iPad + useWidth + iPad + ePad */ int eHeight; /* ePad + iPad + useHeight + iPad + ePad */ int iWidth; /* iPad + useWidth + iPad */ int iHeight; /* iPad + useHeight + iPad */ int ePadX[2]; /* external horizontal padding */ int ePadY[2]; /* external vertical padding */ int iPadX[2]; /* internal horizontal padding */ int iPadY[2]; /* internal vertical padding */ int uPadX[2]; /* padding due to -union */ int uPadY[2]; /* padding due to -union */ int temp; }; /* *---------------------------------------------------------------------- * * Style_DoExpandH -- * * Add extra horizontal space to an element. The space is * distributed from right to left until all available space * is used or expansion is not possible. * * Results: * Layout.ePadX, Layout.iPadX, and Layout.useWidth may be * updated. The amount of available space that was used is * returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Style_DoExpandH( struct Layout *layout, /* Layout to be adjusted. */ int right /* Limit of expansion. */ ) { MElementLink *eLink1 = layout->master; int flags = eLink1->flags; int numExpand = 0, spaceRemaining, spaceUsed = 0; int *ePadX, *iPadX, *uPadX; if (!(flags & (ELF_EXPAND_WE | ELF_iEXPAND_X))) return 0; ePadX = layout->ePadX; iPadX = layout->iPadX; uPadX = layout->uPadX; spaceRemaining = right - (layout->x + ePadX[PAD_TOP_LEFT] + layout->iWidth + MAX(ePadX[PAD_BOTTOM_RIGHT], uPadX[PAD_BOTTOM_RIGHT])); if (spaceRemaining <= 0) return 0; if (layout->temp) numExpand = layout->temp; /* For -detach or vertical layout, just set layout->temp to zero */ else { if (flags & ELF_eEXPAND_W) numExpand++; if (flags & ELF_iEXPAND_W) numExpand++; if (flags & ELF_iEXPAND_X) { if ((eLink1->maxWidth < 0) || (eLink1->maxWidth > layout->useWidth)) numExpand++; } if (flags & ELF_iEXPAND_E) numExpand++; if (flags & ELF_eEXPAND_E) numExpand++; } while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? (spaceRemaining / numExpand) : 1; numExpand = 0; /* Allocate extra space to the *right* padding first so that any * extra single pixel is given to the right. */ if (flags & ELF_eEXPAND_E) { int add = each; ePadX[PAD_BOTTOM_RIGHT] += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_iEXPAND_E) { int add = each; iPadX[PAD_BOTTOM_RIGHT] += add; layout->iWidth += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_iEXPAND_X) { int max = eLink1->maxWidth; if ((max < 0) || (layout->useWidth < max)) { int add = (max < 0) ? each : MIN(each, max - layout->useWidth); layout->useWidth += add; layout->iWidth += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if ((max >= 0) && (max == layout->useWidth)) layout->temp--; if (!spaceRemaining) break; if ((max < 0) || (max > layout->useWidth)) numExpand++; } } if (flags & ELF_iEXPAND_W) { int add = each; iPadX[PAD_TOP_LEFT] += add; layout->iWidth += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_eEXPAND_W) { int add = each; ePadX[PAD_TOP_LEFT] += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } } return spaceUsed; } /* *---------------------------------------------------------------------- * * Style_DoExpandV -- * * Add extra vertical space to an element. The space is * distributed from bottom to top until all available space * is used or expansion is not possible. * * Results: * Layout.ePadY, Layout.iPadY, and Layout.useHeight may be * updated. The amount of available space that was used is * returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Style_DoExpandV( struct Layout *layout, /* Layout to be adjusted. */ int bottom /* Limit of expansion. */ ) { MElementLink *eLink1 = layout->master; int flags = eLink1->flags; int numExpand = 0, spaceRemaining, spaceUsed = 0; int *ePadY, *iPadY, *uPadY; if (!(flags & (ELF_EXPAND_NS | ELF_iEXPAND_Y))) return 0; ePadY = layout->ePadY; iPadY = layout->iPadY; uPadY = layout->uPadY; spaceRemaining = bottom - (layout->y + ePadY[PAD_TOP_LEFT] + layout->iHeight + MAX(ePadY[PAD_BOTTOM_RIGHT], uPadY[PAD_BOTTOM_RIGHT])); if (spaceRemaining <= 0) return 0; if (layout->temp) numExpand = layout->temp; /* For -detach or vertical layout, just set layout->temp to zero */ else { if (flags & ELF_eEXPAND_N) numExpand++; if (flags & ELF_iEXPAND_N) numExpand++; if (flags & ELF_iEXPAND_Y) { if ((eLink1->maxHeight < 0) || (eLink1->maxHeight > layout->useHeight)) numExpand++; } if (flags & ELF_iEXPAND_S) numExpand++; if (flags & ELF_eEXPAND_S) numExpand++; } while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? (spaceRemaining / numExpand) : 1; numExpand = 0; /* Allocate extra space to the *bottom* padding first so that any * extra single pixel is given to the bottom. */ if (flags & ELF_eEXPAND_S) { int add = each; ePadY[PAD_BOTTOM_RIGHT] += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_iEXPAND_S) { int add = each; iPadY[PAD_BOTTOM_RIGHT] += add; layout->iHeight += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_iEXPAND_Y) { int max = eLink1->maxHeight; if ((max < 0) || (layout->useHeight < max)) { int add = (max < 0) ? each : MIN(each, max - layout->useHeight); layout->useHeight += add; layout->iHeight += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if ((max >= 0) && (max == layout->useHeight)) layout->temp--; if (!spaceRemaining) break; if ((max < 0) || (max > layout->useHeight)) numExpand++; } } if (flags & ELF_iEXPAND_N) { int add = each; iPadY[PAD_TOP_LEFT] += add; layout->iHeight += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_eEXPAND_N) { int add = each; ePadY[PAD_TOP_LEFT] += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } } return spaceUsed; } /* *---------------------------------------------------------------------- * * ElementLink_NeededSize -- * * Calculate the needed width and height of an element. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Element_NeededSize( TreeCtrl *tree, /* Widget info. */ MElementLink *eLink1, /* Master style layout info. */ Element *elem, /* Master/Instance element. */ int state, /* STATE_xxx flags. */ int *widthPtr, /* Out: width */ int *heightPtr /* Out: height */ ) { ElementArgs args; int width, height; if ((eLink1->fixedWidth >= 0) && (eLink1->fixedHeight >= 0)) { width = eLink1->fixedWidth; height = eLink1->fixedHeight; } else { args.tree = tree; args.state = state; args.elem = elem; args.needed.fixedWidth = eLink1->fixedWidth; args.needed.fixedHeight = eLink1->fixedHeight; if (eLink1->maxWidth > eLink1->minWidth) args.needed.maxWidth = eLink1->maxWidth; else args.needed.maxWidth = -1; if (eLink1->maxHeight > eLink1->minHeight) args.needed.maxHeight = eLink1->maxHeight; else args.needed.maxHeight = -1; (*args.elem->typePtr->neededProc)(&args); width = args.needed.width; height = args.needed.height; if (eLink1->fixedWidth >= 0) width = eLink1->fixedWidth; else if ((eLink1->minWidth >= 0) && (width < eLink1->minWidth)) width = eLink1->minWidth; else if ((eLink1->maxWidth >= 0) && (width > eLink1->maxWidth)) width = eLink1->maxWidth; if (eLink1->fixedHeight >= 0) height = eLink1->fixedHeight; else if ((eLink1->minHeight >= 0) && (height < eLink1->minHeight)) height = eLink1->minHeight; else if ((eLink1->maxHeight >= 0) && (height > eLink1->maxHeight)) height = eLink1->maxHeight; } *widthPtr = width; *heightPtr = height; } /* *---------------------------------------------------------------------- * * Style_DoLayoutH -- * * Calculate the horizontal size and position of each element. * This gets called if the style -orient option is horizontal or * vertical. * * Results: * layouts[] is updated. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_DoLayoutH( StyleDrawArgs *drawArgs, /* Various args. */ struct Layout layouts[] /* Array of layout records to be * filled in, one per element. Should be * uninitialized. */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; MElementLink *eLinks1, *eLink1; IElementLink *eLinks2, *eLink2; int x = drawArgs->indent; int w, e; int *ePadX, *iPadX, *uPadX, *ePadY, *iPadY, *uPadY; int numExpandWE = 0; int numSqueezeX = 0; int i, j, eLinkCount = 0; int rightEdge = 0; eLinks1 = masterStyle->elements; eLinks2 = style->elements; eLinkCount = masterStyle->numElements; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; layout->eLink = eLink2; layout->master = eLink1; /* Width before squeezing/expanding */ if (eLink1->onion != NULL) layout->useWidth = 0; else { #ifdef CACHE_ELEM_SIZE layout->useWidth = eLink2->neededWidth; #else Element_NeededSize(drawArgs->tree, eLink1, eLink2->elem, drawArgs->state, &layout->neededWidth, &layout->neededHeight); layout->useWidth = layout->neededWidth; #endif } for (j = 0; j < 2; j++) { /* Pad values before expansion */ layout->ePadX[j] = eLink1->ePadX[j]; layout->ePadY[j] = eLink1->ePadY[j]; layout->iPadX[j] = eLink1->iPadX[j]; layout->iPadY[j] = eLink1->iPadY[j]; /* No -union padding yet */ layout->uPadX[j] = 0; layout->uPadY[j] = 0; } /* Count all non-union, non-detach squeezeable elements */ if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; if (eLink1->flags & ELF_SQUEEZE_X) numSqueezeX++; } /* Calculate the padding around elements surrounded by -union elements */ for (i = 0; i < eLinkCount; i++) { eLink1 = &eLinks1[i]; if (eLink1->onion == NULL) continue; ePadX = eLink1->ePadX; ePadY = eLink1->ePadY; iPadX = eLink1->iPadX; iPadY = eLink1->iPadY; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout = &layouts[eLink1->onion[j]]; uPadX = layout->uPadX; uPadY = layout->uPadY; if (masterStyle->vertical) { uPadX[PAD_TOP_LEFT] = MAX(uPadX[PAD_TOP_LEFT], iPadX[PAD_TOP_LEFT] + ePadX[PAD_TOP_LEFT]); uPadX[PAD_BOTTOM_RIGHT] = MAX(uPadX[PAD_BOTTOM_RIGHT], iPadX[PAD_BOTTOM_RIGHT] + ePadX[PAD_BOTTOM_RIGHT]); if (j == 0) /* topmost */ uPadY[PAD_TOP_LEFT] = MAX(uPadY[PAD_TOP_LEFT], iPadY[PAD_TOP_LEFT] + ePadY[PAD_TOP_LEFT]); if (j == eLink1->onionCount - 1) /* bottommost */ uPadY[PAD_BOTTOM_RIGHT] = MAX(uPadY[PAD_BOTTOM_RIGHT], iPadY[PAD_BOTTOM_RIGHT] + ePadY[PAD_BOTTOM_RIGHT]); } else { if (j == 0) /* leftmost */ uPadX[PAD_TOP_LEFT] = MAX(uPadX[PAD_TOP_LEFT], iPadX[PAD_TOP_LEFT] + ePadX[PAD_TOP_LEFT]); if (j == eLink1->onionCount - 1) /* rightmost */ uPadX[PAD_BOTTOM_RIGHT] = MAX(uPadX[PAD_BOTTOM_RIGHT], iPadX[PAD_BOTTOM_RIGHT] + ePadX[PAD_BOTTOM_RIGHT]); uPadY[PAD_TOP_LEFT] = MAX(uPadY[PAD_TOP_LEFT], iPadY[PAD_TOP_LEFT] + ePadY[PAD_TOP_LEFT]); uPadY[PAD_BOTTOM_RIGHT] = MAX(uPadY[PAD_BOTTOM_RIGHT], iPadY[PAD_BOTTOM_RIGHT] + ePadY[PAD_BOTTOM_RIGHT]); } } } /* Left-to-right layout. Make the width of some elements less than they * need */ if (!masterStyle->vertical && (drawArgs->width < style->neededWidth + drawArgs->indent) && (numSqueezeX > 0)) { int numSqueeze = numSqueezeX; int spaceRemaining = (style->neededWidth + drawArgs->indent) - drawArgs->width; while ((spaceRemaining > 0) && (numSqueeze > 0)) { int each = (spaceRemaining >= numSqueeze) ? (spaceRemaining / numSqueeze) : 1; numSqueeze = 0; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int min = 0; eLink1 = &eLinks1[i]; if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; if (!(eLink1->flags & ELF_SQUEEZE_X)) continue; if (eLink1->minWidth >= 0) min = eLink1->minWidth; if (layout->useWidth > min) { int sub = MIN(each, layout->useWidth - min); layout->useWidth -= sub; spaceRemaining -= sub; if (!spaceRemaining) break; if (layout->useWidth > min) numSqueeze++; } } } } /* Reduce the width of all non-union elements, except for the * cases handled above. */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int width, subtract; eLink1 = &eLinks1[i]; if (eLink1->onion != NULL) continue; if (!(eLink1->flags & ELF_SQUEEZE_X)) continue; if (!(eLink1->flags & ELF_DETACH) && !masterStyle->vertical) continue; ePadX = eLink1->ePadX; iPadX = eLink1->iPadX; uPadX = layout->uPadX; width = MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT]) + iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT] + MAX(ePadX[PAD_BOTTOM_RIGHT], uPadX[PAD_BOTTOM_RIGHT]); subtract = width - drawArgs->width; if (!(eLink1->flags & ELF_DETACH) || (eLink1->flags & ELF_INDENT)) subtract += drawArgs->indent; if (subtract > 0) { if ((eLink1->minWidth >= 0) && (eLink1->minWidth <= layout->useWidth) && (layout->useWidth - subtract < eLink1->minWidth)) layout->useWidth = eLink1->minWidth; else layout->useWidth -= subtract; } } /* Layout elements left-to-right */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int right; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; ePadX = eLink1->ePadX; iPadX = eLink1->iPadX; uPadX = layout->uPadX; if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; layout->x = x + abs(ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT])); layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; right = layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth + MAX(ePadX[PAD_BOTTOM_RIGHT], uPadX[PAD_BOTTOM_RIGHT]); if (masterStyle->vertical) rightEdge = MAX(rightEdge, right); else { rightEdge = right; x = layout->x + layout->eWidth; } /* Count number that want to expand */ if (eLink1->flags & (ELF_EXPAND_WE | ELF_iEXPAND_X)) numExpandWE++; } /* Left-to-right layout. Expand some elements horizontally if we have * more space available horizontally than is needed by the Style. */ if (!masterStyle->vertical && (drawArgs->width > rightEdge) && (numExpandWE > 0)) { int numExpand = 0; int spaceRemaining = drawArgs->width - rightEdge; /* Each element has 5 areas that can optionally expand. */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; layout->temp = 0; if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; if (eLink1->flags & ELF_eEXPAND_W) layout->temp++; if (eLink1->flags & ELF_iEXPAND_W) layout->temp++; if (eLink1->flags & ELF_iEXPAND_X) { if ((eLink1->maxWidth < 0) || (eLink1->maxWidth > layout->useWidth)) layout->temp++; } if (eLink1->flags & ELF_iEXPAND_E) layout->temp++; if (eLink1->flags & ELF_eEXPAND_E) layout->temp++; numExpand += layout->temp; } while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? spaceRemaining / numExpand : 1; numExpand = 0; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int spaceUsed; if (!layout->temp) continue; eLink1 = &eLinks1[i]; spaceUsed = Style_DoExpandH(layout, layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth + MAX(layout->ePadX[PAD_BOTTOM_RIGHT], layout->uPadX[PAD_BOTTOM_RIGHT]) + MIN(each * layout->temp, spaceRemaining)); if (spaceUsed) { /* Shift following elements to the right */ for (j = i + 1; j < eLinkCount; j++) if (!(eLinks1[j].flags & ELF_DETACH) && (eLinks1[j].onion == NULL)) layouts[j].x += spaceUsed; rightEdge += spaceUsed; spaceRemaining -= spaceUsed; if (!spaceRemaining) break; numExpand += layout->temp; } else layout->temp = 0; } } } /* Top-to-bottom layout. Expand some elements horizontally */ if (masterStyle->vertical && (numExpandWE > 0)) { for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int right; eLink1 = &eLinks1[i]; if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; layout->temp = 0; Style_DoExpandH(layout, drawArgs->width); right = layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth + MAX(layout->ePadX[PAD_BOTTOM_RIGHT], layout->uPadX[PAD_BOTTOM_RIGHT]); rightEdge = MAX(rightEdge, right); } } /* Now handle column justification */ /* All the non-union, non-detach elements are moved as a group */ if (drawArgs->width > rightEdge) { int dx = drawArgs->width - rightEdge; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; switch (drawArgs->justify) { case TK_JUSTIFY_LEFT: break; case TK_JUSTIFY_RIGHT: layout->x += dx; break; case TK_JUSTIFY_CENTER: layout->x += dx / 2; break; } } } /* Position and expand -detach elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (!(eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; ePadX = eLink1->ePadX; iPadX = eLink1->iPadX; uPadX = layout->uPadX; layout->x = abs(ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT])); if (eLink1->flags & ELF_INDENT) layout->x += drawArgs->indent; layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; layout->temp = 0; Style_DoExpandH(layout, drawArgs->width); } /* Now calculate layout of -union elements. */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (eLink1->onion == NULL) continue; ePadX = eLink1->ePadX; iPadX = eLink1->iPadX; w = 1000000, e = -1000000; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout2 = &layouts[eLink1->onion[j]]; w = MIN(w, layout2->x + layout2->ePadX[PAD_TOP_LEFT]); e = MAX(e, layout2->x + layout2->ePadX[PAD_TOP_LEFT] + layout2->iWidth); } layout->x = w - iPadX[PAD_TOP_LEFT] - ePadX[PAD_TOP_LEFT]; layout->useWidth = (e - w); layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; } /* Expand -union elements if needed: horizontal */ /* Expansion of "-union" elements is different than non-"-union" elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int extraWidth; eLink1 = &eLinks1[i]; if ((eLink1->onion == NULL) || !(eLink1->flags & ELF_EXPAND_WE)) continue; if (drawArgs->width - (layout->eWidth + drawArgs->indent) <= 0) continue; /* External and internal expansion: W */ extraWidth = layout->x - drawArgs->indent; if ((extraWidth > 0) && (eLink1->flags & ELF_EXPAND_W)) { if ((eLink1->flags & ELF_EXPAND_W) == ELF_EXPAND_W) { int eExtra = extraWidth / 2; int iExtra = extraWidth - extraWidth / 2; layout->x = drawArgs->indent; /* External expansion */ layout->ePadX[PAD_TOP_LEFT] += eExtra; layout->eWidth += extraWidth; /* Internal expansion */ layout->iPadX[PAD_TOP_LEFT] += iExtra; layout->iWidth += iExtra; } /* External expansion only: W */ else if (eLink1->flags & ELF_eEXPAND_W) { layout->ePadX[PAD_TOP_LEFT] += extraWidth; layout->x = drawArgs->indent; layout->eWidth += extraWidth; } /* Internal expansion only: W */ else { layout->iPadX[PAD_TOP_LEFT] += extraWidth; layout->x = drawArgs->indent; layout->iWidth += extraWidth; layout->eWidth += extraWidth; } } /* External and internal expansion: E */ extraWidth = drawArgs->width - (layout->x + layout->eWidth); if ((extraWidth > 0) && (eLink1->flags & ELF_EXPAND_E)) { if ((eLink1->flags & ELF_EXPAND_E) == ELF_EXPAND_E) { int eExtra = extraWidth / 2; int iExtra = extraWidth - extraWidth / 2; /* External expansion */ layout->ePadX[PAD_BOTTOM_RIGHT] += eExtra; layout->eWidth += extraWidth; /* all the space */ /* Internal expansion */ layout->iPadX[PAD_BOTTOM_RIGHT] += iExtra; layout->iWidth += iExtra; } /* External expansion only: E */ else if (eLink1->flags & ELF_eEXPAND_E) { layout->ePadX[PAD_BOTTOM_RIGHT] += extraWidth; layout->eWidth += extraWidth; } /* Internal expansion only: E */ else { layout->iPadX[PAD_BOTTOM_RIGHT] += extraWidth; layout->iWidth += extraWidth; layout->eWidth += extraWidth; } } } /* Add internal padding to display area for -union elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; if (eLink1->onion == NULL) continue; iPadX = layout->iPadX; layout->useWidth += iPadX[PAD_TOP_LEFT] + iPadX[PAD_BOTTOM_RIGHT]; iPadX[PAD_TOP_LEFT] = iPadX[PAD_BOTTOM_RIGHT] = 0; } } /* *---------------------------------------------------------------------- * * Style_DoLayoutV -- * * Calculate the vertical size and position of each element. * This gets called if the style -orient option is horizontal or * vertical. * * Results: * layouts[] is updated. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_DoLayoutV( StyleDrawArgs *drawArgs, /* Various args. */ struct Layout layouts[] /* Array of layout records to be filled * in, one per element. Should be * initialized by a call to Style_DoLayoutH(). */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; MElementLink *eLinks1, *eLink1; IElementLink *eLinks2, *eLink2; int y = 0; int n, s; int *ePadY, *iPadY, *uPadY; int numExpandNS = 0; int numSqueezeY = 0; int i, j, eLinkCount = 0; int bottomEdge = 0; eLinks1 = masterStyle->elements; eLinks2 = style->elements; eLinkCount = masterStyle->numElements; for (i = 0; i < eLinkCount; i++) { eLink1 = &eLinks1[i]; /* Count all non-union, non-detach squeezeable elements */ if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; if (eLink1->flags & ELF_SQUEEZE_Y) numSqueezeY++; } /* Top-top-bottom layout. Make the height of some elements less than they * need */ if (masterStyle->vertical && (drawArgs->height < style->neededHeight) && (numSqueezeY > 0)) { int numSqueeze = numSqueezeY; int spaceRemaining = style->neededHeight - drawArgs->height; while ((spaceRemaining > 0) && (numSqueeze > 0)) { int each = (spaceRemaining >= numSqueeze) ? (spaceRemaining / numSqueeze) : 1; numSqueeze = 0; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int min = 0; eLink1 = &eLinks1[i]; if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; if (!(eLink1->flags & ELF_SQUEEZE_Y)) continue; if (eLink1->minHeight >= 0) min = eLink1->minHeight; if (layout->useHeight > min) { int sub = MIN(each, layout->useHeight - min); layout->useHeight -= sub; spaceRemaining -= sub; if (!spaceRemaining) break; if (layout->useHeight > min) numSqueeze++; } } } } /* Reduce the height of all non-union elements, except for the * cases handled above. */ if (drawArgs->height < style->neededHeight) { for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int height, subtract; eLink1 = &eLinks1[i]; if (eLink1->onion != NULL) continue; if (!(eLink1->flags & ELF_SQUEEZE_Y)) continue; if (!(eLink1->flags & ELF_DETACH) && masterStyle->vertical) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; height = MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT]) + iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT] + MAX(ePadY[PAD_BOTTOM_RIGHT], uPadY[PAD_BOTTOM_RIGHT]); subtract = height - drawArgs->height; if (subtract > 0) { if ((eLink1->minHeight >= 0) && (eLink1->minHeight <= layout->useHeight) && (layout->useHeight - subtract < eLink1->minHeight)) layout->useHeight = eLink1->minHeight; else layout->useHeight -= subtract; } } } /* Layout elements top-to-bottom */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; layout->y = y + abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; if (masterStyle->vertical) y = layout->y + layout->eHeight; if (masterStyle->vertical) { bottomEdge = layout->y + layout->ePadY[PAD_TOP_LEFT] + layout->iHeight + MAX(ePadY[PAD_BOTTOM_RIGHT], uPadY[PAD_BOTTOM_RIGHT]); } /* Count number that want to expand */ if (eLink1->flags & (ELF_EXPAND_NS | ELF_iEXPAND_Y)) numExpandNS++; } /* Top-to-bottom layout. Expand some elements vertically if we have * more space available vertically than is needed by the Style. */ if (masterStyle->vertical && (drawArgs->height > bottomEdge) && (numExpandNS > 0)) { int numExpand = 0; int spaceRemaining = drawArgs->height - bottomEdge; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; layout->temp = 0; if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; if (eLink1->flags & ELF_eEXPAND_N) layout->temp++; if (eLink1->flags & ELF_iEXPAND_N) layout->temp++; if (eLink1->flags & ELF_iEXPAND_Y) { if ((eLink1->maxHeight < 0) || (eLink1->maxHeight > layout->useHeight)) layout->temp++; } if (eLink1->flags & ELF_iEXPAND_S) layout->temp++; if (eLink1->flags & ELF_eEXPAND_S) layout->temp++; numExpand += layout->temp; } while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? spaceRemaining / numExpand : 1; numExpand = 0; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int spaceUsed; if (!layout->temp) continue; eLink1 = &eLinks1[i]; spaceUsed = Style_DoExpandV(layout, layout->y + layout->ePadY[PAD_TOP_LEFT] + layout->iHeight + MAX(layout->ePadY[PAD_BOTTOM_RIGHT], layout->uPadY[PAD_BOTTOM_RIGHT]) + MIN(each * layout->temp, spaceRemaining)); if (spaceUsed) { /* Shift following elements down */ for (j = i + 1; j < eLinkCount; j++) if (!(eLinks1[j].flags & ELF_DETACH) && (eLinks1[j].onion == NULL)) layouts[j].y += spaceUsed; spaceRemaining -= spaceUsed; if (!spaceRemaining) break; numExpand += layout->temp; } else layout->temp = 0; } } } /* Left-to-right layout. Expand some elements vertically */ if (!masterStyle->vertical && (numExpandNS > 0)) { for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; if ((eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; layout->temp = 0; Style_DoExpandV(layout, drawArgs->height); } } /* Position and expand -detach elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (!(eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; layout->y = abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; layout->temp = 0; Style_DoExpandV(layout, drawArgs->height); } /* Now calculate layout of -union elements. */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (eLink1->onion == NULL) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; n = 1000000, s = -1000000; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout2 = &layouts[eLink1->onion[j]]; n = MIN(n, layout2->y + layout2->ePadY[PAD_TOP_LEFT]); s = MAX(s, layout2->y + layout2->ePadY[PAD_TOP_LEFT] + layout2->iHeight); } layout->y = n - iPadY[PAD_TOP_LEFT] - ePadY[PAD_TOP_LEFT]; layout->useHeight = (s - n); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; } /* Expand -union elements if needed: vertical */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int extraHeight; eLink1 = &eLinks1[i]; if ((eLink1->onion == NULL) || !(eLink1->flags & ELF_EXPAND_NS)) continue; if (drawArgs->height - layout->eHeight <= 0) continue; /* External and internal expansion: N */ extraHeight = layout->y; if ((extraHeight > 0) && (eLink1->flags & ELF_EXPAND_N)) { if ((eLink1->flags & ELF_EXPAND_N) == ELF_EXPAND_N) { int eExtra = extraHeight / 2; int iExtra = extraHeight - extraHeight / 2; /* External expansion */ layout->ePadY[PAD_TOP_LEFT] += eExtra; layout->y = 0; layout->eHeight += extraHeight; /* Internal expansion */ layout->iPadY[PAD_TOP_LEFT] += iExtra; layout->iHeight += iExtra; } /* External expansion only: N */ else if (eLink1->flags & ELF_eEXPAND_N) { layout->ePadY[PAD_TOP_LEFT] += extraHeight; layout->y = 0; layout->eHeight += extraHeight; } /* Internal expansion only: N */ else { layout->iPadY[PAD_TOP_LEFT] += extraHeight; layout->y = 0; layout->iHeight += extraHeight; layout->eHeight += extraHeight; } } /* External and internal expansion: S */ extraHeight = drawArgs->height - (layout->y + layout->eHeight); if ((extraHeight > 0) && (eLink1->flags & ELF_EXPAND_S)) { if ((eLink1->flags & ELF_EXPAND_S) == ELF_EXPAND_S) { int eExtra = extraHeight / 2; int iExtra = extraHeight - extraHeight / 2; /* External expansion */ layout->ePadY[PAD_BOTTOM_RIGHT] += eExtra; layout->eHeight += extraHeight; /* all the space */ /* Internal expansion */ layout->iPadY[PAD_BOTTOM_RIGHT] += iExtra; layout->iHeight += iExtra; } /* External expansion only: S */ else if (eLink1->flags & ELF_eEXPAND_S) { layout->ePadY[PAD_BOTTOM_RIGHT] += extraHeight; layout->eHeight += extraHeight; } /* Internal expansion only */ else { layout->iPadY[PAD_BOTTOM_RIGHT] += extraHeight; layout->iHeight += extraHeight; layout->eHeight += extraHeight; } } } /* Add internal padding to display area for -union elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; if (eLink1->onion == NULL) continue; iPadY = layout->iPadY; layout->useHeight += iPadY[PAD_TOP_LEFT] + iPadY[PAD_BOTTOM_RIGHT]; iPadY[PAD_TOP_LEFT] = iPadY[PAD_BOTTOM_RIGHT] = 0; } } /* *---------------------------------------------------------------------- * * Layout_Size -- * * Calculate the height and width of a style after all the * elements have been arranged. * * Results: * The height and width of the style. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Layout_Size( int vertical, /* TRUE if elements are arranged from top * to bottom. */ int numLayouts, /* Number of layout records. */ struct Layout layouts[], /* Initialized layout records. */ int *widthPtr, /* Returned width. */ int *heightPtr /* Returned height. */ ) { int i, W, N, E, S; int width = 0, height = 0; W = 1000000, N = 1000000, E = -1000000, S = -1000000; for (i = 0; i < numLayouts; i++) { struct Layout *layout = &layouts[i]; int w, n, e, s; int *ePadX, *iPadX, *uPadX, *ePadY, *iPadY, *uPadY; ePadX = layout->ePadX, iPadX = layout->iPadX, uPadX = layout->uPadX; ePadY = layout->ePadY, iPadY = layout->iPadY, uPadY = layout->uPadY; w = layout->x + ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT]); n = layout->y + ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT]); e = layout->x + layout->eWidth - ePadX[PAD_BOTTOM_RIGHT] + MAX(ePadX[PAD_BOTTOM_RIGHT], uPadX[PAD_BOTTOM_RIGHT]); s = layout->y + layout->eHeight - ePadY[PAD_BOTTOM_RIGHT] + MAX(ePadY[PAD_BOTTOM_RIGHT], uPadY[PAD_BOTTOM_RIGHT]); if (vertical) { N = MIN(N, n); S = MAX(S, s); width = MAX(width, e - w); } else { W = MIN(W, w); E = MAX(E, e); height = MAX(height, s - n); } } if (vertical) height = MAX(height, S - N); else width = MAX(width, E - W); (*widthPtr) = width; (*heightPtr) = height; } /* *---------------------------------------------------------------------- * * Style_DoLayoutNeededV -- * * Calculate the vertical size and position of each element. * This is similar to Style_DoLayoutV but without expansion or * squeezing. Also, the size and position of -union elements * is not calculated. * * Results: * layouts[] is updated. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_DoLayoutNeededV( StyleDrawArgs *drawArgs, /* Various args. */ struct Layout layouts[] /* Array of layout records to be filled * in, one per element. Should be * uninitialized. */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; MElementLink *eLinks1, *eLink1; IElementLink *eLinks2, *eLink2; int *ePadY, *iPadY, *uPadY; int i; int y = 0; eLinks1 = masterStyle->elements; eLinks2 = style->elements; /* Layout elements left-to-right, or top-to-bottom */ for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; /* The size of a -union element is determined by the elements * it surrounds */ if (eLink1->onion != NULL) { /* I don't need good values because I'm only calculating the * needed height */ layout->y = layout->iHeight = layout->eHeight = 0; continue; } /* -detach elements are positioned by themselves */ if (eLink1->flags & ELF_DETACH) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; layout->y = y + abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; if (masterStyle->vertical) y = layout->y + layout->eHeight; } /* -detach elements */ for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (!(eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; layout->y = abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; } } /* *---------------------------------------------------------------------- * * Style_DoLayout -- * * Calculate the size and position of each element. * * Results: * layouts[] is updated. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* Arrange all the Elements considering drawArgs.width and maybe drawArgs.height */ static void Style_DoLayout( StyleDrawArgs *drawArgs, /* Various args. */ struct Layout layouts[], /* Uninitialized records to be filled in. */ int neededV, /* TRUE if drawArgs.height should be ignored. */ char *file, /* debug */ int line /* debug */ ) { TreeCtrl *tree = drawArgs->tree; IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; int state = drawArgs->state; int i; if (style->neededWidth == -1) panic("Style_DoLayout(file %s line %d): style.neededWidth == -1", file, line); #ifdef CACHE_STYLE_STYLE if (style->minWidth + drawArgs->indent > drawArgs->width) panic("Style_DoLayout(file %s line %d): style.minWidth + drawArgs->indent %d > drawArgs.width %d", file, line, style->minWidth + drawArgs->indent, drawArgs->width); #endif Style_DoLayoutH(drawArgs, layouts); for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; MElementLink *eLink1 = layout->master; IElementLink *eLink2 = layout->eLink; ElementArgs args; /* The size of a -union element is determined by the elements * it surrounds */ if (eLink1->onion != NULL) { layout->useHeight = 0; continue; } #ifdef CACHE_ELEM_SIZE layout->useHeight = eLink2->neededHeight; #else layout->useHeight = layout->neededHeight; #endif /* If a Text Element is given less width than it needs (due to * -squeeze x layout), then it may wrap lines. This means * the height can vary depending on the width. */ if (eLink2->elem->typePtr->heightProc == NULL) continue; if (eLink1->fixedHeight >= 0) continue; #ifdef CACHE_ELEM_SIZE /* Not squeezed */ if (layout->useWidth >= eLink2->neededWidth) continue; /* Already calculated the height at this width */ if (layout->useWidth == eLink2->layoutWidth) { layout->useHeight = eLink2->layoutHeight; continue; } #if 0 /* */ if ((eLink2->layoutWidth == -1) && (layout->useWidth >= eLink2->neededWidth)) continue; #endif #else /* Not squeezed */ if (layout->useWidth >= layout->neededWidth) continue; #endif args.tree = tree; args.state = state; args.elem = eLink2->elem; args.height.fixedWidth = layout->useWidth; (*args.elem->typePtr->heightProc)(&args); if (eLink1->fixedHeight >= 0) layout->useHeight = eLink1->fixedHeight; else if ((eLink1->minHeight >= 0) && (args.height.height < eLink1->minHeight)) layout->useHeight = eLink1->minHeight; else if ((eLink1->maxHeight >= 0) && (args.height.height > eLink1->maxHeight)) layout->useHeight = eLink1->maxHeight; else layout->useHeight = args.height.height; #ifdef CACHE_ELEM_SIZE eLink2->layoutWidth = layout->useWidth; eLink2->layoutHeight = layout->useHeight; #endif } if (neededV) { Style_DoLayoutNeededV(drawArgs, layouts); } else { Style_DoLayoutV(drawArgs, layouts); } } /* *---------------------------------------------------------------------- * * Style_NeededSize -- * * Calculate the width and height of a style based only on * the requested size of each element. * * Results: * The width and height. The minimum width and height is equal to * the requested width and height minus any squeezing. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_NeededSize( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style to calculate size of. */ int state, /* STATE_xxx flags. */ int *widthPtr, /* Returned width. */ int *heightPtr, /* Returned height. */ int *minWidthPtr, /* Returned minimum width. */ int *minHeightPtr /* Returned minimum height. */ ) { MStyle *masterStyle = style->master; MElementLink *eLinks1, *eLink1; IElementLink *eLinks2, *eLink2; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; int *ePadX, *iPadX, *uPadX, *ePadY, *iPadY, *uPadY; int i, j; int x = 0, y = 0; int squeezeX = 0, squeezeY = 0; STATIC_ALLOC(layouts, struct Layout, masterStyle->numElements); eLinks1 = masterStyle->elements; eLinks2 = style->elements; for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; /* No -union padding yet */ layout->uPadX[PAD_TOP_LEFT] = 0; layout->uPadX[PAD_BOTTOM_RIGHT] = 0; layout->uPadY[PAD_TOP_LEFT] = 0; layout->uPadY[PAD_BOTTOM_RIGHT] = 0; } /* Figure out the padding around elements surrounded by -union elements */ for (i = 0; i < masterStyle->numElements; i++) { eLink1 = &eLinks1[i]; if (eLink1->onion == NULL) continue; ePadX = eLink1->ePadX; ePadY = eLink1->ePadY; iPadX = eLink1->iPadX; iPadY = eLink1->iPadY; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout = &layouts[eLink1->onion[j]]; uPadX = layout->uPadX; uPadY = layout->uPadY; if (masterStyle->vertical) { uPadX[PAD_TOP_LEFT] = MAX(uPadX[PAD_TOP_LEFT], iPadX[PAD_TOP_LEFT] + ePadX[PAD_TOP_LEFT]); uPadX[PAD_BOTTOM_RIGHT] = MAX(uPadX[PAD_BOTTOM_RIGHT], iPadX[PAD_BOTTOM_RIGHT] + ePadX[PAD_BOTTOM_RIGHT]); if (j == 0) /* topmost */ uPadY[PAD_TOP_LEFT] = MAX(uPadY[PAD_TOP_LEFT], iPadY[PAD_TOP_LEFT] + ePadY[PAD_TOP_LEFT]); if (j == eLink1->onionCount - 1) /* bottommost */ uPadY[PAD_BOTTOM_RIGHT] = MAX(uPadY[PAD_BOTTOM_RIGHT], iPadY[PAD_BOTTOM_RIGHT] + ePadY[PAD_BOTTOM_RIGHT]); } else { if (j == 0) /* leftmost */ uPadX[PAD_TOP_LEFT] = MAX(uPadX[PAD_TOP_LEFT], iPadX[PAD_TOP_LEFT] + ePadX[PAD_TOP_LEFT]); if (j == eLink1->onionCount - 1) /* rightmost */ uPadX[PAD_BOTTOM_RIGHT] = MAX(uPadX[PAD_BOTTOM_RIGHT], iPadX[PAD_BOTTOM_RIGHT] + ePadX[PAD_BOTTOM_RIGHT]); uPadY[PAD_TOP_LEFT] = MAX(uPadY[PAD_TOP_LEFT], iPadY[PAD_TOP_LEFT] + ePadY[PAD_TOP_LEFT]); uPadY[PAD_BOTTOM_RIGHT] = MAX(uPadY[PAD_BOTTOM_RIGHT], iPadY[PAD_BOTTOM_RIGHT] + ePadY[PAD_BOTTOM_RIGHT]); } } } /* Layout elements left-to-right, or top-to-bottom */ for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; ePadX = eLink1->ePadX; ePadY = eLink1->ePadY; iPadX = eLink1->iPadX; iPadY = eLink1->iPadY; uPadX = layout->uPadX; uPadY = layout->uPadY; /* The size of a -union element is determined by the elements * it surrounds */ if (eLink1->onion != NULL) { layout->x = layout->y = layout->eWidth = layout->eHeight = 0; layout->ePadX[PAD_TOP_LEFT] = 0; layout->ePadX[PAD_BOTTOM_RIGHT] = 0; layout->ePadY[PAD_TOP_LEFT] = 0; layout->ePadY[PAD_BOTTOM_RIGHT] = 0; layout->iPadX[PAD_TOP_LEFT] = 0; layout->iPadX[PAD_BOTTOM_RIGHT] = 0; layout->iPadY[PAD_TOP_LEFT] = 0; layout->iPadY[PAD_BOTTOM_RIGHT] = 0; continue; } #ifdef CACHE_ELEM_SIZE if ((eLink2->neededWidth == -1) || (eLink2->neededHeight == -1)) { Element_NeededSize(tree, eLink1, eLink2->elem, state, &eLink2->neededWidth, &eLink2->neededHeight); eLink2->layoutWidth = -1; } layout->useWidth = eLink2->neededWidth; layout->useHeight = eLink2->neededHeight; #else Element_NeededSize(tree, eLink1, eLink2->elem, state, &layout->useWidth, &layout->useHeight); #endif if (eLink1->flags & ELF_SQUEEZE_X) { if ((eLink1->minWidth >= 0) && (eLink1->minWidth <= layout->useWidth)) { squeezeX += layout->useWidth - eLink1->minWidth; } else { squeezeX += layout->useWidth; } } if (eLink1->flags & ELF_SQUEEZE_Y) { if ((eLink1->minHeight >= 0) && (eLink1->minHeight <= layout->useHeight)) { squeezeY += layout->useHeight - eLink1->minHeight; } else { squeezeY += layout->useHeight; } } /* -detach elements are positioned by themselves */ if (eLink1->flags & ELF_DETACH) continue; layout->eLink = eLink2; layout->x = x + abs(ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT])); layout->y = y + abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; for (j = 0; j < 2; j++) { layout->ePadX[j] = eLink1->ePadX[j]; layout->ePadY[j] = eLink1->ePadY[j]; layout->iPadX[j] = eLink1->iPadX[j]; layout->iPadY[j] = eLink1->iPadY[j]; } if (masterStyle->vertical) y = layout->y + layout->eHeight; else x = layout->x + layout->eWidth; } /* -detach elements */ for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (!(eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; ePadX = eLink1->ePadX; ePadY = eLink1->ePadY; iPadX = eLink1->iPadX; iPadY = eLink1->iPadY; uPadX = layout->uPadX; uPadY = layout->uPadY; layout->eLink = eLink2; layout->master = eLink1; layout->x = abs(ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT])); layout->y = abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; for (j = 0; j < 2; j++) { layout->ePadX[j] = eLink1->ePadX[j]; layout->ePadY[j] = eLink1->ePadY[j]; layout->iPadX[j] = eLink1->iPadX[j]; layout->iPadY[j] = eLink1->iPadY[j]; } } Layout_Size(masterStyle->vertical, masterStyle->numElements, layouts, widthPtr, heightPtr); *minWidthPtr = *widthPtr - squeezeX; *minHeightPtr = *heightPtr - squeezeY; STATIC_FREE(layouts, struct Layout, masterStyle->numElements); } /* *---------------------------------------------------------------------- * * Style_CheckNeededSize -- * * If the style's requested size is out-of-date then recalculate * Style.neededWidth, Style.neededHeight, Style.minWidth, and * Style.minHeight. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_CheckNeededSize( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style info. */ int state /* STATE_xxx flags. */ ) { if (style->neededWidth == -1) { int minWidth, minHeight; Style_NeededSize(tree, style, state, &style->neededWidth, &style->neededHeight, &minWidth, &minHeight); #ifdef CACHE_STYLE_SIZE style->minWidth = minWidth; style->minHeight = minHeight; style->layoutWidth = -1; #endif /* CACHE_STYLE_SIZE */ #ifdef TREECTRL_DEBUG style->neededState = state; #endif } #ifdef TREECTRL_DEBUG if (style->neededState != state) panic("Style_CheckNeededSize: neededState %d != state %d\n", style->neededState, state); #endif } #ifndef CACHE_STYLE_SIZE static void Style_MinSize( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style info. */ int state, /* STATE_xxx flags. */ int *minWidthPtr, int *minHeightPtr ) { int i, hasSqueeze = FALSE; for (i = 0; i < style->master->numElements; i++) { MElementLink *eLink1 = &style->master->elements[i]; if ((eLink1->onion == NULL) && (eLink1->flags & (ELF_SQUEEZE_X | ELF_SQUEEZE_Y))) { hasSqueeze = TRUE; break; } } if (hasSqueeze) { int width, height; Style_NeededSize(tree, style, state, &width, &height, minWidthPtr, minHeightPtr); } else { *minWidthPtr = style->neededWidth; *minHeightPtr = style->neededHeight; } } #endif /* !CACHE_STYLE_SIZE */ /* *---------------------------------------------------------------------- * * TreeStyle_NeededWidth -- * * Return the requested width of a style. * * Results: * The requested width. If the requested size is out-of-date * then it is recalculated. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_NeededWidth( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Style token. */ int state /* STATE_xxx flags. */ ) { IStyle *style = (IStyle *) style_; Style_CheckNeededSize(tree, style, state); return style->neededWidth; } /* *---------------------------------------------------------------------- * * TreeStyle_NeededHeight -- * * Return the requested height of a style. * * Results: * The requested height. If the requested size is out-of-date * then it is recalculated. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_NeededHeight( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Style token. */ int state /* STATE_xxx flags. */ ) { IStyle *style = (IStyle *) style_; Style_CheckNeededSize(tree, style, state); return style->neededHeight; } /* *---------------------------------------------------------------------- * * TreeStyle_UseHeight -- * * Return the height of a style for a given state and width. * * Results: * The height of the style. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* Calculate height of Style considering drawArgs.width */ int TreeStyle_UseHeight( StyleDrawArgs *drawArgs /* Various args. */ ) { TreeCtrl *tree = drawArgs->tree; IStyle *style = (IStyle *) drawArgs->style; int state = drawArgs->state; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; int width, height, minWidth; #ifndef CACHE_STYLE_SIZE int minHeight; #endif Style_CheckNeededSize(tree, style, state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; #else if (drawArgs->width < style->neededWidth + drawArgs->indent) Style_MinSize(tree, style, state, &minWidth, &minHeight); else minWidth = style->neededWidth; #endif /* * If we have: * a) infinite space available, or * b) more width than the style needs, or * c) less width than the style needs, but it has no -squeeze x elements * then return the needed height of the style. This is safe since no * text elements will be growing vertically when lines wrap. */ if ((drawArgs->width == -1) || (drawArgs->width >= style->neededWidth + drawArgs->indent) || (style->neededWidth == minWidth)) { return style->neededHeight; } /* We never lay out the style at less than the minimum width */ if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; #ifdef CACHE_STYLE_SIZE /* We have less space than the style needs, and have already calculated * the height of the style at this width. (The height may change because * of text elements wrapping lines). */ if (drawArgs->width == style->layoutWidth) return style->layoutHeight; #endif STATIC_ALLOC(layouts, struct Layout, style->master->numElements); Style_DoLayout(drawArgs, layouts, TRUE, __FILE__, __LINE__); Layout_Size(style->master->vertical, style->master->numElements, layouts, &width, &height); STATIC_FREE(layouts, struct Layout, style->master->numElements); #ifdef CACHE_STYLE_SIZE style->layoutWidth = drawArgs->width; style->layoutHeight = height; #endif return height; } /* *---------------------------------------------------------------------- * * TreeStyle_Draw -- * * Draw all the elements in a style. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeStyle_Draw( StyleDrawArgs *drawArgs /* Various args. */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; TreeCtrl *tree = drawArgs->tree; int *bounds = drawArgs->bounds; ElementArgs args; int i, x, y, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; #define DEBUG_DRAW 0 #if DEBUG_DRAW int debugDraw = FALSE; #endif Style_CheckNeededSize(tree, style, drawArgs->state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else if ((drawArgs->width < style->neededWidth + drawArgs->indent) || (drawArgs->height < style->neededHeight)) { Style_MinSize(tree, style, drawArgs->state, &minWidth, &minHeight); } else { minWidth = style->neededWidth; minHeight = style->neededHeight; } #endif /* Get the bounds allowed for drawing (in window coordinates), inside * the item-column(s) and inside the header/borders. */ x = drawArgs->x + tree->drawableXOrigin - tree->xOrigin; y = drawArgs->y + tree->drawableYOrigin - tree->yOrigin; args.display.bounds[0] = MAX(bounds[0], x); args.display.bounds[1] = MAX(bounds[1], y); args.display.bounds[2] = MIN(bounds[2], x + drawArgs->width); args.display.bounds[3] = MIN(bounds[3], y + drawArgs->height); /* We never lay out the style at less than the minimum size */ if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; STATIC_ALLOC(layouts, struct Layout, masterStyle->numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); args.tree = tree; args.state = drawArgs->state; args.display.drawable = drawArgs->drawable; for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; /* Don't "draw" window elements. TreeStyle_UpdateWindowPositions() * does that for us. */ if (ELEMENT_TYPE_MATCHES(layout->eLink->elem->typePtr, &elemTypeWindow)) continue; #if DEBUG_DRAW if (debugDraw && layout->master->onion != NULL) continue; #endif if ((layout->useWidth > 0) && (layout->useHeight > 0)) { args.elem = layout->eLink->elem; args.display.x = drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT]; args.display.y = drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT]; args.display.x += layout->iPadX[PAD_TOP_LEFT]; args.display.y += layout->iPadY[PAD_TOP_LEFT]; args.display.width = layout->useWidth; args.display.height = layout->useHeight; args.display.sticky = layout->master->flags & ELF_STICKY; #if DEBUG_DRAW if (debugDraw) { XColor *color[3]; GC gc[3]; if (layout->master->onion != NULL) { color[0] = Tk_GetColor(tree->interp, tree->tkwin, "blue2"); gc[0] = Tk_GCForColor(color[0], Tk_WindowId(tree->tkwin)); color[1] = Tk_GetColor(tree->interp, tree->tkwin, "blue3"); gc[1] = Tk_GCForColor(color[1], Tk_WindowId(tree->tkwin)); } else { color[0] = Tk_GetColor(tree->interp, tree->tkwin, "gray50"); gc[0] = Tk_GCForColor(color[0], Tk_WindowId(tree->tkwin)); color[1] = Tk_GetColor(tree->interp, tree->tkwin, "gray60"); gc[1] = Tk_GCForColor(color[1], Tk_WindowId(tree->tkwin)); color[2] = Tk_GetColor(tree->interp, tree->tkwin, "gray70"); gc[2] = Tk_GCForColor(color[2], Tk_WindowId(args.tree->tkwin)); } /* external */ XFillRectangle(tree->display, args.display.drawable, gc[2], args.display.x - layout->ePadX[PAD_TOP_LEFT], args.display.y - layout->ePadY[PAD_TOP_LEFT], layout->eWidth, layout->eHeight); /* internal */ XFillRectangle(tree->display, args.display.drawable, gc[1], args.display.x, args.display.y, args.display.width, args.display.height); /* needed */ if (!layout->master->onion && !(layout->master->flags & ELF_DETACH)) XFillRectangle(tree->display, args.display.drawable, gc[0], args.display.x + layout->iPadX[PAD_TOP_LEFT], args.display.y + layout->iPadY[PAD_TOP_LEFT], layout->eLink->neededWidth, layout->eLink->neededHeight); } else #endif /* DEBUG_DRAW */ (*args.elem->typePtr->displayProc)(&args); } } #if DEBUG_DRAW if (debugDraw) for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; if (layout->master->onion == NULL) continue; if (layout->useWidth > 0 && layout->useHeight > 0) { args.elem = layout->eLink->elem; args.display.x = drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT]; args.display.y = drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT]; args.display.width = layout->iWidth; args.display.height = layout->iHeight; { XColor *color[3]; GC gc[3]; color[0] = Tk_GetColor(tree->interp, tree->tkwin, "blue2"); gc[0] = Tk_GCForColor(color[0], Tk_WindowId(tree->tkwin)); color[1] = Tk_GetColor(tree->interp, tree->tkwin, "blue3"); gc[1] = Tk_GCForColor(color[1], Tk_WindowId(tree->tkwin)); /* external */ XDrawRectangle(tree->display, args.display.drawable, gc[0], args.display.x - layout->ePadX[PAD_TOP_LEFT], args.display.y - layout->ePadY[PAD_TOP_LEFT], layout->eWidth - 1, layout->eHeight - 1); /* internal */ XDrawRectangle(tree->display, args.display.drawable, gc[1], args.display.x, args.display.y, args.display.width - 1, args.display.height - 1); } } } #endif /* DEBUG_DRAW */ STATIC_FREE(layouts, struct Layout, masterStyle->numElements); } /* *---------------------------------------------------------------------- * * TreeStyle_UpdateWindowPositions -- * * Call the displayProc on each window element so it can update * its geometry. This is needed if an item was scrolled and its * displayProc wasn't otherwise called. * * Results: * None. * * Side effects: * Possible window geometry changes. * *---------------------------------------------------------------------- */ void TreeStyle_UpdateWindowPositions( StyleDrawArgs *drawArgs /* Various args. */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; TreeCtrl *tree = drawArgs->tree; int *bounds = drawArgs->bounds; ElementArgs args; int i, x, y, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; int numElements = masterStyle->numElements; /* FIXME: Perhaps remember whether this style has any window * elements */ for (i = 0; i < numElements; i++) { if (ELEMENT_TYPE_MATCHES(masterStyle->elements[i].elem->typePtr, &elemTypeWindow)) break; } if (i == numElements) return; Style_CheckNeededSize(tree, style, drawArgs->state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else if ((drawArgs->width < style->neededWidth + drawArgs->indent) || (drawArgs->height < style->neededHeight)) { Style_MinSize(tree, style, drawArgs->state, &minWidth, &minHeight); } else { minWidth = style->neededWidth; minHeight = style->neededHeight; } #endif /* Get the bounds allowed for drawing (in window coordinates), inside * the item-column(s) and inside the header/borders. */ x = drawArgs->x + tree->drawableXOrigin - tree->xOrigin; y = drawArgs->y + tree->drawableYOrigin - tree->yOrigin; args.display.bounds[0] = MAX(bounds[0], x); args.display.bounds[1] = MAX(bounds[1], y); args.display.bounds[2] = MIN(bounds[2], x + drawArgs->width); args.display.bounds[3] = MIN(bounds[3], y + drawArgs->height); /* We never lay out the style at less than the minimum size */ if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; STATIC_ALLOC(layouts, struct Layout, numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); args.tree = tree; args.state = drawArgs->state; args.display.drawable = drawArgs->drawable; for (i = 0; i < numElements; i++) { struct Layout *layout = &layouts[i]; if (!ELEMENT_TYPE_MATCHES(layout->eLink->elem->typePtr, &elemTypeWindow)) continue; if ((layout->useWidth > 0) && (layout->useHeight > 0)) { int requests; TreeDisplay_GetReadyForTrouble(tree, &requests); args.elem = layout->eLink->elem; args.display.x = drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT]; args.display.y = drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT]; args.display.x += layout->iPadX[PAD_TOP_LEFT]; args.display.y += layout->iPadY[PAD_TOP_LEFT]; args.display.width = layout->useWidth; args.display.height = layout->useHeight; args.display.sticky = layout->master->flags & ELF_STICKY; (*args.elem->typePtr->displayProc)(&args); /* Updating the position of a window may generate a * or event on that window. Binding scripts on those * events could do anything, including deleting items and * thus the style we are drawing. In other cases (such as when * using Tile widgets I notice), the Tk_GeomMgr.requestProc * may get called which calls Tree_ElementChangedItself which * calls FreeDItemInfo which frees a DItem we are in the middle * of displaying. So if anything was done that caused a display * request, then abort abort abort. */ if (TreeDisplay_WasThereTrouble(tree, requests)) break; } } STATIC_FREE(layouts, struct Layout, numElements); } /* *---------------------------------------------------------------------- * * TreeStyle_OnScreen -- * * Call the onScreenProc (if non-NULL) on each element so it can * update its visibility when an item's visibility changes. * * Results: * None. * * Side effects: * Possible window visibility changes. * *---------------------------------------------------------------------- */ void TreeStyle_OnScreen( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Style token. */ int onScreen /* Boolean indicating whether the item * using the style is on screen anymore. */ ) { IStyle *style = (IStyle *) style_; ElementArgs args; int i; args.tree = tree; args.screen.visible = onScreen; for (i = 0; i < style->master->numElements; i++) { IElementLink *eLink = &style->elements[i]; if (eLink->elem->typePtr->onScreenProc == NULL) continue; args.elem = eLink->elem; (*args.elem->typePtr->onScreenProc)(&args); } } /* *---------------------------------------------------------------------- * * Element_FreeResources -- * * Free memory etc associated with an Element. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void Element_FreeResources( TreeCtrl *tree, /* Widget info. */ Element *elem /* Record to free. */ ) { ElementType *typePtr = elem->typePtr; ElementArgs args; Tcl_HashEntry *hPtr; if (elem->master == NULL) { hPtr = Tcl_FindHashEntry(&tree->elementHash, elem->name); Tcl_DeleteHashEntry(hPtr); } args.tree = tree; args.elem = elem; (*typePtr->deleteProc)(&args); Tk_FreeConfigOptions((char *) elem, typePtr->optionTable, tree->tkwin); DynamicOption_Free(tree, elem->options, typePtr->optionSpecs); #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, typePtr->name, (char *) elem, typePtr->size); #else WFREE(elem, Element); #endif } /* *---------------------------------------------------------------------- * * MElementLink_Init -- * * Initialize (don't allocate) a MElementLink. * * Results: * eLink is filled with default values. * * Side effects: * None. * *---------------------------------------------------------------------- */ static MElementLink * MElementLink_Init( MElementLink *eLink, /* Existing record to initialize. */ Element *elem /* Existing element to point to. */ ) { memset(eLink, '\0', sizeof(MElementLink)); eLink->elem = elem; eLink->flags |= ELF_INDENT; eLink->minWidth = eLink->fixedWidth = eLink->maxWidth = -1; eLink->minHeight = eLink->fixedHeight = eLink->maxHeight = -1; eLink->flags |= ELF_STICKY; return eLink; } /* *---------------------------------------------------------------------- * * MElementLink_FreeResources -- * * Free memory etc associated with an MElementLink. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void MElementLink_FreeResources( TreeCtrl *tree, /* Widget info. */ MElementLink *eLink /* Record to free. */ ) { if (eLink->onion != NULL) WCFREE(eLink->onion, int, eLink->onionCount); } /* *---------------------------------------------------------------------- * * IElementLink_FreeResources -- * * Free memory etc associated with an ElementLink. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void IElementLink_FreeResources( TreeCtrl *tree, /* Widget info. */ IElementLink *eLink /* Record to free. */ ) { if (eLink->elem->master != NULL) Element_FreeResources(tree, eLink->elem); } /* *---------------------------------------------------------------------- * * MStyle_FreeResources -- * * Free memory etc associated with a Style. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void MStyle_FreeResources( TreeCtrl *tree, /* Widget info. */ MStyle *style /* Style to free. */ ) { Tcl_HashEntry *hPtr; int i; hPtr = Tcl_FindHashEntry(&tree->styleHash, style->name); Tcl_DeleteHashEntry(hPtr); if (style->numElements > 0) { for (i = 0; i < style->numElements; i++) MElementLink_FreeResources(tree, &style->elements[i]); #ifdef ALLOC_HAX AllocHax_CFree(tree->allocData, MElementLinkUid, (char *) style->elements, sizeof(MElementLink), style->numElements, ELEMENT_LINK_ROUND); #else WCFREE(style->elements, MElementLink, style->numElements); #endif } #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, MStyleUid, (char *) style, sizeof(MStyle)); #else WFREE(style, MStyle); #endif } /* *---------------------------------------------------------------------- * * IStyle_FreeResources -- * * Free memory etc associated with a Style. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void IStyle_FreeResources( TreeCtrl *tree, /* Widget info. */ IStyle *style /* Style to free. */ ) { MStyle *masterStyle = style->master; int i; if (masterStyle->numElements > 0) { for (i = 0; i < masterStyle->numElements; i++) IElementLink_FreeResources(tree, &style->elements[i]); #ifdef ALLOC_HAX AllocHax_CFree(tree->allocData, IElementLinkUid, (char *) style->elements, sizeof(IElementLink), masterStyle->numElements, ELEMENT_LINK_ROUND); #else WCFREE(style->elements, IElementLink, masterStyle->numElements); #endif } #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, IStyleUid, (char *) style, sizeof(IStyle)); #else WFREE(style, IStyle); #endif } /* *---------------------------------------------------------------------- * * TreeStyle_FreeResources -- * * Free memory etc associated with a Style. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeStyle_FreeResources( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Token of style to free. */ ) { MStyle *masterStyle = (MStyle *) style_; IStyle *style = (IStyle *) style_; if (style->master == NULL) MStyle_FreeResources(tree, masterStyle); else IStyle_FreeResources(tree, style); } /* *---------------------------------------------------------------------- * * MStyle_FindElem -- * * Find an ElementLink in a style. * * Results: * If found, a pointer to the ElementLink and index in the * style's array of ElementLinks is returned; otherwise NULL * is returned. * * Side effects: * World peace. * *---------------------------------------------------------------------- */ static MElementLink * MStyle_FindElem( TreeCtrl *tree, /* Widget info. */ MStyle *style, /* Style to search. */ Element *master, /* Master element to find. */ int *index /* Returned index, may be NULL. */ ) { int i; for (i = 0; i < style->numElements; i++) { MElementLink *eLink = &style->elements[i]; if (eLink->elem->name == master->name) { if (index != NULL) (*index) = i; return eLink; } } return NULL; } /* *---------------------------------------------------------------------- * * IStyle_FindElem -- * * Find an ElementLink in a style. * * Results: * If found, a pointer to the ElementLink and index in the * style's array of ElementLinks is returned; otherwise NULL * is returned. * * Side effects: * World peace. * *---------------------------------------------------------------------- */ static IElementLink * IStyle_FindElem( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style to search. */ Element *master, /* Master element to find. */ int *index /* Returned index, may be NULL. */ ) { MStyle *masterStyle = style->master; int i; for (i = 0; i < masterStyle->numElements; i++) { IElementLink *eLink = &style->elements[i]; if (eLink->elem->name == master->name) { if (index != NULL) (*index) = i; return eLink; } } return NULL; } /* *---------------------------------------------------------------------- * * TreeStyle_FindElement -- * * Find an ElementLink in a style. * * Results: * If found, the index in the style's array of ElementLinks is * returned with TCL_OK. Otherwise TCL_ERROR is returned and an * error message is placed in the interpreter result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_FindElement( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Token of style to search. */ TreeElement elem_, /* Master element to find. */ int *index /* Returned index, may be NULL. */ ) { MStyle *masterStyle = (MStyle *) style_; IStyle *style = (IStyle *) style_; Element *elem = (Element *) elem_; if (((style->master == NULL) && (MStyle_FindElem(tree, masterStyle, elem, index) == NULL)) || ((style->master != NULL) && (IStyle_FindElem(tree, style, elem, index) == NULL))) { FormatResult(tree->interp, "style %s does not use element %s", style->master ? style->master->name : masterStyle->name, elem->name); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Element_CreateAndConfig -- * * Allocate and initialize a new Element (master or instance). * * Results: * An Element is allocated, its createProc is called, default * configuration options are set, then the configProc and changeProc * are called to handle any given configurations options. If an * error occurs NULL is returned. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static Element * Element_CreateAndConfig( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. Should * be NULL for a master element. */ TreeItemColumn column, /* Item-column containing the element. * Should be NULL for a master element. */ Element *masterElem, /* Master element if creating an instance. */ ElementType *type, /* Element type. Should be NULL when * creating an instance. */ CONST char *name, /* Name of master element, NULL for an * instance. */ int objc, /* Array of intialial configuration. */ Tcl_Obj *CONST objv[] /* options. */ ) { Element *elem; ElementArgs args; if (masterElem != NULL) { type = masterElem->typePtr; name = masterElem->name; } #ifdef ALLOC_HAX elem = (Element *) AllocHax_Alloc(tree->allocData, type->name, type->size); #else elem = (Element *) ckalloc(type->size); #endif memset(elem, '\0', type->size); elem->name = Tk_GetUid(name); elem->typePtr = type; elem->master = masterElem; args.tree = tree; args.elem = elem; args.create.item = item; args.create.column = column; if ((*type->createProc)(&args) != TCL_OK) { #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, type->name, (char *) elem, type->size); #else WFREE(elem, Element); #endif return NULL; } if (Tk_InitOptions(tree->interp, (char *) elem, type->optionTable, tree->tkwin) != TCL_OK) { #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, type->name, (char *) elem, type->size); #else WFREE(elem, Element); #endif return NULL; } args.config.objc = objc; args.config.objv = objv; args.config.flagSelf = 0; args.config.item = item; args.config.column = column; if ((*type->configProc)(&args) != TCL_OK) { (*type->deleteProc)(&args); Tk_FreeConfigOptions((char *) elem, type->optionTable, tree->tkwin); DynamicOption_Free(tree, elem->options, type->optionSpecs); #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, type->name, (char *) elem, type->size); #else WFREE(elem, Element); #endif return NULL; } args.change.flagSelf = args.config.flagSelf; args.change.flagTree = 0; args.change.flagMaster = 0; (*type->changeProc)(&args); return elem; } /* *---------------------------------------------------------------------- * * Style_CreateElem -- * * Allocate and initialize a new instance Element in a IStyle * (if it doesn't already exist) and return its associated * IElementLink. * * Results: * If the style already has a matching instance element, then a * pointer to an existing IElementLink is returned. * If the style does not already have a matching instance element, * then a new one is created and a pointer to an existing * IElementLink is returned. * If an error occurs creating the new element the result is * NULL. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static IElementLink * Style_CreateElem( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ TreeItemColumn column, /* Item-column containing the element. */ IStyle *style, /* Style to search/add the element to. */ Element *masterElem, /* Element to find or create and instance of. */ int *isNew) /* If non-NULL, set to TRUE if a new instance * element was created. */ { MStyle *masterStyle = style->master; IElementLink *eLink = NULL; Element *elem; int i; if (masterElem->master != NULL) panic("Style_CreateElem called with instance Element"); if (isNew != NULL) (*isNew) = FALSE; for (i = 0; i < masterStyle->numElements; i++) { eLink = &style->elements[i]; if (eLink->elem == masterElem) { /* Allocate instance Element here */ break; } /* Instance Style already has instance Element */ if (eLink->elem->name == masterElem->name) return eLink; } /* Error: Element isn't in the master Style */ if (i == masterStyle->numElements) return NULL; elem = Element_CreateAndConfig(tree, item, column, masterElem, NULL, NULL, 0, NULL); if (elem == NULL) return NULL; eLink->elem = elem; if (isNew != NULL) (*isNew) = TRUE; return eLink; } /* *---------------------------------------------------------------------- * * TreeStyle_NewInstance -- * * Create and initialize a new instance of a master style. * * Results: * A new instance Style. The new array of ElementLinks is * initialized to contain pointers to master elements; instance * elements are created the first time they are configured. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ TreeStyle TreeStyle_NewInstance( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Master style to create instance of. */ ) { MStyle *style = (MStyle *) style_; IStyle *copy; IElementLink *eLink; int i; #ifdef ALLOC_HAX copy = (IStyle *) AllocHax_Alloc(tree->allocData, IStyleUid, sizeof(IStyle)); #else copy = (IStyle *) ckalloc(sizeof(IStyle)); #endif memset(copy, '\0', sizeof(IStyle)); copy->master = style; copy->neededWidth = -1; copy->neededHeight = -1; if (style->numElements > 0) { #ifdef ALLOC_HAX copy->elements = (IElementLink *) AllocHax_CAlloc(tree->allocData, IElementLinkUid, sizeof(IElementLink), style->numElements, ELEMENT_LINK_ROUND); #else copy->elements = (IElementLink *) ckalloc(sizeof(IElementLink) * style->numElements); #endif memset(copy->elements, '\0', sizeof(IElementLink) * style->numElements); for (i = 0; i < style->numElements; i++) { eLink = ©->elements[i]; eLink->elem = style->elements[i].elem; #ifdef CACHE_ELEM_SIZE eLink->neededWidth = -1; eLink->neededHeight = -1; #endif } } return (TreeStyle) copy; } /* *---------------------------------------------------------------------- * * Element_FromObj -- * * Convert a Tcl_Obj to a master element. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Element_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* Object to convert from. */ Element **elemPtr /* Returned record. */ ) { char *name; Tcl_HashEntry *hPtr; name = Tcl_GetString(obj); hPtr = Tcl_FindHashEntry(&tree->elementHash, name); if (hPtr == NULL) { Tcl_AppendResult(tree->interp, "element \"", name, "\" doesn't exist", NULL); return TCL_ERROR; } (*elemPtr) = (Element *) Tcl_GetHashValue(hPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeElement_FromObj -- * * Convert a Tcl_Obj to a master element. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeElement_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* Object to convert from. */ TreeElement *elemPtr /* Returned master element token. */ ) { return Element_FromObj(tree, obj, (Element **) elemPtr); } /* *---------------------------------------------------------------------- * * TreeElement_IsType -- * * Determine if an element is of a certain type. * * Results: * TRUE if the type matches, otherwise FALSE. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeElement_IsType( TreeCtrl *tree, /* Widget info. */ TreeElement elem_, /* Element to check. */ CONST char *type /* NULL-terminated element type name. */ ) { return strcmp(((Element *) elem_)->typePtr->name, type) == 0; } /* *---------------------------------------------------------------------- * * TreeStyle_FromObj -- * * Convert a Tcl_Obj to a master style. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* Object to convert from. */ TreeStyle *stylePtr) /* Returned master style token. */ { char *name; Tcl_HashEntry *hPtr; name = Tcl_GetString(obj); hPtr = Tcl_FindHashEntry(&tree->styleHash, name); if (hPtr == NULL) { Tcl_AppendResult(tree->interp, "style \"", name, "\" doesn't exist", NULL); return TCL_ERROR; } (*stylePtr) = (TreeStyle) Tcl_GetHashValue(hPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Element_ToObj -- * * Create a new Tcl_Obj representing an element. * * Results: * A Tcl_Obj. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static Tcl_Obj * Element_ToObj( Element *elem /* Element to create Tcl_Obj from. */ ) { return Tcl_NewStringObj(elem->name, -1); } /* *---------------------------------------------------------------------- * * TreeStyle_ToObj -- * * Create a new Tcl_Obj representing a style. * * Results: * A Tcl_Obj. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeStyle_ToObj( TreeStyle style_ /* Style token to create Tcl_Obj from. */ ) { MStyle *masterStyle = (MStyle *) style_; IStyle *style = (IStyle *) style_; if (style->master != NULL) masterStyle = style->master; return Tcl_NewStringObj(masterStyle->name, -1); } /* *---------------------------------------------------------------------- * * Style_Changed -- * * Called when a master style is configured or the layout of one * of its elements changes. * * Results: * For each item-column using an instance of the given master * style, size and display info is marked out-of-date. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Style_Changed( TreeCtrl *tree, /* Widget info. */ MStyle *masterStyle /* Style that changed. */ ) { TreeItem item; TreeItemColumn column; TreeColumn treeColumn; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int columnIndex, layout; int updateDInfo = FALSE; IStyle *style; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); treeColumn = tree->columns; column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; layout = FALSE; while (column != NULL) { style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if ((style != NULL) && (style->master == masterStyle)) { #ifdef CACHE_ELEM_SIZE int i; for (i = 0; i < masterStyle->numElements; i++) { IElementLink *eLink = &style->elements[i]; /* This is needed if the -width/-height layout options change */ eLink->neededWidth = eLink->neededHeight = -1; } #endif style->neededWidth = style->neededHeight = -1; Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_InvalidateSize(tree, column); layout = TRUE; } columnIndex++; column = TreeItemColumn_GetNext(tree, column); treeColumn = TreeColumn_Next(treeColumn); } if (layout) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); updateDInfo = TRUE; } hPtr = Tcl_NextHashEntry(&search); } if (updateDInfo) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } /* *---------------------------------------------------------------------- * * MStyle_ChangeElementsAux -- * * Update the list of elements used by a style. Elements * may be inserted or deleted. * * Results: * The list of elements in the style is updated. * * Side effects: * Memory may be allocated/deallocated. * *---------------------------------------------------------------------- */ static void MStyle_ChangeElementsAux( TreeCtrl *tree, /* Widget info. */ MStyle *style, /* Master style to be updated. */ int count, /* The number of elements in the style after * this routine finishes. */ Element **elemList, /* List of master elements the style uses. */ int *map /* Array of indexes into the list of elements * currently used by the style. */ ) { MElementLink *eLink, *eLinks = NULL; int i, staticKeep[STATIC_SIZE], *keep = staticKeep; STATIC_ALLOC(keep, int, style->numElements); if (count > 0) { #ifdef ALLOC_HAX eLinks = (MElementLink *) AllocHax_CAlloc(tree->allocData, MElementLinkUid, sizeof(MElementLink), count, ELEMENT_LINK_ROUND); #else eLinks = (MElementLink *) ckalloc(sizeof(MElementLink) * count); #endif } /* Assume we are discarding all the old ElementLinks */ for (i = 0; i < style->numElements; i++) keep[i] = 0; for (i = 0; i < count; i++) { if (map[i] != -1) { eLinks[i] = style->elements[map[i]]; keep[map[i]] = 1; } else { eLink = MElementLink_Init(&eLinks[i], elemList[i]); } } if (style->numElements > 0) { /* Free unused ElementLinks */ for (i = 0; i < style->numElements; i++) { if (!keep[i]) { MElementLink_FreeResources(tree, &style->elements[i]); } } #ifdef ALLOC_HAX AllocHax_CFree(tree->allocData, MElementLinkUid, (char *) style->elements, sizeof(MElementLink), style->numElements, ELEMENT_LINK_ROUND); #else WCFREE(style->elements, MElementLink, style->numElements); #endif } STATIC_FREE(keep, int, style->numElements); style->elements = eLinks; style->numElements = count; } /* *---------------------------------------------------------------------- * * IStyle_ChangeElementsAux -- * * Update the list of elements used by a style. Elements * may be inserted or deleted. * * Results: * The list of elements in the style is updated. * * Side effects: * Memory may be allocated/deallocated. * *---------------------------------------------------------------------- */ static void IStyle_ChangeElementsAux( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Instance style to be updated. */ int oldCount, /* The previous number of elements. */ int count, /* The number of elements in the style after * this routine finishes. */ Element **elemList, /* List of master elements the style uses. */ int *map /* Array of indexes into the list of elements * currently used by the style. */ ) { IElementLink *eLink, *eLinks = NULL; int i, staticKeep[STATIC_SIZE], *keep = staticKeep; STATIC_ALLOC(keep, int, oldCount); if (count > 0) { #ifdef ALLOC_HAX eLinks = (IElementLink *) AllocHax_CAlloc(tree->allocData, IElementLinkUid, sizeof(IElementLink), count, ELEMENT_LINK_ROUND); #else eLinks = (IElementLink *) ckalloc(sizeof(IElementLink) * count); #endif } /* Assume we are discarding all the old ElementLinks */ for (i = 0; i < oldCount; i++) keep[i] = 0; for (i = 0; i < count; i++) { if (map[i] != -1) { eLinks[i] = style->elements[map[i]]; keep[map[i]] = 1; } else { eLink = &eLinks[i]; eLink->elem = elemList[i]; #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif } } if (oldCount > 0) { /* Free unused ElementLinks */ for (i = 0; i < oldCount; i++) { if (!keep[i]) { IElementLink_FreeResources(tree, &style->elements[i]); } } #ifdef ALLOC_HAX AllocHax_CFree(tree->allocData, IElementLinkUid, (char *) style->elements, sizeof(IElementLink), oldCount, ELEMENT_LINK_ROUND); #else WCFREE(style->elements, IElementLink, oldCount); #endif } STATIC_FREE(keep, int, oldCount); style->elements = eLinks; } /* *---------------------------------------------------------------------- * * Style_ChangeElements -- * * Update the list of elements used by a style. Elements * may be inserted or deleted. * * Results: * The list of elements in the master style is updated. For * each item-column using an instance of the master style, * the list of elements is updated. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Style_ChangeElements( TreeCtrl *tree, /* Widget info. */ MStyle *masterStyle, /* Master style to be updated. */ int count, /* The number of elements in the style after * this routine finishes. */ Element **elemList, /* List of master elements the style uses. */ int *map /* Array of indexes into the list of elements * currently used by the style. */ ) { TreeItem item; TreeItemColumn column; TreeColumn treeColumn; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int columnIndex, layout; int updateDInfo = FALSE; IStyle *style; int i, j, k, oldCount; /* Update -union lists */ for (i = 0; i < masterStyle->numElements; i++) { MElementLink *eLink = &masterStyle->elements[i]; int staticKeep[STATIC_SIZE], *keep = staticKeep; int onionCnt = 0, *onion = NULL; if (eLink->onion == NULL) continue; STATIC_ALLOC(keep, int, eLink->onionCount); /* Check every Element in this -union */ for (j = 0; j < eLink->onionCount; j++) { MElementLink *eLink2 = &masterStyle->elements[eLink->onion[j]]; /* Check the new list of Elements */ keep[j] = -1; for (k = 0; k < count; k++) { /* This new Element is in the -union */ if (elemList[k] == eLink2->elem) { keep[j] = k; onionCnt++; break; } } } if (onionCnt > 0) { if (onionCnt != eLink->onionCount) onion = (int *) ckalloc(sizeof(int) * onionCnt); else onion = eLink->onion; k = 0; for (j = 0; j < eLink->onionCount; j++) { if (keep[j] != -1) onion[k++] = keep[j]; } } STATIC_FREE(keep, int, eLink->onionCount); if (onionCnt != eLink->onionCount) { WCFREE(eLink->onion, int, eLink->onionCount); eLink->onion = onion; eLink->onionCount = onionCnt; } } oldCount = masterStyle->numElements; MStyle_ChangeElementsAux(tree, masterStyle, count, elemList, map); hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); treeColumn = tree->columns; column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; layout = FALSE; while (column != NULL) { style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if ((style != NULL) && (style->master == masterStyle)) { IStyle_ChangeElementsAux(tree, style, oldCount, count, elemList, map); style->neededWidth = style->neededHeight = -1; Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_InvalidateSize(tree, column); layout = TRUE; } columnIndex++; column = TreeItemColumn_GetNext(tree, column); treeColumn = TreeColumn_Next(treeColumn); } if (layout) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); updateDInfo = TRUE; } hPtr = Tcl_NextHashEntry(&search); } if (updateDInfo) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } /* *---------------------------------------------------------------------- * * Style_ElemChanged -- * * Called when a master element or TreeCtrl is configured. * * Results: * A check is made on each item-column to see if it is using * the element. The size of any element/column/item affected * is marked out-of-date. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Style_ElemChanged( TreeCtrl *tree, /* Widget info. */ MStyle *masterStyle, /* Master style that uses the element. */ Element *masterElem, /* Master element affected by the change. */ int masterElemIndex, /* Index of masterElem in masterStyle. */ int flagM, /* Flags returned by ElementType.configProc() * if the master element was configured, * zero if the TreeCtrl was configured. */ int flagT, /* TREE_CONF_xxx flags if the TreeCtrl was * configured, zero if the master element * was configured. */ int csM /* CS_xxx flags returned by * ElementType.changeProc(). */ ) { TreeItem item; TreeItemColumn column; TreeColumn treeColumn; Tcl_HashEntry *hPtr; Tcl_HashSearch search; IElementLink *eLink; int columnIndex; ElementArgs args; IStyle *style; int eMask, cMask, iMask; int updateDInfo = FALSE; args.tree = tree; args.change.flagTree = flagT; args.change.flagMaster = flagM; args.change.flagSelf = 0; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); treeColumn = tree->columns; column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; iMask = 0; while (column != NULL) { cMask = 0; style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if ((style != NULL) && (style->master == masterStyle)) { eLink = &style->elements[masterElemIndex]; if (eLink->elem == masterElem) { #ifdef CACHE_ELEM_SIZE if (csM & CS_LAYOUT) eLink->neededWidth = eLink->neededHeight = -1; #endif cMask |= csM; } /* Instance element */ else { args.elem = eLink->elem; eMask = (*masterElem->typePtr->changeProc)(&args); #ifdef CACHE_ELEM_SIZE if (eMask & CS_LAYOUT) eLink->neededWidth = eLink->neededHeight = -1; #endif cMask |= eMask; } iMask |= cMask; if (cMask & CS_LAYOUT) { style->neededWidth = style->neededHeight = -1; Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_InvalidateSize(tree, column); } else if (cMask & CS_DISPLAY) { Tree_InvalidateItemDInfo(tree, treeColumn, item, NULL); } } columnIndex++; column = TreeItemColumn_GetNext(tree, column); treeColumn = TreeColumn_Next(treeColumn); } if (iMask & CS_LAYOUT) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); updateDInfo = TRUE; } else if (iMask & CS_DISPLAY) { } hPtr = Tcl_NextHashEntry(&search); } if (updateDInfo) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } /* *---------------------------------------------------------------------- * * TreeStyle_GetMaster -- * * Return the master style for an instance style. * * Results: * Token for the master style. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeStyle TreeStyle_GetMaster( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Instance style token. */ ) { return (TreeStyle) ((IStyle *) style_)->master; } static Tcl_Obj *confImageObj = NULL; static Tcl_Obj *confTextObj = NULL; /* *---------------------------------------------------------------------- * * Style_GetImageOrText -- * * Return the value of a configuration option for an element. * * Results: * The result of Tk_GetOptionValue for an option of the first * element of the proper type (if any), otherwise NULL. * * Side effects: * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ static Tcl_Obj * Style_GetImageOrText( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style. */ ElementType *typePtr, /* Type of element to look for. */ CONST char *optionName, /* Name of config option to query. */ Tcl_Obj **optionNameObj /* Pointer to a Tcl_Obj to hold the * option name. Initialized * on the first call. */ ) { IElementLink *eLink; int i; if (*optionNameObj == NULL) { *optionNameObj = Tcl_NewStringObj(optionName, -1); Tcl_IncrRefCount(*optionNameObj); } for (i = 0; i < style->master->numElements; i++) { eLink = &style->elements[i]; if (ELEMENT_TYPE_MATCHES(eLink->elem->typePtr, typePtr)) { Tcl_Obj *resultObjPtr; resultObjPtr = Tk_GetOptionValue(tree->interp, (char *) eLink->elem, eLink->elem->typePtr->optionTable, *optionNameObj, tree->tkwin); return resultObjPtr; } } return NULL; } /* *---------------------------------------------------------------------- * * TreeStyle_GetImage -- * * Return the value of the -image option for the first * image element in a style (if any). * * Results: * The result of Tk_GetOptionValue if the element was found, * otherwise NULL. * * Side effects: * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeStyle_GetImage( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Token for style to examine. */ ) { return Style_GetImageOrText(tree, (IStyle *) style_, &elemTypeImage, "-image", &confImageObj); } /* *---------------------------------------------------------------------- * * TreeStyle_GetText -- * * Return the value of the -text option for the first * text element in a style (if any). * * Results: * The result of Tk_GetOptionValue if the element was found, * otherwise NULL. * * Side effects: * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeStyle_GetText( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Token for style to examine. */ ) { return Style_GetImageOrText(tree, (IStyle *) style_, &elemTypeText, "-text", &confTextObj); } /* *---------------------------------------------------------------------- * * Style_SetImageOrText -- * * Set the value of a configuration option for the first * element of the proper type in a style (if any). * * Results: * A standard Tcl result. * * Side effects: * Size of the element and style will be marked out-of-date. * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ static int Style_SetImageOrText( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the style. Needed if * a new instance Element is created. */ TreeItemColumn column, /* Item-column containing the style */ IStyle *style, /* The style */ ElementType *typePtr, /* Element type to look for. */ CONST char *optionName, /* NULL-terminated config option name. */ Tcl_Obj **optionNameObj, /* Pointer to Tcl_Obj to hold the option * name; initialized on the first call. */ Tcl_Obj *valueObj /* New value for the config option. */ ) { MStyle *masterStyle = style->master; IElementLink *eLink; int i; if (*optionNameObj == NULL) { *optionNameObj = Tcl_NewStringObj(optionName, -1); Tcl_IncrRefCount(*optionNameObj); } for (i = 0; i < masterStyle->numElements; i++) { Element *masterElem = masterStyle->elements[i].elem; if (ELEMENT_TYPE_MATCHES(masterElem->typePtr, typePtr)) { Tcl_Obj *objv[2]; ElementArgs args; eLink = Style_CreateElem(tree, item, column, style, masterElem, NULL); objv[0] = *optionNameObj; objv[1] = valueObj; args.tree = tree; args.elem = eLink->elem; args.config.objc = 2; args.config.objv = objv; args.config.flagSelf = 0; args.config.item = item; args.config.column = column; if ((*eLink->elem->typePtr->configProc)(&args) != TCL_OK) return TCL_ERROR; args.change.flagSelf = args.config.flagSelf; args.change.flagTree = 0; args.change.flagMaster = 0; (void) (*eLink->elem->typePtr->changeProc)(&args); #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif style->neededWidth = style->neededHeight = -1; break; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeStyle_SetImage -- * * Set the value of the -image option for the first image * element in a style (if any). * * Results: * A standard Tcl result. * * Side effects: * Size of the element and style will be marked out-of-date. * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ int TreeStyle_SetImage( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the style. */ TreeItemColumn column, /* Item-column containing the style. */ TreeStyle style_, /* The instance style. */ Tcl_Obj *valueObj /* New value for -image option. */ ) { return Style_SetImageOrText(tree, item, column, (IStyle *) style_, &elemTypeImage, "-image", &confImageObj, valueObj); } /* *---------------------------------------------------------------------- * * TreeStyle_SetText -- * * Set the value of the -text option for the first text * element in a style (if any). * * Results: * A standard Tcl result. * * Side effects: * Size of the element and style will be marked out-of-date. * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ int TreeStyle_SetText( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the style. */ TreeItemColumn column, /* Item-column containing the style. */ TreeStyle style_, /* The instance style. */ Tcl_Obj *valueObj /* New value for -text option. */ ) { return Style_SetImageOrText(tree, item, column, (IStyle *) style_, &elemTypeText, "-text", &confTextObj, valueObj); } /* *---------------------------------------------------------------------- * * Style_Deleted -- * * Called when a master style is about to be deleted. Any * item-columns using an instance of the style have their style * freed. * * Results: * The TreeCtrl -defaultstyle option is updated if the deleted * style was specified in the value of the option. * * Side effects: * Display changes. Memory is deallocated. * *---------------------------------------------------------------------- */ static void Style_Deleted( TreeCtrl *tree, /* Widget info. */ MStyle *masterStyle /* The master style being deleted. */ ) { TreeItem item; TreeItemColumn column; TreeColumn treeColumn; Tcl_HashEntry *hPtr; Tcl_HashSearch search; IStyle *style; int columnIndex; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); treeColumn = tree->columns; column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; while (column != NULL) { style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if ((style != NULL) && (style->master == masterStyle)) { Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_ForgetStyle(tree, column); TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); } columnIndex++; column = TreeItemColumn_GetNext(tree, column); treeColumn = TreeColumn_Next(treeColumn); } hPtr = Tcl_NextHashEntry(&search); } /* Update each column's -itemstyle option */ treeColumn = tree->columns; while (treeColumn != NULL) { TreeColumn_StyleDeleted(treeColumn, (TreeStyle) masterStyle); treeColumn = TreeColumn_Next(treeColumn); } #ifdef DEPRECATED /* Update -defaultstyle option */ if (tree->defaultStyle.stylesObj != NULL) { Tcl_Obj *stylesObj = tree->defaultStyle.stylesObj; if (Tcl_IsShared(stylesObj)) { stylesObj = Tcl_DuplicateObj(stylesObj); Tcl_DecrRefCount(tree->defaultStyle.stylesObj); Tcl_IncrRefCount(stylesObj); tree->defaultStyle.stylesObj = stylesObj; } for (columnIndex = 0; columnIndex < tree->defaultStyle.numStyles; columnIndex++) { Tcl_Obj *emptyObj; if (tree->defaultStyle.styles[columnIndex] != (TreeStyle) masterStyle) continue; tree->defaultStyle.styles[columnIndex] = NULL; emptyObj = Tcl_NewObj(); Tcl_ListObjReplace(tree->interp, stylesObj, columnIndex, 1, 1, &emptyObj); } } #endif /* DEPRECATED */ } /* *---------------------------------------------------------------------- * * Element_Changed -- * * Called when a master element or TreeCtrl has been configured. * * Results: * Every master and instance style using the element is updated. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Element_Changed( TreeCtrl *tree, /* Widget info. */ Element *masterElem, /* Master element that may have changed. */ int flagM, /* Flags returned by ElementType.configProc() * if the master element was configured, * zero if the TreeCtrl was configured. */ int flagT, /* TREE_CONF_xxx flags if the TreeCtrl was * configured, zero if the master element * was configured. */ int csM /* CS_xxx flags returned by * ElementType.changeProc(). */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; MStyle *masterStyle; MElementLink *eLink; int i; hPtr = Tcl_FirstHashEntry(&tree->styleHash, &search); while (hPtr != NULL) { masterStyle = (MStyle *) Tcl_GetHashValue(hPtr); for (i = 0; i < masterStyle->numElements; i++) { eLink = &masterStyle->elements[i]; if (eLink->elem == masterElem) { Style_ElemChanged(tree, masterStyle, masterElem, i, flagM, flagT, csM); break; } } hPtr = Tcl_NextHashEntry(&search); } } /* *---------------------------------------------------------------------- * * Element_Deleted -- * * Called when a master element is about to be deleted. * * Results: * The list of elements in any master styles using the element is * updated. Ditto for instance styles. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Element_Deleted( TreeCtrl *tree, /* Widget info. */ Element *masterElem /* Master element being deleted. */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; MStyle *masterStyle; MElementLink *eLink; int i, j; hPtr = Tcl_FirstHashEntry(&tree->styleHash, &search); while (hPtr != NULL) { masterStyle = (MStyle *) Tcl_GetHashValue(hPtr); for (i = 0; i < masterStyle->numElements; i++) { eLink = &masterStyle->elements[i]; if (eLink->elem == masterElem) { Element *staticElemList[STATIC_SIZE], **elemList = staticElemList; int staticElemMap[STATIC_SIZE], *elemMap = staticElemMap; STATIC_ALLOC(elemList, Element *, masterStyle->numElements); STATIC_ALLOC(elemMap, int, masterStyle->numElements); for (j = 0; j < masterStyle->numElements; j++) { if (j == i) continue; elemList[(j < i) ? j : (j - 1)] = masterStyle->elements[j].elem; elemMap[(j < i) ? j : (j - 1)] = j; } Style_ChangeElements(tree, masterStyle, masterStyle->numElements - 1, elemList, elemMap); STATIC_FREE(elemList, Element *, masterStyle->numElements + 1); STATIC_FREE(elemMap, int, masterStyle->numElements + 1); break; } } hPtr = Tcl_NextHashEntry(&search); } } /* *---------------------------------------------------------------------- * * Tree_RedrawElement -- * * A STUB export. Schedules a redraw of the given item. * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void Tree_RedrawElement( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ Element *elem /* The element that changed. */ ) { /* Master element */ if (elem->master == NULL) { } /* Instance element */ else { Tree_InvalidateItemDInfo(tree, NULL, item, NULL); } } typedef struct Iterate { TreeCtrl *tree; TreeItem item; TreeItemColumn column; int columnIndex; IStyle *style; ElementType *elemTypePtr; IElementLink *eLink; Tcl_HashSearch search; Tcl_HashEntry *hPtr; } Iterate; static int IterateItem(Iterate *iter) { int i; while (iter->column != NULL) { iter->style = (IStyle *) TreeItemColumn_GetStyle(iter->tree, iter->column); if (iter->style != NULL) { for (i = 0; i < iter->style->master->numElements; i++) { iter->eLink = &iter->style->elements[i]; if (ELEMENT_TYPE_MATCHES(iter->eLink->elem->typePtr, iter->elemTypePtr)) return 1; } } iter->column = TreeItemColumn_GetNext(iter->tree, iter->column); iter->columnIndex++; } return 0; } TreeIterate Tree_ElementIterateBegin(TreeCtrl *tree, ElementType *elemTypePtr) { Iterate *iter; iter = (Iterate *) ckalloc(sizeof(Iterate)); iter->tree = tree; iter->elemTypePtr = elemTypePtr; iter->hPtr = Tcl_FirstHashEntry(&tree->itemHash, &iter->search); while (iter->hPtr != NULL) { iter->item = (TreeItem) Tcl_GetHashValue(iter->hPtr); iter->column = TreeItem_GetFirstColumn(tree, iter->item); iter->columnIndex = 0; if (IterateItem(iter)) return (TreeIterate) iter; iter->hPtr = Tcl_NextHashEntry(&iter->search); } ckfree((char *) iter); return NULL; } TreeIterate Tree_ElementIterateNext(TreeIterate iter_) { Iterate *iter = (Iterate *) iter_; iter->column = TreeItemColumn_GetNext(iter->tree, iter->column); iter->columnIndex++; if (IterateItem(iter)) return iter_; iter->hPtr = Tcl_NextHashEntry(&iter->search); while (iter->hPtr != NULL) { iter->item = (TreeItem) Tcl_GetHashValue(iter->hPtr); iter->column = TreeItem_GetFirstColumn(iter->tree, iter->item); iter->columnIndex = 0; if (IterateItem(iter)) return iter_; iter->hPtr = Tcl_NextHashEntry(&iter->search); } ckfree((char *) iter); return NULL; } /* *---------------------------------------------------------------------- * * Tree_ElementChangedItself -- * * Called when an element has reconfigured itself outside of * any API calls. For example, when a window associated with a * window element is resized, or a text element's -textvariable * is set. * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void Tree_ElementChangedItself( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ TreeItemColumn column, /* Item-column containing the element. */ Element *elem, /* The element that changed. */ int flags, /* Element-specific configuration flags. */ int csM /* CS_xxx flags detailing the effects of * the change. */ ) { /* Master element. */ if (item == NULL) { Element_Changed(tree, elem, flags, 0, csM); return; } if (csM & CS_LAYOUT) { IStyle *style = (IStyle *) TreeItemColumn_GetStyle(tree, column); int i; IElementLink *eLink = NULL; int columnIndex; if (style == NULL) panic("Tree_ElementChangedItself but style is NULL\n"); for (i = 0; i < style->master->numElements; i++) { eLink = &style->elements[i]; if (eLink->elem == elem) break; } if (eLink == NULL) panic("Tree_ElementChangedItself but eLink is NULL\n"); columnIndex = TreeItemColumn_Index(tree, item, column); #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif style->neededWidth = style->neededHeight = -1; Tree_InvalidateColumnWidth(tree, Tree_FindColumn(tree, columnIndex)); TreeItemColumn_InvalidateSize(tree, column); TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } else if (csM & CS_DISPLAY) { int columnIndex; columnIndex = TreeItemColumn_Index(tree, item, column); Tree_InvalidateItemDInfo(tree, Tree_FindColumn(tree, columnIndex), item, NULL); } } void Tree_ElementIterateChanged(TreeIterate iter_, int mask) { Iterate *iter = (Iterate *) iter_; if (mask & CS_LAYOUT) { #ifdef CACHE_ELEM_SIZE iter->eLink->neededWidth = iter->eLink->neededHeight = -1; #endif iter->style->neededWidth = iter->style->neededHeight = -1; Tree_InvalidateColumnWidth(iter->tree, Tree_FindColumn(iter->tree, iter->columnIndex)); TreeItemColumn_InvalidateSize(iter->tree, iter->column); TreeItem_InvalidateHeight(iter->tree, iter->item); Tree_FreeItemDInfo(iter->tree, iter->item, NULL); Tree_DInfoChanged(iter->tree, DINFO_REDO_RANGES); } if (mask & CS_DISPLAY) Tree_InvalidateItemDInfo(iter->tree, NULL, iter->item, NULL); } Element *Tree_ElementIterateGet(TreeIterate iter_) { Iterate *iter = (Iterate *) iter_; return iter->eLink->elem; } /* *---------------------------------------------------------------------- * * TreeStyle_TreeChanged -- * * Called when a TreeCtrl is configured. This handles changes to * the -font option affecting text elements for example. * * Results: * Calls the changeProc on every master element. Any elements * affected by the change are eventually redisplayed. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void TreeStyle_TreeChanged( TreeCtrl *tree, /* Widget info. */ int flagT /* TREE_CONF_xxx flags. */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; Element *masterElem; ElementArgs args; int eMask; if (flagT == 0) return; args.tree = tree; args.change.flagTree = flagT; args.change.flagMaster = 0; args.change.flagSelf = 0; hPtr = Tcl_FirstHashEntry(&tree->elementHash, &search); while (hPtr != NULL) { masterElem = (Element *) Tcl_GetHashValue(hPtr); args.elem = masterElem; eMask = (*masterElem->typePtr->changeProc)(&args); Element_Changed(tree, masterElem, 0, flagT, eMask); hPtr = Tcl_NextHashEntry(&search); } } /* *---------------------------------------------------------------------- * * TreeStyle_ElementCget -- * * This procedure is invoked to process the [item element cget] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyle_ElementCget( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ TreeItemColumn column, /* Item-column containing the element. */ TreeStyle style_, /* Style containing the element. */ Tcl_Obj *elemObj, /* Name of the element. */ Tcl_Obj *optionNameObj /* Name of the config option. */ ) { IStyle *style = (IStyle *) style_; Tcl_Obj *resultObjPtr = NULL; Element *elem; IElementLink *eLink; if (Element_FromObj(tree, elemObj, &elem) != TCL_OK) return TCL_ERROR; eLink = IStyle_FindElem(tree, style, elem, NULL); if ((eLink != NULL) && (eLink->elem == elem)) { int index = TreeItemColumn_Index(tree, item, column); TreeColumn treeColumn = Tree_FindColumn(tree, index); FormatResult(tree->interp, "element %s is not configured in item %s%d column %s%d", elem->name, tree->itemPrefix, TreeItem_GetID(tree, item), tree->columnPrefix, TreeColumn_GetID(treeColumn)); return TCL_ERROR; } if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", style->master->name, elem->name); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(tree->interp, (char *) eLink->elem, eLink->elem->typePtr->optionTable, optionNameObj, tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(tree->interp, resultObjPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeStyle_ElementConfigure -- * * This procedure is invoked to process the [item element configure] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyle_ElementConfigure( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ TreeItemColumn column, /* Item-column containing the element. */ TreeStyle style_, /* Style containing the element. */ Tcl_Obj *elemObj, /* Name of the element. */ int objc, /* Number of arguments. */ Tcl_Obj **objv, /* Argument values. */ int *eMask /* Returned CS_xxx flags. */ ) { IStyle *style = (IStyle *) style_; Element *elem; IElementLink *eLink; ElementArgs args; (*eMask) = 0; if (Element_FromObj(tree, elemObj, &elem) != TCL_OK) return TCL_ERROR; if (objc <= 1) { Tcl_Obj *resultObjPtr; eLink = IStyle_FindElem(tree, style, elem, NULL); if ((eLink != NULL) && (eLink->elem == elem)) { int index = TreeItemColumn_Index(tree, item, column); TreeColumn treeColumn = Tree_FindColumn(tree, index); FormatResult(tree->interp, "element %s is not configured in item %s%d column %s%d", elem->name, tree->itemPrefix, TreeItem_GetID(tree, item), tree->columnPrefix, TreeColumn_GetID(treeColumn)); return TCL_ERROR; } if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", style->master->name, elem->name); return TCL_ERROR; } resultObjPtr = Tk_GetOptionInfo(tree->interp, (char *) eLink->elem, eLink->elem->typePtr->optionTable, (objc == 0) ? (Tcl_Obj *) NULL : objv[0], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(tree->interp, resultObjPtr); } else { int isNew; eLink = Style_CreateElem(tree, item, column, style, elem, &isNew); if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", style->master->name, elem->name); return TCL_ERROR; } /* Do this before configProc(). If eLink was just allocated and an * error occurs in configProc() it won't be done */ (*eMask) = 0; if (isNew) { #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif style->neededWidth = style->neededHeight = -1; (*eMask) = CS_DISPLAY | CS_LAYOUT; } args.tree = tree; args.elem = eLink->elem; args.config.objc = objc; args.config.objv = objv; args.config.flagSelf = 0; args.config.item = item; args.config.column = column; if ((*args.elem->typePtr->configProc)(&args) != TCL_OK) return TCL_ERROR; args.change.flagSelf = args.config.flagSelf; args.change.flagTree = 0; args.change.flagMaster = 0; (*eMask) |= (*elem->typePtr->changeProc)(&args); if (!isNew && ((*eMask) & CS_LAYOUT)) { #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif style->neededWidth = style->neededHeight = -1; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeStyle_ElementActual -- * * This procedure is invoked to process the [item element perstate] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyle_ElementActual( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* The style. */ int state, /* STATE_xxx flags. */ Tcl_Obj *elemObj, /* Name of the element. */ Tcl_Obj *optionNameObj /* Name of the config option. */ ) { IStyle *style = (IStyle *) style_; Element *masterElem; IElementLink *eLink; ElementArgs args; if (Element_FromObj(tree, elemObj, &masterElem) != TCL_OK) return TCL_ERROR; eLink = IStyle_FindElem(tree, style, masterElem, NULL); if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", style->master->name, masterElem->name); return TCL_ERROR; } args.tree = tree; args.elem = eLink->elem; args.state = state; args.actual.obj = optionNameObj; return (*masterElem->typePtr->actualProc)(&args); } /* *---------------------------------------------------------------------- * * TreeElementCmd -- * * This procedure is invoked to process the [element] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeElementCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandNames[] = { "cget", "configure", "create", "delete", "names", "perstate", "type", (char *) NULL }; enum { COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CREATE, COMMAND_DELETE, COMMAND_NAMES, COMMAND_PERSTATE, COMMAND_TYPE }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_CGET: { Tcl_Obj *resultObjPtr = NULL; Element *elem; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "name option"); return TCL_ERROR; } if (Element_FromObj(tree, objv[3], &elem) != TCL_OK) return TCL_ERROR; resultObjPtr = Tk_GetOptionValue(interp, (char *) elem, elem->typePtr->optionTable, objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr = NULL; Element *elem; int eMask; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "name ?option? ?value option value ...?"); return TCL_ERROR; } if (Element_FromObj(tree, objv[3], &elem) != TCL_OK) return TCL_ERROR; if (objc <= 5) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) elem, elem->typePtr->optionTable, (objc == 4) ? (Tcl_Obj *) NULL : objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); } else { ElementArgs args; args.tree = tree; args.elem = elem; args.config.objc = objc - 4; args.config.objv = objv + 4; args.config.flagSelf = 0; args.config.item = NULL; args.config.column = NULL; if ((*elem->typePtr->configProc)(&args) != TCL_OK) return TCL_ERROR; args.change.flagSelf = args.config.flagSelf; args.change.flagTree = 0; args.change.flagMaster = 0; eMask = (*elem->typePtr->changeProc)(&args); Element_Changed(tree, elem, args.change.flagSelf, 0, eMask); } break; } case COMMAND_CREATE: { char *name; int length; int isNew; Element *elem; ElementType *typePtr; Tcl_HashEntry *hPtr; if (objc < 5) { Tcl_WrongNumArgs(interp, 3, objv, "name type ?option value ...?"); return TCL_ERROR; } name = Tcl_GetStringFromObj(objv[3], &length); if (!length) return TCL_ERROR; hPtr = Tcl_FindHashEntry(&tree->elementHash, name); if (hPtr != NULL) { FormatResult(interp, "element \"%s\" already exists", name); return TCL_ERROR; } if (TreeElement_TypeFromObj(tree, objv[4], &typePtr) != TCL_OK) return TCL_ERROR; elem = Element_CreateAndConfig(tree, NULL, NULL, NULL, typePtr, name, objc - 5, objv + 5); if (elem == NULL) return TCL_ERROR; hPtr = Tcl_CreateHashEntry(&tree->elementHash, name, &isNew); Tcl_SetHashValue(hPtr, elem); Tcl_SetObjResult(interp, Element_ToObj(elem)); break; } case COMMAND_DELETE: { Element *elem; int i; for (i = 3; i < objc; i++) { if (Element_FromObj(tree, objv[i], &elem) != TCL_OK) return TCL_ERROR; Element_Deleted(tree, elem); Element_FreeResources(tree, elem); } break; } case COMMAND_NAMES: { Tcl_Obj *listObj; Tcl_HashSearch search; Tcl_HashEntry *hPtr; Element *elem; if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } listObj = Tcl_NewListObj(0, NULL); hPtr = Tcl_FirstHashEntry(&tree->elementHash, &search); while (hPtr != NULL) { elem = (Element *) Tcl_GetHashValue(hPtr); Tcl_ListObjAppendElement(interp, listObj, Element_ToObj(elem)); hPtr = Tcl_NextHashEntry(&search); } Tcl_SetObjResult(interp, listObj); break; } /* T element perstate E option stateList */ case COMMAND_PERSTATE: { Element *elem; int states[3]; ElementArgs args; if (objc != 6) { Tcl_WrongNumArgs(tree->interp, 3, objv, "element option stateList"); return TCL_ERROR; } if (Element_FromObj(tree, objv[3], &elem) != TCL_OK) return TCL_ERROR; if (Tree_StateFromListObj(tree, objv[5], states, SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; args.tree = tree; args.elem = elem; args.state = states[STATE_OP_ON]; args.actual.obj = objv[4]; return (*elem->typePtr->actualProc)(&args); } case COMMAND_TYPE: { Element *elem; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "name"); return TCL_ERROR; } if (Element_FromObj(tree, objv[3], &elem) != TCL_OK) return TCL_ERROR; Tcl_SetResult(interp, elem->typePtr->name, TCL_STATIC); /* Tk_Uid */ break; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Style_CreateAndConfig -- * * Allocate and initialize a master style. * * Results: * Pointer to the new Style, or NULL if an error occurs. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static MStyle * Style_CreateAndConfig( TreeCtrl *tree, /* Widget info. */ char *name, /* Name of new style. */ int objc, /* Number of config-option arg-value pairs. */ Tcl_Obj *CONST objv[] /* Config-option arg-value pairs. */ ) { MStyle *style; #ifdef ALLOC_HAX style = (MStyle *) AllocHax_Alloc(tree->allocData, MStyleUid, sizeof(MStyle)); #else style = (MStyle *) ckalloc(sizeof(MStyle)); #endif memset(style, '\0', sizeof(MStyle)); style->name = Tk_GetUid(name); if (Tk_InitOptions(tree->interp, (char *) style, tree->styleOptionTable, tree->tkwin) != TCL_OK) { #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, MStyleUid, (char *) style, sizeof(MStyle)); #else WFREE(style, MStyle); #endif return NULL; } if (Tk_SetOptions(tree->interp, (char *) style, tree->styleOptionTable, objc, objv, tree->tkwin, NULL, NULL) != TCL_OK) { Tk_FreeConfigOptions((char *) style, tree->styleOptionTable, tree->tkwin); #ifdef ALLOC_HAX AllocHax_Free(tree->allocData, MStyleUid, (char *) style, sizeof(MStyle)); #else WFREE(style, MStyle); #endif return NULL; } return style; } /* *---------------------------------------------------------------------- * * TreeStyle_ListElements -- * * Creates a Tcl list with the names of elements in a style. * * Results: * If the style is a master style, the interpreter result holds * a list of each element in the style. If the style is an * instance style, the interpreter result holds a list of those * elements configured for the style (i.e., instance elements). * * Side effects: * Memory is allocated, interpreter result changed. * *---------------------------------------------------------------------- */ void TreeStyle_ListElements( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* The style. */ ) { MStyle *masterStyle = (MStyle *) style_; IStyle *style = (IStyle *) style_; Tcl_Obj *listObj; Element *elem; int i, numElements = TreeStyle_NumElements(tree, style_); if (numElements <= 0) return; listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < numElements; i++) { if (style->master != NULL) { elem = style->elements[i].elem; if (elem->master == NULL) continue; } else { elem = masterStyle->elements[i].elem; } Tcl_ListObjAppendElement(tree->interp, listObj, Element_ToObj(elem)); } Tcl_SetObjResult(tree->interp, listObj); } enum { OPTION_DETACH, OPTION_EXPAND, OPTION_HEIGHT, OPTION_iEXPAND, OPTION_INDENT, OPTION_iPADX, OPTION_iPADY, OPTION_MAXHEIGHT, OPTION_MAXWIDTH, OPTION_MINHEIGHT, OPTION_MINWIDTH, OPTION_PADX, OPTION_PADY, OPTION_SQUEEZE, OPTION_STICKY, OPTION_UNION, OPTION_WIDTH }; /* *---------------------------------------------------------------------- * * LayoutOptionToObj -- * * Return a Tcl_Obj holding the value of a style layout option * for an element. * * Results: * Pointer to a new Tcl_Obj or NULL if the option has no value. * * Side effects: * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ static Tcl_Obj * LayoutOptionToObj( TreeCtrl *tree, /* Widget info. */ MStyle *style, /* Master style using the element. */ MElementLink *eLink, /* Layout info for the element. */ int option /* OPTION_xxx constant. */ ) { Tcl_Interp *interp = tree->interp; switch (option) { case OPTION_PADX: return TreeCtrl_NewPadAmountObj(eLink->ePadX); case OPTION_PADY: return TreeCtrl_NewPadAmountObj(eLink->ePadY); case OPTION_iPADX: return TreeCtrl_NewPadAmountObj(eLink->iPadX); case OPTION_iPADY: return TreeCtrl_NewPadAmountObj(eLink->iPadY); case OPTION_DETACH: return Tcl_NewStringObj((eLink->flags & ELF_DETACH) ? "yes" : "no", -1); case OPTION_EXPAND: { char flags[4]; int n = 0; if (eLink->flags & ELF_eEXPAND_W) flags[n++] = 'w'; if (eLink->flags & ELF_eEXPAND_N) flags[n++] = 'n'; if (eLink->flags & ELF_eEXPAND_E) flags[n++] = 'e'; if (eLink->flags & ELF_eEXPAND_S) flags[n++] = 's'; if (n) return Tcl_NewStringObj(flags, n); break; } case OPTION_iEXPAND: { char flags[6]; int n = 0; if (eLink->flags & ELF_iEXPAND_X) flags[n++] = 'x'; if (eLink->flags & ELF_iEXPAND_Y) flags[n++] = 'y'; if (eLink->flags & ELF_iEXPAND_W) flags[n++] = 'w'; if (eLink->flags & ELF_iEXPAND_N) flags[n++] = 'n'; if (eLink->flags & ELF_iEXPAND_E) flags[n++] = 'e'; if (eLink->flags & ELF_iEXPAND_S) flags[n++] = 's'; if (n) return Tcl_NewStringObj(flags, n); break; } case OPTION_INDENT: return Tcl_NewStringObj((eLink->flags & ELF_INDENT) ? "yes" : "no", -1); case OPTION_SQUEEZE: { char flags[2]; int n = 0; if (eLink->flags & ELF_SQUEEZE_X) flags[n++] = 'x'; if (eLink->flags & ELF_SQUEEZE_Y) flags[n++] = 'y'; if (n) return Tcl_NewStringObj(flags, n); break; } case OPTION_UNION: { int i; Tcl_Obj *objPtr; if (eLink->onionCount == 0) break; objPtr = Tcl_NewListObj(0, NULL); for (i = 0; i < eLink->onionCount; i++) Tcl_ListObjAppendElement(interp, objPtr, Element_ToObj(style->elements[eLink->onion[i]].elem)); return objPtr; } case OPTION_MAXHEIGHT: { if (eLink->maxHeight >= 0) return Tcl_NewIntObj(eLink->maxHeight); break; } case OPTION_MINHEIGHT: { if (eLink->minHeight >= 0) return Tcl_NewIntObj(eLink->minHeight); break; } case OPTION_HEIGHT: { if (eLink->fixedHeight >= 0) return Tcl_NewIntObj(eLink->fixedHeight); break; } case OPTION_MAXWIDTH: { if (eLink->maxWidth >= 0) return Tcl_NewIntObj(eLink->maxWidth); break; } case OPTION_MINWIDTH: { if (eLink->minWidth >= 0) return Tcl_NewIntObj(eLink->minWidth); break; } case OPTION_WIDTH: { if (eLink->fixedWidth >= 0) return Tcl_NewIntObj(eLink->fixedWidth); break; } case OPTION_STICKY: { char flags[4]; int n = 0; if (eLink->flags & ELF_STICKY_W) flags[n++] = 'w'; if (eLink->flags & ELF_STICKY_N) flags[n++] = 'n'; if (eLink->flags & ELF_STICKY_E) flags[n++] = 'e'; if (eLink->flags & ELF_STICKY_S) flags[n++] = 's'; if (n) return Tcl_NewStringObj(flags, n); break; } } return NULL; } /* *---------------------------------------------------------------------- * * StyleLayoutCmd -- * * This procedure is invoked to process the [style layout] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StyleLayoutCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* The current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; TreeStyle _style; MStyle *style; Element *elem; MElementLink saved, *eLink; int i, index; static CONST84 char *optionNames[] = { "-detach", "-expand", "-height", "-iexpand", "-indent", "-ipadx", "-ipady", "-maxheight", "-maxwidth", "-minheight", "-minwidth", "-padx", "-pady", "-squeeze", "-sticky", "-union", "-width", (char *) NULL }; if (objc < 5) { Tcl_WrongNumArgs(interp, 3, objv, "name element ?option? ?value? ?option value ...?"); return TCL_ERROR; } if (TreeStyle_FromObj(tree, objv[3], &_style) != TCL_OK) return TCL_ERROR; style = (MStyle *) _style; if (Element_FromObj(tree, objv[4], &elem) != TCL_OK) return TCL_ERROR; eLink = MStyle_FindElem(tree, style, elem, NULL); if (eLink == NULL) { FormatResult(interp, "style %s does not use element %s", style->name, elem->name); return TCL_ERROR; } /* T style layout S E */ if (objc == 5) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); Tcl_Obj *objPtr; for (i = 0; optionNames[i] != NULL; i++) { Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(optionNames[i], -1)); objPtr = LayoutOptionToObj(tree, style, eLink, i); Tcl_ListObjAppendElement(interp, listObj, objPtr ? objPtr : Tcl_NewObj()); } Tcl_SetObjResult(interp, listObj); return TCL_OK; } /* T style layout S E option */ if (objc == 6) { Tcl_Obj *objPtr; if (Tcl_GetIndexFromObj(interp, objv[5], optionNames, "option", 0, &index) != TCL_OK) return TCL_ERROR; objPtr = LayoutOptionToObj(tree, style, eLink, index); if (objPtr != NULL) Tcl_SetObjResult(interp, objPtr); return TCL_OK; } saved = *eLink; for (i = 5; i < objc; i += 2) { if (i + 2 > objc) { FormatResult(interp, "value for \"%s\" missing", Tcl_GetString(objv[i])); goto badConfig; } if (Tcl_GetIndexFromObj(interp, objv[i], optionNames, "option", 0, &index) != TCL_OK) { goto badConfig; } switch (index) { case OPTION_PADX: { if (TreeCtrl_GetPadAmountFromObj(interp, tree->tkwin, objv[i + 1], &eLink->ePadX[PAD_TOP_LEFT], &eLink->ePadX[PAD_BOTTOM_RIGHT]) != TCL_OK) goto badConfig; break; } case OPTION_PADY: { if (TreeCtrl_GetPadAmountFromObj(interp, tree->tkwin, objv[i + 1], &eLink->ePadY[PAD_TOP_LEFT], &eLink->ePadY[PAD_BOTTOM_RIGHT]) != TCL_OK) goto badConfig; break; } case OPTION_iPADX: { if (TreeCtrl_GetPadAmountFromObj(interp, tree->tkwin, objv[i + 1], &eLink->iPadX[PAD_TOP_LEFT], &eLink->iPadX[PAD_BOTTOM_RIGHT]) != TCL_OK) goto badConfig; break; } case OPTION_iPADY: { if (TreeCtrl_GetPadAmountFromObj(interp, tree->tkwin, objv[i + 1], &eLink->iPadY[PAD_TOP_LEFT], &eLink->iPadY[PAD_BOTTOM_RIGHT]) != TCL_OK) goto badConfig; break; } case OPTION_DETACH: { int detach; if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &detach) != TCL_OK) goto badConfig; if (detach) eLink->flags |= ELF_DETACH; else eLink->flags &= ~ELF_DETACH; break; } case OPTION_EXPAND: { char *expand; int len, k; expand = Tcl_GetStringFromObj(objv[i + 1], &len); eLink->flags &= ~ELF_eEXPAND; for (k = 0; k < len; k++) { switch (expand[k]) { case 'w': case 'W': eLink->flags |= ELF_eEXPAND_W; break; case 'n': case 'N': eLink->flags |= ELF_eEXPAND_N; break; case 'e': case 'E': eLink->flags |= ELF_eEXPAND_E; break; case 's': case 'S': eLink->flags |= ELF_eEXPAND_S; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad expand value \"", expand, "\": must be a string ", "containing zero or more of n, e, s, and w", (char *) NULL); goto badConfig; } } } break; } case OPTION_iEXPAND: { char *expand; int len, k; expand = Tcl_GetStringFromObj(objv[i + 1], &len); eLink->flags &= ~(ELF_iEXPAND | ELF_iEXPAND_X | ELF_iEXPAND_Y); for (k = 0; k < len; k++) { switch (expand[k]) { case 'x': case 'X': eLink->flags |= ELF_iEXPAND_X; break; case 'y': case 'Y': eLink->flags |= ELF_iEXPAND_Y; break; case 'w': case 'W': eLink->flags |= ELF_iEXPAND_W; break; case 'n': case 'N': eLink->flags |= ELF_iEXPAND_N; break; case 'e': case 'E': eLink->flags |= ELF_iEXPAND_E; break; case 's': case 'S': eLink->flags |= ELF_iEXPAND_S; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad iexpand value \"", expand, "\": must be a string ", "containing zero or more of x, y, n, e, s, and w", (char *) NULL); goto badConfig; } } } break; } case OPTION_INDENT: { int indent; if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &indent) != TCL_OK) goto badConfig; if (indent) eLink->flags |= ELF_INDENT; else eLink->flags &= ~ELF_INDENT; break; } case OPTION_SQUEEZE: { char *string; int len, k; string = Tcl_GetStringFromObj(objv[i + 1], &len); eLink->flags &= ~(ELF_SQUEEZE_X | ELF_SQUEEZE_Y); for (k = 0; k < len; k++) { switch (string[k]) { case 'x': case 'X': eLink->flags |= ELF_SQUEEZE_X; break; case 'y': case 'Y': eLink->flags |= ELF_SQUEEZE_Y; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad squeeze value \"", string, "\": must be a string ", "containing zero or more of x and y", (char *) NULL); goto badConfig; } } } break; } case OPTION_UNION: { int objc1; Tcl_Obj **objv1; int j, k, n, *onion, count = 0; if (Tcl_ListObjGetElements(interp, objv[i + 1], &objc1, &objv1) != TCL_OK) goto badConfig; if (objc1 == 0) { if (eLink->onion != NULL) { if (eLink->onion != saved.onion) WCFREE(eLink->onion, int, eLink->onionCount); eLink->onionCount = 0; eLink->onion = NULL; } break; } onion = (int *) ckalloc(sizeof(int) * objc1); for (j = 0; j < objc1; j++) { Element *elem2; MElementLink *eLink2; if (Element_FromObj(tree, objv1[j], &elem2) != TCL_OK) { ckfree((char *) onion); goto badConfig; } eLink2 = MStyle_FindElem(tree, style, elem2, &n); if (eLink2 == NULL) { ckfree((char *) onion); FormatResult(interp, "style %s does not use element %s", style->name, elem2->name); goto badConfig; } if (eLink == eLink2) { ckfree((char *) onion); FormatResult(interp, "element %s can't form union with itself", elem2->name); goto badConfig; } /* Silently ignore duplicates */ for (k = 0; k < count; k++) { if (onion[k] == n) break; } if (k < count) continue; onion[count++] = n; } if ((eLink->onion != NULL) && (eLink->onion != saved.onion)) WCFREE(eLink->onion, int, eLink->onionCount); if (count == objc1) eLink->onion = onion; else { eLink->onion = (int *) ckalloc(sizeof(int) * count); for (k = 0; k < count; k++) eLink->onion[k] = onion[k]; ckfree((char *) onion); } eLink->onionCount = count; break; } case OPTION_MAXHEIGHT: { int height; if (ObjectIsEmpty(objv[i + 1])) { eLink->maxHeight = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &height) != TCL_OK) || (height < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->maxHeight = height; break; } case OPTION_MINHEIGHT: { int height; if (ObjectIsEmpty(objv[i + 1])) { eLink->minHeight = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &height) != TCL_OK) || (height < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->minHeight = height; break; } case OPTION_HEIGHT: { int height; if (ObjectIsEmpty(objv[i + 1])) { eLink->fixedHeight = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &height) != TCL_OK) || (height < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->fixedHeight = height; break; } case OPTION_MAXWIDTH: { int width; if (ObjectIsEmpty(objv[i + 1])) { eLink->maxWidth = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &width) != TCL_OK) || (width < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->maxWidth = width; break; } case OPTION_MINWIDTH: { int width; if (ObjectIsEmpty(objv[i + 1])) { eLink->minWidth = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &width) != TCL_OK) || (width < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->minWidth = width; break; } case OPTION_WIDTH: { int width; if (ObjectIsEmpty(objv[i + 1])) { eLink->fixedWidth = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &width) != TCL_OK) || (width < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->fixedWidth = width; break; } case OPTION_STICKY: { char *sticky; int len, k; sticky = Tcl_GetStringFromObj(objv[i + 1], &len); eLink->flags &= ~ELF_STICKY; for (k = 0; k < len; k++) { switch (sticky[k]) { case 'w': case 'W': eLink->flags |= ELF_STICKY_W; break; case 'n': case 'N': eLink->flags |= ELF_STICKY_N; break; case 'e': case 'E': eLink->flags |= ELF_STICKY_E; break; case 's': case 'S': eLink->flags |= ELF_STICKY_S; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad sticky value \"", sticky, "\": must be a string ", "containing zero or more of n, e, s, and w", (char *) NULL); goto badConfig; } } } break; } } } if (saved.onion && (eLink->onion != saved.onion)) WCFREE(saved.onion, int, saved.onionCount); Style_Changed(tree, style); return TCL_OK; badConfig: if (eLink->onion && (eLink->onion != saved.onion)) WCFREE(eLink->onion, int, eLink->onionCount); *eLink = saved; return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TreeStyleCmd -- * * This procedure is invoked to process the [style] widget * command. See the user documentation for details on what it * does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyleCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; static CONST84 char *commandNames[] = { "cget", "configure", "create", "delete", "elements", "layout", "names", (char *) NULL }; enum { COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CREATE, COMMAND_DELETE, COMMAND_ELEMENTS, COMMAND_LAYOUT, COMMAND_NAMES }; int index; TreeStyle _style; MStyle *style; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_CGET: { Tcl_Obj *resultObjPtr; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "name option"); return TCL_ERROR; } if (TreeStyle_FromObj(tree, objv[3], &_style) != TCL_OK) return TCL_ERROR; style = (MStyle *) _style; resultObjPtr = Tk_GetOptionValue(interp, (char *) style, tree->styleOptionTable, objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr = NULL; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "name ?option? ?value option value ...?"); return TCL_ERROR; } if (TreeStyle_FromObj(tree, objv[3], &_style) != TCL_OK) return TCL_ERROR; style = (MStyle *) _style; if (objc <= 5) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) style, tree->styleOptionTable, (objc == 4) ? (Tcl_Obj *) NULL : objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); } else { if (Tk_SetOptions(tree->interp, (char *) style, tree->styleOptionTable, objc - 4, objv + 4, tree->tkwin, NULL, NULL) != TCL_OK) return TCL_ERROR; Style_Changed(tree, style); } break; } case COMMAND_CREATE: { char *name; int len; Tcl_HashEntry *hPtr; int isNew; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "name ?option value ...?"); return TCL_ERROR; } name = Tcl_GetStringFromObj(objv[3], &len); if (!len) { FormatResult(interp, "invalid style name \"\""); return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&tree->styleHash, name); if (hPtr != NULL) { FormatResult(interp, "style \"%s\" already exists", name); return TCL_ERROR; } style = Style_CreateAndConfig(tree, name, objc - 4, objv + 4); if (style == NULL) return TCL_ERROR; hPtr = Tcl_CreateHashEntry(&tree->styleHash, name, &isNew); Tcl_SetHashValue(hPtr, style); Tcl_SetObjResult(interp, TreeStyle_ToObj((TreeStyle) style)); break; } case COMMAND_DELETE: { int i; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?name ...?"); return TCL_ERROR; } for (i = 3; i < objc; i++) { if (TreeStyle_FromObj(tree, objv[i], &_style) != TCL_OK) return TCL_ERROR; Style_Deleted(tree, (MStyle *) _style); TreeStyle_FreeResources(tree, _style); } break; } /* T style elements S ?{E ...}? */ case COMMAND_ELEMENTS: { Element *elem, **elemList = NULL; int i, j, count = 0; int staticMap[STATIC_SIZE], *map = staticMap; int listObjc; Tcl_Obj **listObjv; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "name ?elementList?"); return TCL_ERROR; } if (TreeStyle_FromObj(tree, objv[3], &_style) != TCL_OK) return TCL_ERROR; style = (MStyle *) _style; if (objc == 5) { if (Tcl_ListObjGetElements(interp, objv[4], &listObjc, &listObjv) != TCL_OK) return TCL_ERROR; if (listObjc > 0) elemList = (Element **) ckalloc(sizeof(Element *) * listObjc); for (i = 0; i < listObjc; i++) { if (Element_FromObj(tree, listObjv[i], &elem) != TCL_OK) { ckfree((char *) elemList); return TCL_ERROR; } /* Ignore duplicate elements */ for (j = 0; j < count; j++) { if (elemList[j] == elem) break; } if (j < count) continue; elemList[count++] = elem; } STATIC_ALLOC(map, int, count); for (i = 0; i < count; i++) map[i] = -1; /* Reassigning Elements to a Style */ if (style->numElements > 0) { /* Check each Element */ for (i = 0; i < count; i++) { /* See if this Element is already used by the Style */ for (j = 0; j < style->numElements; j++) { if (elemList[i] == style->elements[j].elem) { /* Preserve it */ map[i] = j; break; } } } } Style_ChangeElements(tree, style, count, elemList, map); if (elemList != NULL) ckfree((char *) elemList); STATIC_FREE(map, int, count); break; } TreeStyle_ListElements(tree, (TreeStyle) style); break; } /* T style layout S E ?option? ?value? ?option value ...? */ case COMMAND_LAYOUT: { return StyleLayoutCmd(clientData, interp, objc, objv); } case COMMAND_NAMES: { Tcl_Obj *listObj; Tcl_HashSearch search; Tcl_HashEntry *hPtr; listObj = Tcl_NewListObj(0, NULL); hPtr = Tcl_FirstHashEntry(&tree->styleHash, &search); while (hPtr != NULL) { _style = (TreeStyle) Tcl_GetHashValue(hPtr); Tcl_ListObjAppendElement(interp, listObj, TreeStyle_ToObj(_style)); hPtr = Tcl_NextHashEntry(&search); } Tcl_SetObjResult(interp, listObj); break; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * ButtonMaxWidth -- * * Return the maximum possible size of a button in any state. This * includes the size of the -buttonimage and -buttonbitmap options, * as well as the theme button and default +/- button. * * Results: * Pixel size >= 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ int ButtonMaxWidth( TreeCtrl *tree /* Widget info. */ ) { int w, h, width = 0; PerStateImage_MaxSize(tree, &tree->buttonImage, &w, &h); width = MAX(width, w); PerStateBitmap_MaxSize(tree, &tree->buttonBitmap, &w, &h); width = MAX(width, w); if (tree->useTheme) { if (TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), TRUE, &w, &h) == TCL_OK) width = MAX(width, w); if (TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), FALSE, &w, &h) == TCL_OK) width = MAX(width, w); } return MAX(width, tree->buttonSize); } /* *---------------------------------------------------------------------- * * ButtonHeight -- * * Return the size of a button for a certain state. * * Results: * Pixel size >= 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ int ButtonHeight( TreeCtrl *tree, /* Widget info. */ int state /* STATE_xxx flags. */ ) { Tk_Image image; Pixmap bitmap; int w, h; image = PerStateImage_ForState(tree, &tree->buttonImage, state, NULL); if (image != NULL) { Tk_SizeOfImage(image, &w, &h); return h; } bitmap = PerStateBitmap_ForState(tree, &tree->buttonBitmap, state, NULL); if (bitmap != None) { Tk_SizeOfBitmap(tree->display, bitmap, &w, &h); return h; } if (tree->useTheme && TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), (state & STATE_OPEN) != 0, &w, &h) == TCL_OK) return h; return tree->buttonSize; } /* *---------------------------------------------------------------------- * * TreeStyle_Identify -- * * Perform hit-testing on a style. * * Results: * The name of the element containing the given point, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * TreeStyle_Identify( StyleDrawArgs *drawArgs, /* Various args. */ int x, /* Window x-coord to hit-test against. */ int y /* Window y-coord to hit-test against. */ ) { TreeCtrl *tree = drawArgs->tree; IStyle *style = (IStyle *) drawArgs->style; int state = drawArgs->state; IElementLink *eLink = NULL; int i, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; Style_CheckNeededSize(tree, style, state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else Style_MinSize(tree, style, state, &minWidth, &minHeight); #endif if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; x -= drawArgs->x; STATIC_ALLOC(layouts, struct Layout, style->master->numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); for (i = style->master->numElements - 1; i >= 0; i--) { struct Layout *layout = &layouts[i]; eLink = layout->eLink; if ((x >= layout->x + layout->ePadX[PAD_TOP_LEFT]) && (x < layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth) && (y >= layout->y + layout->ePadY[PAD_TOP_LEFT]) && (y < layout->y + layout->ePadY[PAD_TOP_LEFT] + layout->iHeight)) { goto done; } } eLink = NULL; done: STATIC_FREE(layouts, struct Layout, style->master->numElements); if (eLink != NULL) return (char *) eLink->elem->name; return NULL; } /* *---------------------------------------------------------------------- * * TreeStyle_Identify2 -- * * Return a list of elements overlapping the given area. * * Results: * The names of any elements overlapping the given area are * appended to the supplied list. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ void TreeStyle_Identify2( StyleDrawArgs *drawArgs, /* Various args. */ int x1, int y1, /* Top-left of area to hit-test. */ int x2, int y2, /* Bottom-right of area to hit-test. */ Tcl_Obj *listObj /* Initialized list object to hold * the result. */ ) { TreeCtrl *tree = drawArgs->tree; IStyle *style = (IStyle *) drawArgs->style; int state = drawArgs->state; IElementLink *eLink; int i, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; Style_CheckNeededSize(tree, style, state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else Style_MinSize(tree, style, state, &minWidth, &minHeight); #endif if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; STATIC_ALLOC(layouts, struct Layout, style->master->numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); for (i = style->master->numElements - 1; i >= 0; i--) { struct Layout *layout = &layouts[i]; eLink = layout->eLink; if ((drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT] < x2) && (drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth > x1) && (drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT] < y2) && (drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT] + layout->iHeight > y1)) { Tcl_ListObjAppendElement(drawArgs->tree->interp, listObj, Tcl_NewStringObj(eLink->elem->name, -1)); } } STATIC_FREE(layouts, struct Layout, style->master->numElements); } /* *---------------------------------------------------------------------- * * TreeStyle_Remap -- * * The guts of the [item style map] command. See the user * documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyle_Remap( TreeCtrl *tree, /* Widget info. */ TreeStyle styleFrom_, /* Current instance style. */ TreeStyle styleTo_, /* Master style to "convert" the current * style to. */ int objc, /* Must be even number. */ Tcl_Obj *CONST objv[] /* Array of old-new element names. */ ) { IStyle *styleFrom = (IStyle *) styleFrom_; MStyle *styleTo = (MStyle *) styleTo_; int i, indexFrom, indexTo; int staticMap[STATIC_SIZE], *map = staticMap; IElementLink *eLink; Element *elemFrom, *elemTo; Element *staticElemMap[STATIC_SIZE], **elemMap = staticElemMap; int styleFromNumElements = styleFrom->master->numElements; int result = TCL_OK; /* Must be instance */ if ((styleFrom == NULL) || (styleFrom->master == NULL)) return TCL_ERROR; /* Must be master */ if ((styleTo == NULL) || (styleTo->master != NULL)) return TCL_ERROR; /* Nothing to do */ if (styleFrom->master == styleTo) return TCL_OK; if (objc & 1) return TCL_ERROR; STATIC_ALLOC(map, int, styleFromNumElements); STATIC_ALLOC(elemMap, Element *, styleFromNumElements); for (i = 0; i < styleFromNumElements; i++) map[i] = -1; for (i = 0; i < objc; i += 2) { /* Get the old-style element */ if (Element_FromObj(tree, objv[i], &elemFrom) != TCL_OK) { result = TCL_ERROR; goto done; } /* Verify the old style uses the element */ if (MStyle_FindElem(tree, styleFrom->master, elemFrom, &indexFrom) == NULL) { FormatResult(tree->interp, "style %s does not use element %s", styleFrom->master->name, elemFrom->name); result = TCL_ERROR; goto done; } /* Get the new-style element */ if (Element_FromObj(tree, objv[i + 1], &elemTo) != TCL_OK) { result = TCL_ERROR; goto done; } /* Verify the new style uses the element */ if (MStyle_FindElem(tree, styleTo, elemTo, &indexTo) == NULL) { FormatResult(tree->interp, "style %s does not use element %s", styleTo->name, elemTo->name); result = TCL_ERROR; goto done; } /* Must be the same type */ if (elemFrom->typePtr != elemTo->typePtr) { FormatResult(tree->interp, "can't map element type %s to %s", elemFrom->typePtr->name, elemTo->typePtr->name); result = TCL_ERROR; goto done; } /* See if the instance style has any info for this element */ eLink = &styleFrom->elements[indexFrom]; if (eLink->elem->master != NULL) { map[indexFrom] = indexTo; elemMap[indexFrom] = eLink->elem; } } for (i = 0; i < styleFromNumElements; i++) { eLink = &styleFrom->elements[i]; indexTo = map[i]; /* Free info for any Elements not being remapped */ if ((indexTo == -1) && (eLink->elem->master != NULL)) { elemFrom = eLink->elem->master; Element_FreeResources(tree, eLink->elem); eLink->elem = elemFrom; } /* Remap this Element */ if (indexTo != -1) { elemMap[i]->master = styleTo->elements[indexTo].elem; elemMap[i]->name = styleTo->elements[indexTo].elem->name; } } if (styleFromNumElements != styleTo->numElements) { #ifdef ALLOC_HAX if (styleFromNumElements > 0) AllocHax_CFree(tree->allocData, IElementLinkUid, (char *) styleFrom->elements, sizeof(IElementLink), styleFromNumElements, ELEMENT_LINK_ROUND); styleFrom->elements = (IElementLink *) AllocHax_CAlloc(tree->allocData, IElementLinkUid, sizeof(IElementLink), styleTo->numElements, ELEMENT_LINK_ROUND); #else if (styleFromNumElements > 0) WCFREE(styleFrom->elements, IElementLink, styleFromNumElements); styleFrom->elements = (IElementLink *) ckalloc(sizeof(IElementLink) * styleTo->numElements); #endif memset(styleFrom->elements, '\0', sizeof(IElementLink) * styleTo->numElements); } for (i = 0; i < styleTo->numElements; i++) { styleFrom->elements[i].elem = styleTo->elements[i].elem; #ifdef CACHE_ELEM_SIZE styleFrom->elements[i].neededWidth = -1; styleFrom->elements[i].neededHeight = -1; #endif } for (i = 0; i < styleFromNumElements; i++) { indexTo = map[i]; if (indexTo != -1) styleFrom->elements[indexTo].elem = elemMap[i]; } styleFrom->master = styleTo; styleFrom->neededWidth = styleFrom->neededHeight = -1; done: STATIC_FREE(map, int, styleFromNumElements); STATIC_FREE(elemMap, Element *, styleFromNumElements); return result; } /* *---------------------------------------------------------------------- * * TreeStyle_GetSortData -- * * Called by the [item sort] code. Returns a long, double or * string value from a text element. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_GetSortData( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* The style. */ int elemIndex, /* Index of a text element, or -1 to use * the first text element. */ int type, /* SORT_xxx constant. */ long *lv, /* Returned for SORT_LONG. */ double *dv, /* Returned for SORT_DOUBLE. */ char **sv /* Returned for SORT_ASCII or SORT_DICT. */ ) { IStyle *style = (IStyle *) style_; IElementLink *eLink = style->elements; int i; if (elemIndex == -1) { for (i = 0; i < style->master->numElements; i++) { if (ELEMENT_TYPE_MATCHES(eLink->elem->typePtr, &elemTypeText)) return Element_GetSortData(tree, eLink->elem, type, lv, dv, sv); eLink++; } } else { if ((elemIndex < 0) || (elemIndex >= style->master->numElements)) panic("bad elemIndex %d to TreeStyle_GetSortData", elemIndex); eLink = &style->elements[elemIndex]; if (ELEMENT_TYPE_MATCHES(eLink->elem->typePtr, &elemTypeText)) return Element_GetSortData(tree, eLink->elem, type, lv, dv, sv); } FormatResult(tree->interp, "can't find text element in style %s", style->master->name); return TCL_ERROR; } #if 0 /* *---------------------------------------------------------------------- * * TreeStyle_ValidateElements -- * * Verify that each object in an objv[] array refers to a * master element. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_ValidateElements( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Instance style. */ int objc, /* Number of element names. */ Tcl_Obj *CONST objv[] /* Array of element names. */ ) { IStyle *style = (IStyle *) style_; MStyle *master = style->master; Element *elem; MElementLink *eLink; int i; for (i = 0; i < objc; i++) { if (Element_FromObj(tree, objv[i], &elem) != TCL_OK) return TCL_ERROR; eLink = MStyle_FindElem(tree, master, elem, NULL); if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", master->name, elem->name); return TCL_ERROR; } } return TCL_OK; } #endif /* 0 */ /* *---------------------------------------------------------------------- * * TreeStyle_GetElemRects -- * * Return a list of rectangles for specified elements in a style. * * Results: * The number of rects[] written. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_GetElemRects( StyleDrawArgs *drawArgs, /* Various args. */ int objc, /* Number of element names. */ Tcl_Obj *CONST objv[], /* Array of element names. */ XRectangle rects[] /* Returned rectangles. */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *master = style->master; int i, j, count = 0, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; Element *staticElems[STATIC_SIZE], **elems = staticElems; MElementLink *eLink; STATIC_ALLOC(elems, Element *, objc); for (j = 0; j < objc; j++) { if (Element_FromObj(drawArgs->tree, objv[j], &elems[j]) != TCL_OK) { count = -1; goto done; } eLink = MStyle_FindElem(drawArgs->tree, master, elems[j], NULL); if (eLink == NULL) { FormatResult(drawArgs->tree->interp, "style %s does not use element %s", master->name, elems[j]->name); count = -1; goto done; } } #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else Style_MinSize(drawArgs->tree, style, drawArgs->state, &minWidth, &minHeight); #endif if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; STATIC_ALLOC(layouts, struct Layout, master->numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); for (i = master->numElements - 1; i >= 0; i--) { struct Layout *layout = &layouts[i]; if (objc > 0) { for (j = 0; j < objc; j++) if (elems[j] == layout->eLink->elem || elems[j] == layout->master->elem) break; if (j == objc) continue; } rects[count].x = drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT]; rects[count].y = drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT]; if (layout->master->onion == NULL) { rects[count].x += layout->iPadX[PAD_TOP_LEFT]; rects[count].y += layout->iPadY[PAD_TOP_LEFT]; rects[count].width = layout->useWidth; rects[count].height = layout->useHeight; } else { rects[count].width = layout->iWidth; rects[count].height = layout->iHeight; } count++; } STATIC_FREE(layouts, struct Layout, master->numElements); done: STATIC_FREE(elems, Element *, objc); return count; } /* *---------------------------------------------------------------------- * * TreeStyle_ChangeState -- * * Called when the state of an item or item-column changes. * * Results: * A bitmask of CS_DISPLAY and CS_LAYOUT values. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_ChangeState( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* This instance style. */ int state1, /* The previous state. */ int state2 /* The current state. */ ) { IStyle *style = (IStyle *) style_; IElementLink *eLink; ElementArgs args; int i, eMask, mask = 0; if (state1 == state2) return 0; args.tree = tree; args.states.state1 = state1; args.states.state2 = state2; for (i = 0; i < style->master->numElements; i++) { eLink = &style->elements[i]; args.elem = eLink->elem; eMask = (*eLink->elem->typePtr->stateProc)(&args); if (eMask) { #ifdef CACHE_ELEM_SIZE if (eMask & CS_LAYOUT) eLink->neededWidth = eLink->neededHeight = -1; #endif mask |= eMask; } } if (mask & CS_LAYOUT) style->neededWidth = style->neededHeight = -1; #ifdef TREECTRL_DEBUG if (style->neededWidth != -1) style->neededState = state2; #endif return mask; } /* *---------------------------------------------------------------------- * * Tree_UndefineState -- * * The guts of the [state undefine] widget command. * * Results: * The undefProc of every element is called to respond to the * undefined state flag. The size of every element/column/item is * marked out-of-date regardless of whether the state change * affected the element. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void Tree_UndefineState( TreeCtrl *tree, /* Widget info. */ int state /* STATE_xxx flag. */ ) { TreeItem item; TreeItemColumn column; Tcl_HashEntry *hPtr; Tcl_HashSearch search; IElementLink *eLink; int i, columnIndex; ElementArgs args; args.tree = tree; args.state = state; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; while (column != NULL) { IStyle *style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if (style != NULL) { for (i = 0; i < style->master->numElements; i++) { eLink = &style->elements[i]; /* Instance element */ if (eLink->elem->master != NULL) { args.elem = eLink->elem; (*args.elem->typePtr->undefProc)(&args); } #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif } style->neededWidth = style->neededHeight = -1; TreeItemColumn_InvalidateSize(tree, column); } columnIndex++; column = TreeItemColumn_GetNext(tree, column); } TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); TreeItem_UndefineState(tree, item, state); hPtr = Tcl_NextHashEntry(&search); } Tree_InvalidateColumnWidth(tree, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); hPtr = Tcl_FirstHashEntry(&tree->elementHash, &search); while (hPtr != NULL) { args.elem = (Element *) Tcl_GetHashValue(hPtr); (*args.elem->typePtr->undefProc)(&args); hPtr = Tcl_NextHashEntry(&search); } } /* *---------------------------------------------------------------------- * * TreeStyle_NumElements -- * * Return the number of elements in a style. * * Results: * The number of... oh nevermind. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_NumElements( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* The style. */ ) { MStyle *masterStyle = ((MStyle *) style_); IStyle *style = ((IStyle *) style_); return (style->master == NULL) ? masterStyle->numElements : style->master->numElements; } /* *---------------------------------------------------------------------- * * TreeStyle_Init -- * * Style-related package initialization. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_Init( TreeCtrl *tree /* Widget info. */ ) { tree->styleOptionTable = Tk_CreateOptionTable(tree->interp, styleOptionSpecs); return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeStyle_Free -- * * Free style-related resources for a deleted TreeCtrl. * * Results: * None. * * Side effects: * Memory is freed. * *---------------------------------------------------------------------- */ void TreeStyle_Free( TreeCtrl *tree /* Widget info. */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; Element *elem; TreeStyle style; while (1) { hPtr = Tcl_FirstHashEntry(&tree->styleHash, &search); if (hPtr == NULL) break; style = (TreeStyle) Tcl_GetHashValue(hPtr); TreeStyle_FreeResources(tree, style); } while (1) { hPtr = Tcl_FirstHashEntry(&tree->elementHash, &search); if (hPtr == NULL) break; elem = (Element *) Tcl_GetHashValue(hPtr); Element_FreeResources(tree, elem); } Tcl_DeleteHashTable(&tree->elementHash); Tcl_DeleteHashTable(&tree->styleHash); } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/qebind.c0000644000175000017500000017635111044115430024107 0ustar domibeldomibel/* * qebind.c -- * * This module implements quasi-events. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: qebind.c,v 1.3 2008-07-30 16:47:20 barre Exp $ */ /* * A general purpose module that allows a program to send event-like * messages to scripts, and to bind Tcl commands to those quasi-events. * Each event has it's own detail field and other fields, and this * module performs %-substitution on bound scripts just like regular * Tk binding model. * * To use it first call QE_BindInit() to initialize the package. * Then call QE_InstallEvent() for each new event you wish to define. * For events with details, call QE_InstallDetail() to register each * detail associated with a specific event type. Then create a * binding table, which records all binding commands defined by your * scripts, with QE_CreateBindingTable(). QE_BindCmd() is * called to associate a Tcl script with a given event for a particular * object. The objects that commands are bound to can be a Tk widget or any * string, just like the usual "bind" command. Bindings are not automatically * deleted when a widget is destroyed. */ #include "vtkTcl.h" #include "vtkTk.h" #include #include #include #include #include "qebind.h" #ifdef HAVE_DBWIN_H #include "dbwin.h" #else /* HAVE_DBWIN_H */ #define dbwin printf #endif /* HAVE_DBWIN_H */ /* * The macro below is used to modify a "char" value (e.g. by casting * it to an unsigned character) so that it can be used safely with * macros such as isspace. */ #define UCHAR(c) ((unsigned char) (c)) int debug_bindings = 0; /* * Allow bindings to be deactivated. */ #define BIND_ACTIVE 1 /* * Allow new events to be added/removed by Tcl commands. */ #define ALLOW_INSTALL 1 /* * Delete scripts bound to a window when that window is destroyed. */ #define DELETE_WIN_BINDINGS 1 typedef struct BindValue { int type; /* Type of event, etc) */ int detail; /* Misc. other information, or 0 for none */ ClientData object; char *command; int specific; /* For less-specific events (detail=0), this is 1 * if a more-specific event (detail>0) exists. */ struct BindValue *nextValue; /* list of BindValues matching event */ #if BIND_ACTIVE int active; /* 1 if binding is "active", 0 otherwise */ #endif /* BIND_ACTIVE */ } BindValue; typedef struct Pattern { int type; /* Type of event */ int detail; /* Misc. other information, or 0 for none */ } Pattern; typedef struct PatternTableKey { int type; /* Type of event */ int detail; /* Misc. other information, or 0 for none */ } PatternTableKey; typedef struct ObjectTableKey { int type; /* Type of event */ int detail; /* Misc. other information, or 0 for none */ ClientData object; /* Object info */ } ObjectTableKey; typedef struct Detail { Tk_Uid name; /* Name of detail */ int code; /* Detail code */ struct EventInfo *event; /* Associated event */ QE_ExpandProc expandProc; /* Callback to expand % in scripts */ #if ALLOW_INSTALL int dynamic; /* Created by QE_InstallCmd() */ char *command; /* Tcl command to expand percents, or NULL */ #endif struct Detail *next; /* List of Details for event */ } Detail; typedef struct EventInfo { char *name; /* Name of event */ int type; /* Type of event */ QE_ExpandProc expandProc; /* Callback to expand % in scripts */ Detail *detailList; /* List of Details */ int nextDetailId; /* Next unique Detail.code */ #if ALLOW_INSTALL int dynamic; /* Created by QE_InstallCmd() */ char *command; /* Tcl command to expand percents, or NULL */ #endif struct EventInfo *next; /* List of all EventInfos */ } EventInfo; typedef struct GenerateField { char which; /* The %-char */ char *string; /* Replace %-char with it */ } GenerateField; typedef struct GenerateData { GenerateField staticField[20]; GenerateField *field; int count; char *command; /* Tcl command to expand percents, or NULL */ } GenerateData; typedef struct BindingTable { Tcl_Interp *interp; Tcl_HashTable patternTable; /* Key: PatternTableKey, Value: (BindValue *) */ Tcl_HashTable objectTable; /* Key: ObjectTableKey, Value: (BindValue *) */ Tcl_HashTable eventTableByName; /* Key: string, Value: EventInfo */ Tcl_HashTable eventTableByType; /* Key: int, Value: EventInfo */ Tcl_HashTable detailTableByType; /* Key: PatternTableKey, Value: Detail */ #if DELETE_WIN_BINDINGS Tcl_HashTable winTable; /* Key: Tk_Uid of window name, Value: WinTableValue */ #endif EventInfo *eventList; /* List of all EventInfos */ int nextEventId; /* Next unique EventInfo.type */ } BindingTable; static void ExpandPercents(BindingTable *bindPtr, ClientData object, char *command, QE_Event *eventPtr, QE_ExpandProc expandProc, Tcl_DString *result); static int ParseEventDescription(BindingTable *bindPtr, char *eventPattern, Pattern *patPtr, EventInfo **eventInfoPtr, Detail **detailPtr); static int FindSequence(BindingTable *bindPtr, ClientData object, char *eventString, int create, int *created, BindValue **result); static void Percents_CharMap(QE_ExpandArgs *args); static void Percents_Command(QE_ExpandArgs *args); #if ALLOW_INSTALL typedef struct PercentsData { GenerateData *gdPtr; char *command; EventInfo *eventPtr; Detail *detailPtr; } PercentsData; #endif static int DeleteBinding(BindingTable *bindPtr, BindValue *valuePtr); static EventInfo *FindEvent(BindingTable *bindPtr, int eventType); static int initialized = 0; int QE_BindInit(Tcl_Interp *interp) { if (initialized) return TCL_OK; initialized = 1; return TCL_OK; } static int CheckName(char *name) { char *p = name; if (*p == '\0') return TCL_ERROR; while ((*p != '\0') && (*p != '-') && !isspace(UCHAR(*p))) p++; if (*p == '\0') return TCL_OK; return TCL_ERROR; } int QE_InstallEvent(QE_BindingTable bindingTable, char *name, QE_ExpandProc expandProc) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; EventInfo *eiPtr; int isNew; int type; if (CheckName(name) != TCL_OK) { Tcl_AppendResult(bindPtr->interp, "bad event name \"", name, "\"", (char *) NULL); return 0; } hPtr = Tcl_CreateHashEntry(&bindPtr->eventTableByName, name, &isNew); if (!isNew) { Tcl_AppendResult(bindPtr->interp, "event \"", name, "\" already exists", NULL); return 0; } type = bindPtr->nextEventId++; eiPtr = (EventInfo *) Tcl_Alloc(sizeof(EventInfo)); eiPtr->name = Tcl_Alloc((int)strlen(name) + 1); strcpy(eiPtr->name, name); eiPtr->type = type; eiPtr->expandProc = expandProc; eiPtr->detailList = NULL; eiPtr->nextDetailId = 1; #ifdef ALLOW_INSTALL eiPtr->dynamic = 0; eiPtr->command = NULL; #endif Tcl_SetHashValue(hPtr, (ClientData) eiPtr); hPtr = Tcl_CreateHashEntry(&bindPtr->eventTableByType, (char *) type, &isNew); Tcl_SetHashValue(hPtr, (ClientData) eiPtr); /* List of EventInfos */ eiPtr->next = bindPtr->eventList; bindPtr->eventList = eiPtr; return type; } int QE_InstallDetail(QE_BindingTable bindingTable, char *name, int eventType, QE_ExpandProc expandProc) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Detail *dPtr; EventInfo *eiPtr; PatternTableKey key; int isNew; int code; if (CheckName(name) != TCL_OK) { Tcl_AppendResult(bindPtr->interp, "bad detail name \"", name, "\"", (char *) NULL); return 0; } /* Find the event this detail goes with */ eiPtr = FindEvent(bindPtr, eventType); if (eiPtr == NULL) return 0; /* Verify the detail is not already defined for this event */ for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, name) == 0) { Tcl_AppendResult(bindPtr->interp, "detail \"", name, "\" already exists for event \"", eiPtr->name, "\"", NULL); return 0; } } code = eiPtr->nextDetailId++; /* New Detail for detailTable */ dPtr = (Detail *) Tcl_Alloc(sizeof(Detail)); dPtr->name = Tk_GetUid(name); dPtr->code = code; dPtr->event = eiPtr; dPtr->expandProc = expandProc; #if ALLOW_INSTALL dPtr->dynamic = 0; dPtr->command = NULL; #endif /* Entry to find detail by event type and detail code */ key.type = eventType; key.detail = code; hPtr = Tcl_CreateHashEntry(&bindPtr->detailTableByType, (char *) &key, &isNew); Tcl_SetHashValue(hPtr, (ClientData) dPtr); /* List of Details */ dPtr->next = eiPtr->detailList; eiPtr->detailList = dPtr; return code; } static void DeleteEvent(BindingTable *bindPtr, EventInfo *eiPtr) { EventInfo *eiPrev; Detail *dPtr, *dNext; /* Free Details */ for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dNext) { dNext = dPtr->next; #ifdef ALLOW_INSTALL if (dPtr->command != NULL) Tcl_Free(dPtr->command); #endif memset((char *) dPtr, 0xAA, sizeof(Detail)); Tcl_Free((char *) dPtr); } if (bindPtr->eventList == eiPtr) bindPtr->eventList = eiPtr->next; else { for (eiPrev = bindPtr->eventList; eiPrev->next != eiPtr; eiPrev = eiPrev->next) { } eiPrev->next = eiPtr->next; } /* Free EventInfo */ Tcl_Free(eiPtr->name); #ifdef ALLOW_INSTALL if (eiPtr->command != NULL) Tcl_Free(eiPtr->command); #endif memset((char *) eiPtr, 0xAA, sizeof(EventInfo)); Tcl_Free((char *) eiPtr); } int QE_UninstallEvent(QE_BindingTable bindingTable, int eventType) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Tcl_HashSearch search; EventInfo *eiPtr; BindValue *valuePtr, **valueList; Tcl_DString dString; int i, count = 0; /* Find the event */ hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByType, (char *) eventType); if (hPtr == NULL) return TCL_ERROR; eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); Tcl_DeleteHashEntry(hPtr); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eiPtr->name); Tcl_DeleteHashEntry(hPtr); Tcl_DStringInit(&dString); /* Find all bindings to this event for any object */ hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { if (valuePtr->type == eiPtr->type) { Tcl_DStringAppend(&dString, (char *) &valuePtr, sizeof(valuePtr)); count++; } valuePtr = valuePtr->nextValue; } hPtr = Tcl_NextHashEntry(&search); } valueList = (BindValue **) Tcl_DStringValue(&dString); for (i = 0; i < count; i++) DeleteBinding(bindPtr, valueList[i]); Tcl_DStringFree(&dString); DeleteEvent(bindPtr, eiPtr); return TCL_OK; } int QE_UninstallDetail(QE_BindingTable bindingTable, int eventType, int detail) { BindingTable *bindPtr = (BindingTable *) bindingTable; PatternTableKey key; Tcl_HashEntry *hPtr; Detail *dPtr = NULL, *dPrev; EventInfo *eiPtr; /* Find the event */ eiPtr = FindEvent(bindPtr, eventType); if (eiPtr == NULL) return TCL_ERROR; if (eiPtr->detailList == NULL) return TCL_ERROR; /* Delete all bindings on this event/detail for all objects */ while (1) { key.type = eventType; key.detail = detail; hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); if (hPtr == NULL) break; DeleteBinding(bindPtr, (BindValue *) Tcl_GetHashValue(hPtr)); } if (eiPtr->detailList->code == detail) { dPtr = eiPtr->detailList; eiPtr->detailList = eiPtr->detailList->next; } else { for (dPrev = eiPtr->detailList; dPrev != NULL; dPrev = dPrev->next) { if ((dPrev->next != NULL) && (dPrev->next->code == detail)) { dPtr = dPrev->next; dPrev->next = dPtr->next; break; } } if (dPtr == NULL) return TCL_ERROR; } #ifdef ALLOW_INSTALL if (dPtr->command != NULL) Tcl_Free(dPtr->command); #endif memset((char *) dPtr, 0xAA, sizeof(Detail)); Tcl_Free((char *) dPtr); key.type = eventType; key.detail = detail; hPtr = Tcl_FindHashEntry(&bindPtr->detailTableByType, (char *) &key); Tcl_DeleteHashEntry(hPtr); return TCL_OK; } static EventInfo *FindEvent(BindingTable *bindPtr, int eventType) { Tcl_HashEntry *hPtr; hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByType, (char *) eventType); if (hPtr == NULL) return NULL; return (EventInfo *) Tcl_GetHashValue(hPtr); } static Detail *FindDetail(BindingTable *bindPtr, int eventType, int code) { PatternTableKey key; Tcl_HashEntry *hPtr; key.type = eventType; key.detail = code; hPtr = Tcl_FindHashEntry(&bindPtr->detailTableByType, (char *) &key); if (hPtr == NULL) return NULL; return (Detail *) Tcl_GetHashValue(hPtr); } #if DELETE_WIN_BINDINGS typedef struct WinTableValue { BindingTable *bindPtr; ClientData object; Tk_Window tkwin; int count; /* Number of BindValues on object */ } WinTableValue; static void TkWinEventProc(ClientData clientData, XEvent *eventPtr) { WinTableValue *cd = (WinTableValue *) clientData; BindingTable *bindPtr = cd->bindPtr; ClientData object = cd->object; if (eventPtr->type != DestroyNotify) return; QE_DeleteBinding((QE_BindingTable) bindPtr, object, NULL); } #endif QE_BindingTable QE_CreateBindingTable(Tcl_Interp *interp) { BindingTable *bindPtr; bindPtr = (BindingTable *) Tcl_Alloc(sizeof(BindingTable)); bindPtr->interp = interp; Tcl_InitHashTable(&bindPtr->patternTable, sizeof(PatternTableKey) / sizeof(int)); Tcl_InitHashTable(&bindPtr->objectTable, sizeof(ObjectTableKey) / sizeof(int)); Tcl_InitHashTable(&bindPtr->eventTableByName, TCL_STRING_KEYS); Tcl_InitHashTable(&bindPtr->eventTableByType, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&bindPtr->detailTableByType, sizeof(PatternTableKey) / sizeof(int)); #if DELETE_WIN_BINDINGS Tcl_InitHashTable(&bindPtr->winTable, TCL_ONE_WORD_KEYS); #endif bindPtr->nextEventId = 1; bindPtr->eventList = NULL; return (QE_BindingTable) bindPtr; } void QE_DeleteBindingTable(QE_BindingTable bindingTable) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Tcl_HashSearch search; EventInfo *eiPtr, *eiNext; Detail *dPtr, *dNext; hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { BindValue *valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { BindValue *nextValue = valuePtr->nextValue; Tcl_Free((char *) valuePtr->command); memset((char *) valuePtr, 0xAA, sizeof(BindValue)); Tcl_Free((char *) valuePtr); valuePtr = nextValue; } hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&bindPtr->patternTable); Tcl_DeleteHashTable(&bindPtr->objectTable); for (eiPtr = bindPtr->eventList; eiPtr != NULL; eiPtr = eiNext) { eiNext = eiPtr->next; /* Free Detail */ for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dNext) { dNext = dPtr->next; #ifdef ALLOW_INSTALL if (dPtr->command != NULL) Tcl_Free(dPtr->command); #endif memset((char *) dPtr, 0xAA, sizeof(Detail)); Tcl_Free((char *) dPtr); } /* Free EventInfo */ Tcl_Free(eiPtr->name); #ifdef ALLOW_INSTALL if (eiPtr->command != NULL) Tcl_Free(eiPtr->command); #endif memset((char *) eiPtr, 0xAA, sizeof(EventInfo)); Tcl_Free((char *) eiPtr); } Tcl_DeleteHashTable(&bindPtr->eventTableByName); Tcl_DeleteHashTable(&bindPtr->eventTableByType); Tcl_DeleteHashTable(&bindPtr->detailTableByType); #if DELETE_WIN_BINDINGS hPtr = Tcl_FirstHashEntry(&bindPtr->winTable, &search); while (hPtr != NULL) { WinTableValue *cd = (WinTableValue *) Tcl_GetHashValue(hPtr); Tk_DeleteEventHandler(cd->tkwin, StructureNotifyMask, TkWinEventProc, (ClientData) cd); Tcl_Free((char *) cd); hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&bindPtr->winTable); #endif memset((char *) bindPtr, 0xAA, sizeof(BindingTable)); Tcl_Free((char *) bindPtr); } int QE_CreateBinding(QE_BindingTable bindingTable, ClientData object, char *eventString, char *command, int append) { BindingTable *bindPtr = (BindingTable *) bindingTable; BindValue *valuePtr; int isNew, length; char *cmdOld, *cmdNew; if (FindSequence(bindPtr, object, eventString, 1, &isNew, &valuePtr) != TCL_OK) return TCL_ERROR; /* created a new objectTable entry */ if (isNew) { Tcl_HashEntry *hPtr; PatternTableKey key; #if DELETE_WIN_BINDINGS char *winName = (char *) object; if (winName[0] == '.') { Tk_Window tkwin = Tk_MainWindow(bindPtr->interp); Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(bindPtr->interp, winName, tkwin); if (tkwin2 != NULL) { WinTableValue *cd; hPtr = Tcl_CreateHashEntry(&bindPtr->winTable, object, &isNew); if (isNew) { cd = (WinTableValue *) Tcl_Alloc(sizeof(WinTableValue)); cd->bindPtr = bindPtr; cd->object = object; cd->tkwin = tkwin2; cd->count = 0; Tk_CreateEventHandler(tkwin2, StructureNotifyMask, TkWinEventProc, (ClientData) cd); Tcl_SetHashValue(hPtr, (ClientData) cd); } else { cd = (WinTableValue *) Tcl_GetHashValue(hPtr); } /* Number of BindValues for this window */ cd->count++; } } #endif key.type = valuePtr->type; key.detail = valuePtr->detail; hPtr = Tcl_CreateHashEntry(&bindPtr->patternTable, (char *) &key, &isNew); /* * A patternTable entry exists for each different type/detail. * The entry points to a BindValue which is the head of the list * of BindValue's with this same type/detail, but for different * objects. */ if (!isNew) { valuePtr->nextValue = (BindValue *) Tcl_GetHashValue(hPtr); } Tcl_SetHashValue(hPtr, (ClientData) valuePtr); } cmdOld = valuePtr->command; /* Append given command to any existing command */ if (append && cmdOld) { length = (int)strlen(cmdOld) + (int)strlen(command) + 2; cmdNew = Tcl_Alloc((unsigned) length); (void) sprintf(cmdNew, "%s\n%s", cmdOld, command); } /* Copy the given command */ else { cmdNew = (char *) Tcl_Alloc((unsigned) strlen(command) + 1); (void) strcpy(cmdNew, command); } /* Free the old command, if any */ if (cmdOld) Tcl_Free(cmdOld); /* Save command associated with this binding */ valuePtr->command = cmdNew; return TCL_OK; } int QE_DeleteBinding(QE_BindingTable bindingTable, ClientData object, char *eventString) { BindingTable *bindPtr = (BindingTable *) bindingTable; BindValue *valuePtr, **valueList; /* Delete all bindings on this object */ if (eventString == NULL) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_DString dString; int i, count = 0; Tcl_DStringInit(&dString); hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { if (valuePtr->object == object) { Tcl_DStringAppend(&dString, (char *) &valuePtr, sizeof(valuePtr)); count++; break; } valuePtr = valuePtr->nextValue; } hPtr = Tcl_NextHashEntry(&search); } valueList = (BindValue **) Tcl_DStringValue(&dString); for (i = 0; i < count; i++) DeleteBinding(bindPtr, valueList[i]); Tcl_DStringFree(&dString); return TCL_OK; } if (FindSequence(bindPtr, object, eventString, 0, NULL, &valuePtr) != TCL_OK) return TCL_ERROR; if (valuePtr == NULL) { Tcl_ResetResult(bindPtr->interp); return TCL_OK; } DeleteBinding(bindPtr, valuePtr); return TCL_OK; } static int DeleteBinding(BindingTable *bindPtr, BindValue *valuePtr) { Tcl_HashEntry *hPtr; BindValue *listPtr; ObjectTableKey keyObj; PatternTableKey keyPat; /* Delete the objectTable entry */ keyObj.type = valuePtr->type; keyObj.detail = valuePtr->detail; keyObj.object = valuePtr->object; hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) &keyObj); if (hPtr == NULL) return TCL_ERROR; /* fatal error */ Tcl_DeleteHashEntry(hPtr); /* Find the patternTable entry for this type/detail */ keyPat.type = valuePtr->type; keyPat.detail = valuePtr->detail; hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &keyPat); if (hPtr == NULL) return TCL_ERROR; /* fatal error */ /* * Get the patternTable value. This is the head of a list of * BindValue's that match the type/detail, but for different * objects; */ listPtr = (BindValue *) Tcl_GetHashValue(hPtr); /* The deleted BindValue is the first */ if (listPtr == valuePtr) { /* The deleted BindValue was the only one in the list */ if (valuePtr->nextValue == NULL) { if (debug_bindings) dbwin("QE_DeleteBinding: Deleted pattern type=%d detail=%d\n", valuePtr->type, valuePtr->detail); Tcl_DeleteHashEntry(hPtr); } /* The next BindValue is the new head of the list */ else { Tcl_SetHashValue(hPtr, valuePtr->nextValue); } } /* Look for the deleted BindValue in the list, and remove it */ else { while (1) { if (listPtr->nextValue == NULL) return TCL_ERROR; /* fatal */ if (listPtr->nextValue == valuePtr) { if (debug_bindings) dbwin("QE_DeleteBinding: Unlinked binding type=%d detail=%d\n", valuePtr->type, valuePtr->detail); listPtr->nextValue = valuePtr->nextValue; break; } listPtr = listPtr->nextValue; } } #if DELETE_WIN_BINDINGS { char *winName = (char *) valuePtr->object; if (winName[0] == '.') { WinTableValue *cd; hPtr = Tcl_FindHashEntry(&bindPtr->winTable, winName); if (hPtr == NULL) return TCL_ERROR; /* fatal error */ cd = (WinTableValue *) Tcl_GetHashValue(hPtr); cd->count--; if (cd->count == 0) { Tk_DeleteEventHandler(cd->tkwin, StructureNotifyMask, TkWinEventProc, (ClientData) cd); Tcl_Free((char *) cd); Tcl_DeleteHashEntry(hPtr); } } } #endif Tcl_Free((char *) valuePtr->command); memset((char *) valuePtr, 0xAA, sizeof(BindValue)); Tcl_Free((char *) valuePtr); return TCL_OK; } int QE_GetAllObjects(QE_BindingTable bindingTable) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_DString dString; ClientData *objectList; int i, count = 0; Tcl_Obj *listObj; Tcl_DStringInit(&dString); hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { BindValue *valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { objectList = (ClientData *) Tcl_DStringValue(&dString); for (i = 0; i < count; i++) { if (objectList[i] == valuePtr->object) break; } if (i >= count) { Tcl_DStringAppend(&dString, (char *) &valuePtr->object, sizeof(ClientData)); count++; } valuePtr = valuePtr->nextValue; } hPtr = Tcl_NextHashEntry(&search); } if (count > 0) { listObj = Tcl_NewListObj(0, NULL); objectList = (ClientData *) Tcl_DStringValue(&dString); for (i = 0; i < count; i++) { Tcl_ListObjAppendElement(bindPtr->interp, listObj, Tcl_NewStringObj((char *) objectList[i], -1)); } Tcl_SetObjResult(bindPtr->interp, listObj); } Tcl_DStringFree(&dString); return TCL_OK; } int QE_GetBinding(QE_BindingTable bindingTable, ClientData object, char *eventString) { BindingTable *bindPtr = (BindingTable *) bindingTable; BindValue *valuePtr; if (FindSequence(bindPtr, object, eventString, 0, NULL, &valuePtr) != TCL_OK) return TCL_ERROR; if (valuePtr == NULL) return TCL_OK; Tcl_SetObjResult(bindPtr->interp, Tcl_NewStringObj(valuePtr->command, -1)); return TCL_OK; } static void GetPatternString(BindingTable *bindPtr, BindValue *bindValue, Tcl_DString *dString) { EventInfo *eiPtr; eiPtr = FindEvent(bindPtr, bindValue->type); if (eiPtr != NULL) { Tcl_DStringAppend(dString, "<", 1); Tcl_DStringAppend(dString, eiPtr->name, -1); if (bindValue->detail) { Detail *detail = FindDetail(bindPtr, bindValue->type, bindValue->detail); if (detail != NULL) { Tcl_DStringAppend(dString, "-", 1); Tcl_DStringAppend(dString, detail->name, -1); } } Tcl_DStringAppend(dString, ">", 1); } } int QE_GetAllBindings(QE_BindingTable bindingTable, ClientData object) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_DString dString; Tcl_DStringInit(&dString); hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { BindValue *valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { if (valuePtr->object == object) { Tcl_DStringSetLength(&dString, 0); GetPatternString(bindPtr, valuePtr, &dString); Tcl_AppendElement(bindPtr->interp, Tcl_DStringValue(&dString)); break; } valuePtr = valuePtr->nextValue; } hPtr = Tcl_NextHashEntry(&search); } Tcl_DStringFree(&dString); return TCL_OK; } int QE_GetEventNames(QE_BindingTable bindingTable) { BindingTable *bindPtr = (BindingTable *) bindingTable; EventInfo *eiPtr; for (eiPtr = bindPtr->eventList; eiPtr != NULL; eiPtr = eiPtr->next) { Tcl_AppendElement(bindPtr->interp, eiPtr->name); } return TCL_OK; } int QE_GetDetailNames(QE_BindingTable bindingTable, char *eventName) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; EventInfo *eiPtr; Detail *dPtr; hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { Tcl_AppendElement(bindPtr->interp, dPtr->name); } return TCL_OK; } static void ExpandPercents(BindingTable *bindPtr, ClientData object, char *command, QE_Event *eventPtr, QE_ExpandProc expandProc, Tcl_DString *result) { char *string; QE_ExpandArgs expandArgs; #if 0 Tcl_DStringSetLength(result, 0); if (debug_bindings) dbwin("ExpandPercents on '%s' name=%s type=%d detail=%d expand=%lu\n", object, eiPtr->name, eiPtr->type, eventPtr->detail, eiPtr->expand); #endif expandArgs.bindingTable = (QE_BindingTable) bindPtr; expandArgs.object = object; expandArgs.event = eventPtr->type; expandArgs.detail = eventPtr->detail; expandArgs.result = result; expandArgs.clientData = eventPtr->clientData; while (1) { for (string = command; (*string != 0) && (*string != '%'); string++) { /* Empty loop body. */ } if (string != command) { Tcl_DStringAppend(result, command, (int)(string - command)); command = string; } if (*command == 0) { break; } /* Expand % here */ expandArgs.which = command[1]; (*expandProc)(&expandArgs); command += 2; } } static void BindEvent(BindingTable *bindPtr, QE_Event *eventPtr, int wantDetail, EventInfo *eiPtr, Detail *dPtr, GenerateData *gdPtr) { Tcl_HashEntry *hPtr; BindValue *valuePtr; ObjectTableKey keyObj; PatternTableKey key; Tcl_DString scripts, savedResult; int code; char *p, *end; char *command = gdPtr ? gdPtr->command : NULL; /* Find the first BindValue for this event */ key.type = eventPtr->type; key.detail = wantDetail ? eventPtr->detail : 0; hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); if (hPtr == NULL) return; /* Collect all scripts, with % expanded, separated by null characters. * Do it this way because anything could happen while evaluating, including * uninstalling events/details, even the interpreter being deleted. */ Tcl_DStringInit(&scripts); for (valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); valuePtr; valuePtr = valuePtr->nextValue) { if (wantDetail && valuePtr->detail) { keyObj.type = key.type; keyObj.detail = 0; keyObj.object = valuePtr->object; hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) &keyObj); if (hPtr != NULL) { BindValue *value2Ptr; value2Ptr = (BindValue *) Tcl_GetHashValue(hPtr); value2Ptr->specific = 1; } } /* * If a binding for a more-specific event exists for this object * and event-type, and this is a binding for a less-specific * event, then skip this binding, since the binding for the * more-specific event was already invoked. */ else if (!wantDetail && valuePtr->specific) { if (debug_bindings) dbwin("QE_BindEvent: Skipping less-specific event type=%d object='%s'\n", valuePtr->type, (char *) valuePtr->object); valuePtr->specific = 0; continue; } #if BIND_ACTIVE /* This binding isn't active */ if (valuePtr->active == 0) continue; #endif /* BIND_ACTIVE */ #if ALLOW_INSTALL if (command == NULL) { if ((dPtr != NULL) && (dPtr->command != NULL)) { command = dPtr->command; } else if (((dPtr == NULL) || ((dPtr != NULL) && (dPtr->expandProc == NULL))) && (eiPtr->command != NULL)) { command = eiPtr->command; } } #endif /* ALLOW_INSTALL */ /* called by QE_GenerateCmd */ if (command != NULL) { PercentsData data; data.gdPtr = gdPtr; data.command = command; data.eventPtr = eiPtr; data.detailPtr = dPtr; eventPtr->clientData = (ClientData) &data; ExpandPercents(bindPtr, valuePtr->object, valuePtr->command, eventPtr, Percents_Command, &scripts); } /* called by QE_GenerateCmd */ else if (gdPtr != NULL) { /* Called QE_GenerateCmd with: * a) a static event and no percentsCommand argument, or * b) a dynamic event with no percentsCommand installed and * no percentsCommand argument */ eventPtr->clientData = (ClientData) gdPtr; ExpandPercents(bindPtr, valuePtr->object, valuePtr->command, eventPtr, Percents_CharMap, &scripts); } else { QE_ExpandProc expandProc = ((dPtr != NULL) && (dPtr->expandProc != NULL)) ? dPtr->expandProc : eiPtr->expandProc; ExpandPercents(bindPtr, valuePtr->object, valuePtr->command, eventPtr, expandProc, &scripts); } /* Separate each script by '\0' */ Tcl_DStringAppend(&scripts, "", 1); Tcl_DStringAppend(&scripts, eiPtr->name, -1); Tcl_DStringAppend(&scripts, "", 1); Tcl_DStringAppend(&scripts, (valuePtr->detail && dPtr) ? dPtr->name : "", -1); Tcl_DStringAppend(&scripts, "", 1); Tcl_DStringAppend(&scripts, valuePtr->object, -1); Tcl_DStringAppend(&scripts, "", 1); } /* Nothing to do. No need to call Tcl_DStringFree(&scripts) */ if (Tcl_DStringLength(&scripts) == 0) return; /* * As in Tk bindings, we expect that bindings may be invoked * in the middle of Tcl commands. So we preserve the current * interpreter result and restore it later. */ Tcl_DStringInit(&savedResult); Tcl_DStringGetResult(bindPtr->interp, &savedResult); p = Tcl_DStringValue(&scripts); end = p + Tcl_DStringLength(&scripts); while (p < end) { code = Tcl_GlobalEval(bindPtr->interp, p); p += strlen(p); p++; if (code != TCL_OK) { if (code == TCL_CONTINUE) { /* Nothing */ } else if (code == TCL_BREAK) { /* Nothing */ } else { char buf[256]; char *eventName = p; char *detailName = p + strlen(p) + 1; char *object = detailName + strlen(detailName) + 1; (void) sprintf(buf, "\n (<%s%s%s> binding on %s)", eventName, detailName[0] ? "-" : "", detailName, object); Tcl_AddErrorInfo(bindPtr->interp, buf); Tcl_BackgroundError(bindPtr->interp); } } /* Skip event\0detail\0object\0 */ p += strlen(p); p++; p += strlen(p); p++; p += strlen(p); p++; } Tcl_DStringFree(&scripts); /* Restore the interpreter result */ Tcl_DStringResult(bindPtr->interp, &savedResult); } static int BindEventWrapper(QE_BindingTable bindingTable, QE_Event *eventPtr, GenerateData *gdPtr) { BindingTable *bindPtr = (BindingTable *) bindingTable; Detail *dPtr = NULL; EventInfo *eiPtr; /* Find the event */ eiPtr = FindEvent(bindPtr, eventPtr->type); if (eiPtr == NULL) return TCL_OK; /* Find the detail */ if (eventPtr->detail) { dPtr = FindDetail(bindPtr, eventPtr->type, eventPtr->detail); if (dPtr == NULL) return TCL_OK; } BindEvent(bindPtr, eventPtr, 1, eiPtr, dPtr, gdPtr); if (eventPtr->detail) BindEvent(bindPtr, eventPtr, 0, eiPtr, dPtr, gdPtr); return TCL_OK; } int QE_BindEvent(QE_BindingTable bindingTable, QE_Event *eventPtr) { return BindEventWrapper(bindingTable, eventPtr, NULL); } static char *GetField(char *p, char *copy, int size) { int ch = *p; while ((ch != '\0') && !isspace(UCHAR(ch)) && ((ch != '>') || (p[1] != '\0')) && (ch != '-') && (size > 1)) { *copy = ch; p++; copy++; size--; ch = *p; } *copy = '\0'; while ((*p == '-') || isspace(UCHAR(*p))) { p++; } return p; } #define FIELD_SIZE 48 static int ParseEventDescription1(BindingTable *bindPtr, char *pattern, char eventName[FIELD_SIZE], char detailName[FIELD_SIZE]) { Tcl_Interp *interp = bindPtr->interp; char *p = pattern; eventName[0] = detailName[0] = '\0'; /* First char must by opening < */ if (*p != '<') { Tcl_AppendResult(interp, "missing \"<\" in event pattern \"", pattern, "\"", (char *) NULL); return TCL_ERROR; } p++; /* Event name (required)*/ p = GetField(p, eventName, FIELD_SIZE); if (debug_bindings) dbwin("GetField='%s'\n", eventName); /* Terminating > */ if (*p == '>') return TCL_OK; /* Detail name (optional) */ p = GetField(p, detailName, FIELD_SIZE); if (debug_bindings) dbwin("GetField='%s'\n", detailName); /* Terminating > */ if (*p != '>') { Tcl_AppendResult(interp, "missing \">\" in event pattern \"", pattern, "\"", (char *) NULL); return TCL_ERROR; } return TCL_OK; } static int ParseEventDescription(BindingTable *bindPtr, char *eventString, Pattern *patPtr, EventInfo **eventInfoPtr, Detail **detailPtr) { Tcl_Interp *interp = bindPtr->interp; Tcl_HashEntry *hPtr; char eventName[FIELD_SIZE], detailName[FIELD_SIZE]; EventInfo *eiPtr; Detail *dPtr; char errorMsg[512]; if (eventInfoPtr) *eventInfoPtr = NULL; if (detailPtr) *detailPtr = NULL; patPtr->type = -1; patPtr->detail = 0; if (ParseEventDescription1(bindPtr, eventString, eventName, detailName) != TCL_OK) return TCL_ERROR; hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { sprintf(errorMsg, "unknown event \"%.128s\"", eventName); Tcl_SetResult(interp, errorMsg, TCL_VOLATILE); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); patPtr->type = eiPtr->type; if (eventInfoPtr) *eventInfoPtr = eiPtr; if (detailName[0] != '\0') { /* Find detail for the matching event */ for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, detailName) == 0) break; } if (dPtr == NULL) { sprintf(errorMsg, "unknown detail \"%.128s\" for event \"%.128s\"", detailName, eiPtr->name); Tcl_SetResult(interp, errorMsg, TCL_VOLATILE); return TCL_ERROR; } patPtr->detail = dPtr->code; if (detailPtr) *detailPtr = dPtr; } return TCL_OK; } static int FindSequence(BindingTable *bindPtr, ClientData object, char *eventString, int create, int *created, BindValue **result) { Tcl_HashEntry *hPtr; Pattern pats; ObjectTableKey key; BindValue *valuePtr; int isNew; if (debug_bindings) dbwin("FindSequence object='%s' pattern='%s'...\n", (char *) object, eventString); if (created) (*created) = 0; /* Event description -> Pattern */ if (ParseEventDescription(bindPtr, eventString, &pats, NULL, NULL) != TCL_OK) return TCL_ERROR; /* type + detail + object -> BindValue */ key.type = pats.type; key.detail = pats.detail; key.object = object; if (create) { hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) &key, &isNew); if (isNew) { if (debug_bindings) dbwin("New BindValue for '%s' type=%d detail=%d\n", (char *) object, pats.type, pats.detail); valuePtr = (BindValue *) Tcl_Alloc(sizeof(BindValue)); valuePtr->type = pats.type; valuePtr->detail = pats.detail; valuePtr->object = object; valuePtr->command = NULL; valuePtr->specific = 0; valuePtr->nextValue = NULL; #if BIND_ACTIVE /* This binding is active */ valuePtr->active = 1; #endif /* BIND_ACTIVE */ Tcl_SetHashValue(hPtr, (ClientData) valuePtr); } if (created) (*created) = isNew; (*result) = (BindValue *) Tcl_GetHashValue(hPtr); return TCL_OK; } /* Look for existing objectTable entry */ hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) &key); if (hPtr == NULL) { (*result) = NULL; return TCL_OK; } (*result) = (BindValue *) Tcl_GetHashValue(hPtr); return TCL_OK; } void QE_ExpandDouble(double number, Tcl_DString *result) { char numStorage[TCL_DOUBLE_SPACE]; Tcl_PrintDouble((Tcl_Interp *) NULL, number, numStorage); Tcl_DStringAppend(result, numStorage, -1); /* QE_ExpandString(numStorage, result); */ } void QE_ExpandNumber(long number, Tcl_DString *result) { char numStorage[TCL_INTEGER_SPACE]; /* TclFormatInt() */ (void) sprintf(numStorage, "%ld", number); Tcl_DStringAppend(result, numStorage, -1); /* QE_ExpandString(numStorage, result); */ } void QE_ExpandString(char *string, Tcl_DString *result) { int length, spaceNeeded, cvtFlags; spaceNeeded = Tcl_ScanElement(string, &cvtFlags); length = Tcl_DStringLength(result); Tcl_DStringSetLength(result, length + spaceNeeded); spaceNeeded = Tcl_ConvertElement(string, Tcl_DStringValue(result) + length, cvtFlags | TCL_DONT_USE_BRACES); Tcl_DStringSetLength(result, length + spaceNeeded); } void QE_ExpandUnknown(char which, Tcl_DString *result) { char string[2]; (void) sprintf(string, "%c", which); QE_ExpandString(string, result); } void QE_ExpandEvent(QE_BindingTable bindingTable, int eventType, Tcl_DString *result) { BindingTable *bindPtr = (BindingTable *) bindingTable; EventInfo *eiPtr = FindEvent(bindPtr, eventType); if (eiPtr != NULL) QE_ExpandString((char *) eiPtr->name, result); else QE_ExpandString("unknown", result); } void QE_ExpandDetail(QE_BindingTable bindingTable, int event, int detail, Tcl_DString *result) { BindingTable *bindPtr = (BindingTable *) bindingTable; Detail *dPtr; if (detail == 0) { QE_ExpandString("", result); return; } dPtr = FindDetail(bindPtr, event, detail); if (dPtr != NULL) QE_ExpandString((char *) dPtr->name, result); else QE_ExpandString("unknown", result); } void QE_ExpandPattern(QE_BindingTable bindingTable, int eventType, int detail, Tcl_DString *result) { BindingTable *bindPtr = (BindingTable *) bindingTable; EventInfo *eiPtr = FindEvent(bindPtr, eventType); Tcl_DStringAppend(result, "<", 1); Tcl_DStringAppend(result, eiPtr ? eiPtr->name : "unknown", -1); if (detail) { Detail *dPtr = FindDetail(bindPtr, eventType, detail); Tcl_DStringAppend(result, "-", 1); Tcl_DStringAppend(result, dPtr ? dPtr->name : "unknown", -1); } Tcl_DStringAppend(result, ">", 1); } int QE_BindCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; Tk_Window tkwin = Tk_MainWindow(bindPtr->interp); ClientData object; char *string; if ((objC < 1) || (objC > 4)) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "?object? ?pattern? ?script?"); return TCL_ERROR; } if (objC == 1) { QE_GetAllObjects(bindingTable); return TCL_OK; } string = Tcl_GetString(objV[1]); if (string[0] == '.') { Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(bindPtr->interp, string, tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } object = (ClientData) Tk_GetUid(Tk_PathName(tkwin2)); } else { object = (ClientData) Tk_GetUid(string); } if (objC == 4) { int append = 0; char *sequence = Tcl_GetString(objV[2]); char *script = Tcl_GetString(objV[3]); if (script[0] == 0) { return QE_DeleteBinding(bindingTable, object, sequence); } if (script[0] == '+') { script++; append = 1; } return QE_CreateBinding(bindingTable, object, sequence, script, append); } else if (objC == 3) { char *sequence = Tcl_GetString(objV[2]); return QE_GetBinding(bindingTable, object, sequence); } else { QE_GetAllBindings(bindingTable, object); } return TCL_OK; } int QE_UnbindCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; Tk_Window tkwin = Tk_MainWindow(bindPtr->interp); ClientData object; char *string, *sequence; if ((objC < 2) || (objC > 3)) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "object ?pattern?"); return TCL_ERROR; } string = Tcl_GetString(objV[1]); if (string[0] == '.') { Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(bindPtr->interp, string, tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } object = (ClientData) Tk_GetUid(Tk_PathName(tkwin2)); } else { object = (ClientData) Tk_GetUid(string); } if (objC == 2) { return QE_DeleteBinding(bindingTable, object, NULL); } sequence = Tcl_GetString(objV[2]); return QE_DeleteBinding(bindingTable, object, sequence); } /* * qegenerate -- Generate events from scripts. * Usage: qegenerate $pattern ?$charMap? ?$percentsCommand? * Desciption: Scripts can generate "fake" quasi-events by providing * a quasi-event pattern and option field/value pairs. */ int QE_GenerateCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; QE_Event fakeEvent; EventInfo *eiPtr; Detail *dPtr; GenerateData genData; GenerateField *fieldPtr; char *p, *t; int listObjc; int i; Tcl_Obj **listObjv; Pattern pats; int result; if (objC < 2 || objC > 4) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern ?charMap? ?percentsCommand?"); return TCL_ERROR; } p = Tcl_GetStringFromObj(objV[1], NULL); if (ParseEventDescription(bindPtr, p, &pats, &eiPtr, &dPtr) != TCL_OK) return TCL_ERROR; /* Can't generate an event without a detail */ if ((dPtr == NULL) && (eiPtr->detailList != NULL)) { Tcl_AppendResult(bindPtr->interp, "cannot generate \"", p, "\": missing detail", (char *) NULL); return TCL_ERROR; } if (objC >= 3) { if (Tcl_ListObjGetElements(bindPtr->interp, objV[2], &listObjc, &listObjv) != TCL_OK) return TCL_ERROR; if (listObjc & 1) { Tcl_AppendResult(bindPtr->interp, "char map must have even number of elements", (char *) NULL); return TCL_ERROR; } genData.count = listObjc / 2; genData.field = genData.staticField; if (genData.count > sizeof(genData.staticField) / sizeof(genData.staticField[0])) { genData.field = (GenerateField *) Tcl_Alloc(sizeof(GenerateField) * genData.count); } genData.count = 0; while (listObjc > 1) { int length; t = Tcl_GetStringFromObj(listObjv[0], &length); if (length != 1) { Tcl_AppendResult(bindPtr->interp, "invalid percent char \"", t, "\"", NULL); result = TCL_ERROR; goto done; } /* Duplicate %-chars result in last duplicate being used */ fieldPtr = NULL; for (i = 0; i < genData.count; i++) { if (genData.field[i].which == t[0]) { fieldPtr = &genData.field[i]; break; } } if (fieldPtr == NULL) fieldPtr = &genData.field[genData.count++]; fieldPtr->which = t[0]; fieldPtr->string = Tcl_GetStringFromObj(listObjv[1], NULL); listObjv += 2; listObjc -= 2; } } else { genData.count = 0; genData.field = genData.staticField; } if (objC == 4) { genData.command = Tcl_GetString(objV[3]); } else { genData.command = NULL; } fakeEvent.type = pats.type; fakeEvent.detail = pats.detail; fakeEvent.clientData = NULL; result = BindEventWrapper(bindingTable, &fakeEvent, &genData); done: if (genData.field != genData.staticField) Tcl_Free((char *) genData.field); return result; } #if BIND_ACTIVE /* qeconfigure $win -active no */ int QE_ConfigureCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_Interp *interp = bindPtr->interp; Tk_Window tkwin = Tk_MainWindow(interp); static CONST84 char *configSwitch[] = {"-active", NULL}; Tcl_Obj *CONST *objPtr; BindValue *valuePtr; char *t, *eventString; int index; ClientData object; if (objC < 3) { Tcl_WrongNumArgs(interp, objOffset + 1, objv, "object pattern ?option? ?value? ?option value ...?"); return TCL_ERROR; } t = Tcl_GetStringFromObj(objV[1], NULL); eventString = Tcl_GetStringFromObj(objV[2], NULL); if (t[0] == '.') { Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(interp, t, tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } object = (ClientData) Tk_GetUid(Tk_PathName(tkwin2)); } else { object = (ClientData) Tk_GetUid(t); } if (FindSequence(bindPtr, object, eventString, 0, NULL, &valuePtr) != TCL_OK) return TCL_ERROR; if (valuePtr == NULL) return TCL_OK; objPtr = objv + objOffset + 3; objc -= objOffset + 3; if (objc == 0) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj("-active", -1)); Tcl_ListObjAppendElement(interp, listObj, Tcl_NewBooleanObj(valuePtr->active)); Tcl_SetObjResult(interp, listObj); return TCL_OK; } if (objc == 1) { if (Tcl_GetIndexFromObj(interp, objPtr[0], configSwitch, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case 0: /* -active */ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(valuePtr->active)); break; } return TCL_OK; } while (objc > 1) { if (Tcl_GetIndexFromObj(interp, objPtr[0], configSwitch, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case 0: /* -active */ if (Tcl_GetBooleanFromObj(interp, objPtr[1], &valuePtr->active) != TCL_OK) { return TCL_ERROR; } break; } objPtr += 2; objc -= 2; } return TCL_OK; } #endif /* BIND_ACTIVE */ /* Perform %-substitution with $charMap only */ static void Percents_CharMap(QE_ExpandArgs *args) { GenerateData *gdPtr = (GenerateData *) args->clientData; int i; for (i = 0; i < gdPtr->count; i++) { GenerateField *gfPtr = &gdPtr->field[i]; if (gfPtr->which == args->which) { QE_ExpandString(gfPtr->string, args->result); return; } } QE_ExpandUnknown(args->which, args->result); } /* Perform %-substitution by calling a Tcl command */ static void Percents_Command(QE_ExpandArgs *args) { BindingTable *bindPtr = (BindingTable *) args->bindingTable; Tcl_Interp *interp = bindPtr->interp; PercentsData *data = (PercentsData *) args->clientData; GenerateData *gdPtr = data->gdPtr; EventInfo *eiPtr = data->eventPtr; Detail *dPtr = data->detailPtr; Tcl_DString command; Tcl_SavedResult state; int i; Tcl_DStringInit(&command); Tcl_DStringAppend(&command, data->command, -1); Tcl_DStringAppend(&command, " ", 1); Tcl_DStringAppend(&command, &args->which, 1); Tcl_DStringAppend(&command, " ", 1); Tcl_DStringAppend(&command, (char *) args->object, -1); Tcl_DStringAppend(&command, " ", 1); Tcl_DStringAppend(&command, eiPtr->name, -1); Tcl_DStringAppend(&command, " ", 1); if (dPtr != NULL) Tcl_DStringAppend(&command, dPtr->name, -1); else Tcl_DStringAppend(&command, "{}", -1); Tcl_DStringStartSublist(&command); for (i = 0; i < gdPtr->count; i++) { GenerateField *genField = &gdPtr->field[i]; char string[2]; string[0] = genField->which; string[1] = '\0'; Tcl_DStringAppendElement(&command, string); Tcl_DStringAppendElement(&command, genField->string); } Tcl_DStringEndSublist(&command); Tcl_SaveResult(interp, &state); if (Tcl_EvalEx(interp, Tcl_DStringValue(&command), Tcl_DStringLength(&command), TCL_EVAL_GLOBAL) == TCL_OK) { QE_ExpandString(Tcl_GetStringFromObj(Tcl_GetObjResult(interp), NULL), args->result); } else { QE_ExpandUnknown(args->which, args->result); Tcl_AddErrorInfo(interp, "\n (expanding percents)"); Tcl_BackgroundError(interp); } Tcl_RestoreResult(interp, &state); Tcl_DStringFree(&command); } #if ALLOW_INSTALL int QE_InstallCmd_New(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *pattern, *command = NULL; char eventName[FIELD_SIZE], detailName[FIELD_SIZE]; int id, length; EventInfo *eiPtr; Detail *dPtr = NULL; Tcl_HashEntry *hPtr; if (objC < 2 || objC > 3) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern ?percentsCommand?"); return TCL_ERROR; } pattern = Tcl_GetString(objV[1]); if (ParseEventDescription1(bindPtr, pattern, eventName, detailName) != TCL_OK) return TCL_ERROR; hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); /* The event is not defined */ if (hPtr == NULL) { id = QE_InstallEvent(bindingTable, eventName, NULL); if (id == 0) return TCL_ERROR; /* Find the event we just installed */ hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) return TCL_ERROR; eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); /* Mark as installed-by-script */ eiPtr->dynamic = 1; } /* The event is already defined */ else { eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); } if (detailName[0]) { for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, detailName) == 0) break; } /* The detail is not defined */ if (dPtr == NULL) { /* Define the new detail */ id = QE_InstallDetail(bindingTable, detailName, eiPtr->type, NULL); if (id == 0) return TCL_ERROR; /* Get the detail we just defined */ dPtr = FindDetail(bindPtr, eiPtr->type, id); if (dPtr == NULL) return TCL_ERROR; /* Mark as installed-by-script */ dPtr->dynamic = 1; } } if (objC == 3) command = Tcl_GetStringFromObj(objV[2], &length); if (dPtr != NULL) { if (!dPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, pattern, " is not dynamic", NULL); return TCL_ERROR; } if (command != NULL) { if (dPtr->command) { Tcl_Free(dPtr->command); dPtr->command = NULL; } if (length) { dPtr->command = Tcl_Alloc(length + 1); (void) strcpy(dPtr->command, command); } } if (dPtr->command) Tcl_SetResult(bindPtr->interp, dPtr->command, TCL_VOLATILE); } else { if (!eiPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, pattern, " is not dynamic", NULL); return TCL_ERROR; } if (command != NULL) { if (eiPtr->command) { Tcl_Free(eiPtr->command); eiPtr->command = NULL; } if (length) { eiPtr->command = Tcl_Alloc(length + 1); (void) strcpy(eiPtr->command, command); } } if (eiPtr->command) Tcl_SetResult(bindPtr->interp, eiPtr->command, TCL_VOLATILE); } return TCL_OK; } int QE_InstallCmd_Old(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; static CONST84 char *commandOption[] = {"detail", "event", NULL}; int index; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "option arg ..."); return TCL_ERROR; } if (Tcl_GetIndexFromObj(bindPtr->interp, objV[1], commandOption, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case 0: /* detail */ { char *eventName, *detailName, *command; int id, length; Detail *dPtr; EventInfo *eiPtr; Tcl_HashEntry *hPtr; if ((objC < 4) || (objC > 5)) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 2, objv, "event detail ?percentsCommand?"); return TCL_ERROR; } /* Find the event type */ eventName = Tcl_GetStringFromObj(objV[2], NULL); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); /* Get the detail name */ detailName = Tcl_GetStringFromObj(objV[3], NULL); /* Define the new detail */ id = QE_InstallDetail(bindingTable, detailName, eiPtr->type, NULL); if (id == 0) return TCL_ERROR; /* Get the detail we just defined */ dPtr = FindDetail(bindPtr, eiPtr->type, id); if (dPtr == NULL) return TCL_ERROR; dPtr->dynamic = 1; if (objC == 4) break; /* Set the Tcl command for this detail */ command = Tcl_GetStringFromObj(objV[4], &length); if (length) { dPtr->command = Tcl_Alloc(length + 1); (void) strcpy(dPtr->command, command); } break; } case 1: /* event */ { char *eventName, *command; int id, length; EventInfo *eiPtr; Tcl_HashEntry *hPtr; if (objC < 3 || objC > 4) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 2, objv, "name ?percentsCommand?"); return TCL_ERROR; } eventName = Tcl_GetStringFromObj(objV[2], NULL); id = QE_InstallEvent(bindingTable, eventName, NULL); if (id == 0) return TCL_ERROR; /* Find the event we just installed */ hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) return TCL_ERROR; eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); /* Mark as installed-by-script */ eiPtr->dynamic = 1; if (objC == 3) break; /* Set the Tcl command for this event */ command = Tcl_GetStringFromObj(objV[3], &length); if (length) { eiPtr->command = Tcl_Alloc(length + 1); (void) strcpy(eiPtr->command, command); } break; } } return TCL_OK; } int QE_InstallCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *s; int length; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern ?percentsCommand?"); return TCL_ERROR; } s = Tcl_GetStringFromObj(objV[1], &length); if (length && (!strcmp(s, "detail") || !strcmp(s, "event"))) return QE_InstallCmd_Old(bindingTable, objOffset, objc, objv); return QE_InstallCmd_New(bindingTable, objOffset, objc, objv); } int QE_UninstallCmd_New(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *pattern; Pattern pats; EventInfo *eiPtr; Detail *dPtr; if (objC != 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern"); return TCL_ERROR; } pattern = Tcl_GetString(objV[1]); if (ParseEventDescription(bindPtr, pattern, &pats, &eiPtr, &dPtr) != TCL_OK) return TCL_ERROR; if (dPtr != NULL) { if (!dPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, "can't uninstall static detail \"", dPtr->name, "\"", NULL); return TCL_ERROR; } return QE_UninstallDetail(bindingTable, eiPtr->type, dPtr->code); } if (!eiPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, "can't uninstall static event \"", eiPtr->name, "\"", NULL); return TCL_ERROR; } return QE_UninstallEvent(bindingTable, eiPtr->type); } int QE_UninstallCmd_Old(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; static CONST84 char *commandOption[] = {"detail", "event", NULL}; int index; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "option arg ..."); return TCL_ERROR; } if (Tcl_GetIndexFromObj(bindPtr->interp, objV[1], commandOption, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case 0: /* detail */ { char *eventName, *detailName; Detail *dPtr; EventInfo *eiPtr; Tcl_HashEntry *hPtr; if (objC != 4) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 2, objv, "event detail"); return TCL_ERROR; } /* Find the event type */ eventName = Tcl_GetStringFromObj(objV[2], NULL); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); /* Get the detail name */ detailName = Tcl_GetStringFromObj(objV[3], NULL); for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, detailName) == 0) break; } if (dPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown detail \"", detailName, "\" for event \"", eiPtr->name, "\"", NULL); return TCL_ERROR; } if (!dPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, "can't uninstall static detail \"", detailName, "\"", NULL); return TCL_ERROR; } return QE_UninstallDetail(bindingTable, eiPtr->type, dPtr->code); } case 1: /* event */ { Tcl_HashEntry *hPtr; EventInfo *eiPtr; char *eventName; if (objC != 3) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 2, objv, "name"); return TCL_ERROR; } /* Find the event type */ eventName = Tcl_GetStringFromObj(objV[2], NULL); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); if (!eiPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, "can't uninstall static event \"", eventName, "\"", NULL); return TCL_ERROR; } return QE_UninstallEvent(bindingTable, eiPtr->type); } } return TCL_OK; } int QE_UninstallCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *s; int length; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern"); return TCL_ERROR; } s = Tcl_GetStringFromObj(objV[1], &length); if (length && (!strcmp(s, "detail") || !strcmp(s, "event"))) return QE_UninstallCmd_Old(bindingTable, objOffset, objc, objv); return QE_UninstallCmd_New(bindingTable, objOffset, objc, objv); } int QE_LinkageCmd_New(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *pattern; Pattern pats; EventInfo *eiPtr; Detail *dPtr; if (objC != 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern"); return TCL_ERROR; } pattern = Tcl_GetString(objV[1]); if (ParseEventDescription(bindPtr, pattern, &pats, &eiPtr, &dPtr) != TCL_OK) return TCL_ERROR; if (dPtr != NULL) { Tcl_SetResult(bindPtr->interp, dPtr->dynamic ? "dynamic" : "static", TCL_STATIC); return TCL_OK; } Tcl_SetResult(bindPtr->interp, eiPtr->dynamic ? "dynamic" : "static", TCL_STATIC); return TCL_OK; } int QE_LinkageCmd_Old(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *eventName, *detailName; Detail *dPtr; EventInfo *eiPtr; Tcl_HashEntry *hPtr; if (objC < 2 || objC > 3) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "event ?detail?"); return TCL_ERROR; } /* Find the event type */ eventName = Tcl_GetStringFromObj(objV[1], NULL); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); if (objC == 2) { Tcl_SetResult(bindPtr->interp, eiPtr->dynamic ? "dynamic" : "static", TCL_STATIC); return TCL_OK; } /* Get the detail name */ detailName = Tcl_GetStringFromObj(objV[2], NULL); for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, detailName) == 0) break; } if (dPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown detail \"", detailName, "\" for event \"", eiPtr->name, "\"", NULL); return TCL_ERROR; } Tcl_SetResult(bindPtr->interp, dPtr->dynamic ? "dynamic" : "static", TCL_STATIC); return TCL_OK; } int QE_LinkageCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *s; int length; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern"); return TCL_ERROR; } s = Tcl_GetStringFromObj(objV[1], &length); if ((objC == 3) || (length && s[0] != '<')) return QE_LinkageCmd_Old(bindingTable, objOffset, objc, objv); return QE_LinkageCmd_New(bindingTable, objOffset, objc, objv); } #endif /* ALLOW_INSTALL */ kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeTheme.c0000644000175000017500000006411711037221320025060 0ustar domibeldomibel/* * tkTreeTheme.c -- * * This module implements platform-specific visual themes. * * Copyright (c) 2006 Tim Baker * * RCS: @(#) $Id: tkTreeTheme.c,v 1.5 2008-07-15 22:21:04 barre Exp $ */ #if defined(WIN32) && !defined(WINVER) #define WINVER 0x0501 /* Cygwin */ #endif #include "tkTreeCtrl.h" /* These must agree with tkTreeColumn.c */ #define COLUMN_STATE_NORMAL 0 #define COLUMN_STATE_ACTIVE 1 #define COLUMN_STATE_PRESSED 2 #ifdef WIN32 #include "vtkWin32Header.h" // vtkSetWindowLong #include "tkWinInt.h" #include #include #ifndef DTBG_OMITBORDER # ifndef DTBG_CLIPRECT # define DTBG_CLIPRECT 0x00000001 # endif # ifndef DTBG_DRAWSOLID # define DTBG_DRAWSOLID 0x00000002 # endif # ifndef DTBG_OMITBORDER # define DTBG_OMITBORDER 0x00000004 # endif # ifndef DTBG_OMITCONTENT # define DTBG_OMITCONTENT 0x00000008 # endif # ifndef DTBG_COMPUTINGREGION # define DTBG_COMPUTINGREGION 0x00000010 # endif # ifndef DTBG_MIRRORDC # define DTBG_MIRRORDC 0x00000020 # endif typedef struct _DTBGOPTS { DWORD dwSize; DWORD dwFlags; RECT rcClip; } DTBGOPTS, *PDTBGOPTS; #endif // _DTBGOPTS #include /* Cygwin */ #ifndef TMT_CONTENTMARGINS #define TMT_CONTENTMARGINS 3602 #endif typedef HTHEME (STDAPICALLTYPE OpenThemeDataProc)(HWND hwnd, LPCWSTR pszClassList); typedef HRESULT (STDAPICALLTYPE CloseThemeDataProc)(HTHEME hTheme); typedef HRESULT (STDAPICALLTYPE DrawThemeBackgroundProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); typedef HRESULT (STDAPICALLTYPE DrawThemeBackgroundExProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, DTBGOPTS *PDTBGOPTS); typedef HRESULT (STDAPICALLTYPE DrawThemeParentBackgroundProc)(HWND hwnd, HDC hdc, OPTIONAL const RECT *prc); typedef HRESULT (STDAPICALLTYPE DrawThemeEdgeProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pDestRect, UINT uEdge, UINT uFlags, RECT *pContentRect); typedef HRESULT (STDAPICALLTYPE DrawThemeTextProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect); typedef HRESULT (STDAPICALLTYPE GetThemeBackgroundContentRectProc)( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect); typedef HRESULT (STDAPICALLTYPE GetThemeBackgroundExtentProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pContentRect, RECT *pExtentRect); typedef HRESULT (STDAPICALLTYPE GetThemeMarginsProc)(HTHEME, HDC, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, MARGINS *pMargins); typedef HRESULT (STDAPICALLTYPE GetThemePartSizeProc)(HTHEME, HDC, int iPartId, int iStateId, RECT *prc, enum THEMESIZE eSize, SIZE *psz); typedef HRESULT (STDAPICALLTYPE GetThemeTextExtentProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, const RECT *pBoundingRect, RECT *pExtentRect); typedef BOOL (STDAPICALLTYPE IsThemeActiveProc)(VOID); typedef BOOL (STDAPICALLTYPE IsThemePartDefinedProc)(HTHEME, int, int); typedef HRESULT (STDAPICALLTYPE IsThemeBackgroundPartiallyTransparentProc)( HTHEME, int, int); typedef struct { OpenThemeDataProc *OpenThemeData; CloseThemeDataProc *CloseThemeData; DrawThemeBackgroundProc *DrawThemeBackground; DrawThemeBackgroundExProc *DrawThemeBackgroundEx; DrawThemeParentBackgroundProc *DrawThemeParentBackground; DrawThemeEdgeProc *DrawThemeEdge; DrawThemeTextProc *DrawThemeText; GetThemeBackgroundContentRectProc *GetThemeBackgroundContentRect; GetThemeBackgroundExtentProc *GetThemeBackgroundExtent; GetThemeMarginsProc *GetThemeMargins; GetThemePartSizeProc *GetThemePartSize; GetThemeTextExtentProc *GetThemeTextExtent; IsThemeActiveProc *IsThemeActive; IsThemePartDefinedProc *IsThemePartDefined; IsThemeBackgroundPartiallyTransparentProc *IsThemeBackgroundPartiallyTransparent; } XPThemeProcs; typedef struct { HINSTANCE hlibrary; XPThemeProcs *procs; int registered; int themeEnabled; SIZE buttonOpen; SIZE buttonClosed; } XPThemeData; typedef struct TreeThemeData_ { HTHEME hThemeHEADER; HTHEME hThemeTREEVIEW; } TreeThemeData_; static XPThemeProcs *procs = NULL; static XPThemeData *appThemeData = NULL; TCL_DECLARE_MUTEX(themeMutex) /* *---------------------------------------------------------------------- * * LoadXPThemeProcs -- * Initialize XP theming support. * * XP theme support is included in UXTHEME.DLL * We dynamically load this DLL at runtime instead of linking * to it at build-time. * * Returns: * A pointer to an XPThemeProcs table if successful, NULL otherwise. */ static XPThemeProcs * LoadXPThemeProcs(HINSTANCE *phlib) { OSVERSIONINFO os; /* * We have to check whether we are running at least on Windows XP. * In order to determine this we call GetVersionEx directly, although * it would be a good idea to wrap it inside a function similar to * TkWinGetPlatformId... */ ZeroMemory(&os, sizeof(os)); os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&os); if (os.dwMajorVersion >= 5 && os.dwMinorVersion >= 1) { /* * We are running under Windows XP or a newer version. * Load the library "uxtheme.dll", where the native widget * drawing routines are implemented. */ HINSTANCE handle; *phlib = handle = LoadLibrary("uxtheme.dll"); if (handle != 0) { /* * We have successfully loaded the library. Proceed in storing the * addresses of the functions we want to use. */ XPThemeProcs *procs = (XPThemeProcs*)ckalloc(sizeof(XPThemeProcs)); #define LOADPROC(name) \ (0 != (procs->name = (name ## Proc *)GetProcAddress(handle, #name) )) if ( LOADPROC(OpenThemeData) && LOADPROC(CloseThemeData) && LOADPROC(DrawThemeBackground) && LOADPROC(DrawThemeBackgroundEx) && LOADPROC(DrawThemeParentBackground) && LOADPROC(DrawThemeEdge) && LOADPROC(DrawThemeText) && LOADPROC(GetThemeBackgroundContentRect) && LOADPROC(GetThemeBackgroundExtent) && LOADPROC(GetThemeMargins) && LOADPROC(GetThemePartSize) && LOADPROC(GetThemeTextExtent) && LOADPROC(IsThemeActive) && LOADPROC(IsThemePartDefined) && LOADPROC(IsThemeBackgroundPartiallyTransparent) ) { return procs; } #undef LOADPROC ckfree((char*)procs); } } return 0; } int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height) { HTHEME hTheme; HDC hDC; TkWinDCState dcState; RECT rc; HRESULT hr; int iPartId = HP_HEADERITEM; int iStateId = HIS_NORMAL; switch (state) { case COLUMN_STATE_ACTIVE: iStateId = HIS_HOT; break; case COLUMN_STATE_PRESSED: iStateId = HIS_PRESSED; break; } if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; hTheme = tree->themeData->hThemeHEADER; if (!hTheme) return TCL_ERROR; #if 0 /* Always returns FALSE */ if (!procs->IsThemePartDefined( hTheme, iPartId, iStateId)) { return TCL_ERROR; } #endif rc.left = x; rc.top = y; rc.right = x + width; rc.bottom = y + height; /* Is transparent for the default XP style. */ if (procs->IsThemeBackgroundPartiallyTransparent( hTheme, iPartId, iStateId)) { #if 1 /* What color should I use? */ Tk_Fill3DRectangle(tree->tkwin, drawable, tree->border, x, y, width, height, 0, TK_RELIEF_FLAT); #else /* This draws nothing, maybe because the parent window is not * themed */ procs->DrawThemeParentBackground( hwnd, hDC, &rc); #endif } hDC = TkWinGetDrawableDC(tree->display, drawable, &dcState); #if 0 { /* Default XP theme gives rect 3 pixels narrower than rc */ RECT contentRect, extentRect; hr = procs->GetThemeBackgroundContentRect( hTheme, hDC, iPartId, iStateId, &rc, &contentRect ); dbwin("GetThemeBackgroundContentRect width=%d height=%d\n", contentRect.right - contentRect.left, contentRect.bottom - contentRect.top); /* Gives rc */ hr = procs->GetThemeBackgroundExtent( hTheme, hDC, iPartId, iStateId, &contentRect, &extentRect ); dbwin("GetThemeBackgroundExtent width=%d height=%d\n", extentRect.right - extentRect.left, extentRect.bottom - extentRect.top); } #endif hr = procs->DrawThemeBackground( hTheme, hDC, iPartId, iStateId, &rc, NULL); TkWinReleaseDrawableDC(drawable, hDC, &dcState); if (hr != S_OK) return TCL_ERROR; return TCL_OK; } int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]) { Window win = Tk_WindowId(tree->tkwin); HTHEME hTheme; HDC hDC; TkWinDCState dcState; HRESULT hr; MARGINS margins; int iPartId = HP_HEADERITEM; int iStateId = HIS_NORMAL; switch (state) { case COLUMN_STATE_ACTIVE: iStateId = HIS_HOT; break; case COLUMN_STATE_PRESSED: iStateId = HIS_PRESSED; break; } if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; hTheme = tree->themeData->hThemeHEADER; if (!hTheme) return TCL_ERROR; hDC = TkWinGetDrawableDC(tree->display, win, &dcState); /* The default XP themes give 3,0,0,0 which makes little sense since * it is the *right* side that should not be drawn over by text; the * 2-pixel wide header divider is on the right */ hr = procs->GetThemeMargins( hTheme, hDC, iPartId, iStateId, TMT_CONTENTMARGINS, NULL, &margins); TkWinReleaseDrawableDC(win, hDC, &dcState); if (hr != S_OK) return TCL_ERROR; bounds[0] = margins.cxLeftWidth; bounds[1] = margins.cyTopHeight; bounds[2] = margins.cxRightWidth; bounds[3] = margins.cyBottomHeight; /* dbwin("margins %d %d %d %d\n", bounds[0], bounds[1], bounds[2], bounds[3]); */ return TCL_OK; } int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height) { #if 1 XColor *color; GC gc; int i; if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; color = Tk_GetColor(tree->interp, tree->tkwin, "#ACA899"); gc = Tk_GCForColor(color, drawable); if (up) { for (i = 0; i < height; i++) { XDrawLine(tree->display, drawable, gc, x + width / 2 - i, y + i, x + width / 2 + i + 1, y + i); } } else { for (i = 0; i < height; i++) { XDrawLine(tree->display, drawable, gc, x + width / 2 - i, y + (height - 1) - i, x + width / 2 + i + 1, y + (height - 1) - i); } } Tk_FreeColor(color); return TCL_OK; #else /* Doesn't seem that Microsoft actually implemented this */ Window win = Tk_WindowId(tree->tkwin); HWND hwnd = Tk_GetHWND(win); HTHEME hTheme; HDC hDC; TkWinDCState dcState; RECT rc; HRESULT hr; int iPartId = HP_HEADERSORTARROW; int iStateId = up ? HSAS_SORTEDUP : HSAS_SORTEDDOWN; if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; hTheme = tree->themeData->hThemeHEADER; if (!hTheme) return TCL_ERROR; if (!procs->IsThemePartDefined( hTheme, iPartId, iStateId)) { return TCL_ERROR; } hDC = TkWinGetDrawableDC(tree->display, drawable, &dcState); rc.left = x; rc.top = y; rc.right = x + width; rc.bottom = y + height; hr = procs->DrawThemeBackground( hTheme, hDC, iPartId, iStateId, &rc, NULL); TkWinReleaseDrawableDC(drawable, hDC, &dcState); return TCL_OK; #endif /* 0 */ } int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height) { HTHEME hTheme; HDC hDC; TkWinDCState dcState; RECT rc; HRESULT hr; int iPartId, iStateId; if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; iPartId = TVP_GLYPH; iStateId = open ? GLPS_OPENED : GLPS_CLOSED; hTheme = tree->themeData->hThemeTREEVIEW; if (!hTheme) return TCL_ERROR; #if 0 /* Always returns FALSE */ if (!procs->IsThemePartDefined( hTheme, iPartId, iStateId)) { return TCL_ERROR; } #endif hDC = TkWinGetDrawableDC(tree->display, drawable, &dcState); rc.left = x; rc.top = y; rc.right = x + width; rc.bottom = y + height; hr = procs->DrawThemeBackground( hTheme, hDC, iPartId, iStateId, &rc, NULL); TkWinReleaseDrawableDC(drawable, hDC, &dcState); if (hr != S_OK) return TCL_ERROR; return TCL_OK; } int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr) { HTHEME hTheme; HDC hDC; TkWinDCState dcState; HRESULT hr; SIZE size; int iPartId, iStateId; if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; /* Use cached values */ size = open ? appThemeData->buttonOpen : appThemeData->buttonClosed; if (size.cx > 1) { *widthPtr = size.cx; *heightPtr = size.cy; return TCL_OK; } iPartId = TVP_GLYPH; iStateId = open ? GLPS_OPENED : GLPS_CLOSED; hTheme = tree->themeData->hThemeTREEVIEW; if (!hTheme) return TCL_ERROR; #if 0 /* Always returns FALSE */ if (!procs->IsThemePartDefined( hTheme, iPartId, iStateId)) { return TCL_ERROR; } #endif hDC = TkWinGetDrawableDC(tree->display, drawable, &dcState); /* Returns 9x9 for default XP style */ hr = procs->GetThemePartSize( hTheme, hDC, iPartId, iStateId, NULL, TS_DRAW, &size ); TkWinReleaseDrawableDC(drawable, hDC, &dcState); /* With RandomN of 10000, I eventually get hr=E_HANDLE, invalid handle */ /* Not any longer since I don't call OpenThemeData/CloseThemeData for * every call. */ if (hr != S_OK) return TCL_ERROR; /* Gave me 0,0 for a non-default theme, even though glyph existed */ if ((size.cx <= 1) && (size.cy <= 1)) return TCL_ERROR; /* Cache the values */ if (open) appThemeData->buttonOpen = size; else appThemeData->buttonClosed = size; *widthPtr = size.cx; *heightPtr = size.cy; return TCL_OK; } int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr) { if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; *widthPtr = 9; *heightPtr = 5; return TCL_OK; } #if !defined(WM_THEMECHANGED) #define WM_THEMECHANGED 0x031A #endif static LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { /*Tcl_Interp *interp = (Tcl_Interp *)GetWindowLong(hwnd, GWL_USERDATA); */ Tcl_Interp *interp = (Tcl_Interp *)vtkGetWindowLong(hwnd,vtkGWL_USERDATA); switch (msg) { case WM_THEMECHANGED: Tcl_MutexLock(&themeMutex); appThemeData->themeEnabled = procs->IsThemeActive(); appThemeData->buttonClosed.cx = appThemeData->buttonOpen.cx = -1; Tcl_MutexUnlock(&themeMutex); Tree_TheWorldHasChanged(interp); break; } return DefWindowProc(hwnd, msg, wp, lp); } static CHAR windowClassName[32] = "TreeCtrlMonitorClass"; static BOOL RegisterThemeMonitorWindowClass(HINSTANCE hinst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hinst; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszMenuName = windowClassName; wc.lpszClassName = windowClassName; return RegisterClassEx(&wc); } static HWND CreateThemeMonitorWindow(HINSTANCE hinst, Tcl_Interp *interp) { CHAR title[32] = "TreeCtrlMonitorWindow"; HWND hwnd; hwnd = CreateWindow(windowClassName, title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, NULL); if (!hwnd) return NULL; /* SetWindowLong(hwnd, GWL_USERDATA, (LONG)interp); */ vtkSetWindowLong(hwnd, vtkGWL_USERDATA, (vtkLONG)interp); ShowWindow(hwnd, SW_HIDE); UpdateWindow(hwnd); return hwnd; } typedef struct PerInterpData PerInterpData; struct PerInterpData { HWND hwnd; }; static void FreeAssocData(ClientData clientData, Tcl_Interp *interp) { PerInterpData *data = (PerInterpData *) clientData; DestroyWindow(data->hwnd); ckfree((char *) data); } void TreeTheme_ThemeChanged(TreeCtrl *tree) { Window win = Tk_WindowId(tree->tkwin); HWND hwnd = Tk_GetHWND(win); if (tree->themeData->hThemeHEADER != NULL) { procs->CloseThemeData(tree->themeData->hThemeHEADER); tree->themeData->hThemeHEADER = NULL; } if (tree->themeData->hThemeTREEVIEW != NULL) { procs->CloseThemeData(tree->themeData->hThemeTREEVIEW); tree->themeData->hThemeTREEVIEW = NULL; } if (!appThemeData->themeEnabled || !procs) return; tree->themeData->hThemeHEADER = procs->OpenThemeData(hwnd, L"HEADER"); tree->themeData->hThemeTREEVIEW = procs->OpenThemeData(hwnd, L"TREEVIEW"); } int TreeTheme_Init(TreeCtrl *tree) { Window win = Tk_WindowId(tree->tkwin); HWND hwnd = Tk_GetHWND(win); if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; tree->themeData = (TreeThemeData) ckalloc(sizeof(TreeThemeData_)); /* http://www.codeproject.com/cs/miscctrl/themedtabpage.asp?msg=1445385#xx1445385xx */ /* http://msdn2.microsoft.com/en-us/library/ms649781.aspx */ tree->themeData->hThemeHEADER = procs->OpenThemeData(hwnd, L"HEADER"); tree->themeData->hThemeTREEVIEW = procs->OpenThemeData(hwnd, L"TREEVIEW"); return TCL_OK; } int TreeTheme_Free(TreeCtrl *tree) { if (tree->themeData != NULL) { if (tree->themeData->hThemeHEADER != NULL) procs->CloseThemeData(tree->themeData->hThemeHEADER); if (tree->themeData->hThemeTREEVIEW != NULL) procs->CloseThemeData(tree->themeData->hThemeTREEVIEW); ckfree((char *) tree->themeData); } return TCL_OK; } int TreeTheme_InitInterp(Tcl_Interp *interp) { HWND hwnd; PerInterpData *data; Tcl_MutexLock(&themeMutex); /* This is done once per-application */ if (appThemeData == NULL) { appThemeData = (XPThemeData *) ckalloc(sizeof(XPThemeData)); appThemeData->procs = LoadXPThemeProcs(&appThemeData->hlibrary); appThemeData->registered = FALSE; appThemeData->themeEnabled = FALSE; appThemeData->buttonClosed.cx = appThemeData->buttonOpen.cx = -1; procs = appThemeData->procs; if (appThemeData->procs) { /* Check this again if WM_THEMECHANGED arrives */ appThemeData->themeEnabled = procs->IsThemeActive(); appThemeData->registered = RegisterThemeMonitorWindowClass(Tk_GetHINSTANCE()); } } Tcl_MutexUnlock(&themeMutex); if (!procs || !appThemeData->registered) return TCL_ERROR; /* Per-interp */ hwnd = CreateThemeMonitorWindow(Tk_GetHINSTANCE(), interp); if (!hwnd) return TCL_ERROR; data = (PerInterpData *) ckalloc(sizeof(PerInterpData)); data->hwnd = hwnd; Tcl_SetAssocData(interp, "TreeCtrlTheme", FreeAssocData, (ClientData) data); return TCL_OK; } #elif defined(MAC_OSX_TK) #include #include "tkMacOSXInt.h" static RgnHandle oldClip = NULL, boundsRgn = NULL; int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height) { MacDrawable *macWin = (MacDrawable *) drawable; Rect bounds; ThemeButtonDrawInfo info; CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; bounds.left = macWin->xOff + x; bounds.top = macWin->yOff + y; bounds.right = bounds.left + width; bounds.bottom = bounds.top + height; switch (state) { case COLUMN_STATE_ACTIVE: info.state = kThemeStateActive /* kThemeStateRollover */; break; case COLUMN_STATE_PRESSED: info.state = kThemeStatePressed; break; default: info.state = kThemeStateActive; break; } /* Background window */ if (!tree->isActive) info.state = kThemeStateInactive; info.value = (arrow != 0) ? kThemeButtonOn : kThemeButtonOff; info.adornment = (arrow == 1) ? kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone; destPort = TkMacOSXGetDrawablePort(drawable); GetGWorld(&saveWorld, &saveDevice); SetGWorld(destPort, 0); TkMacOSXSetUpClippingRgn(drawable); /* Save the old clipping region because we are going to modify it. */ if (oldClip == NULL) oldClip = NewRgn(); GetClip(oldClip); /* Create a clipping region as big as the header. */ if (boundsRgn == NULL) boundsRgn = NewRgn(); RectRgn(boundsRgn, &bounds); /* Set the clipping region to the intersection of the two regions. */ SectRgn(oldClip, boundsRgn, boundsRgn); SetClip(boundsRgn); /* Draw the left edge outside of the clipping region. */ bounds.left -= 1; (void) DrawThemeButton(&bounds, kThemeListHeaderButton, &info, NULL, /*prevInfo*/ NULL, /*eraseProc*/ NULL, /*labelProc*/ (UInt32)NULL); /*userData*/ SetClip(oldClip); SetGWorld(saveWorld,saveDevice); return TCL_OK; } /* List headers are a fixed height on Aqua */ int TreeTheme_GetHeaderFixedHeight(TreeCtrl *tree, int *heightPtr) { SInt32 metric; GetThemeMetric(kThemeMetricListHeaderHeight, &metric); *heightPtr = metric; return TCL_OK; } int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]) { Rect inBounds, outBounds; ThemeButtonDrawInfo info; SInt32 metric; inBounds.left = 0; inBounds.top = 0; inBounds.right = 100; GetThemeMetric(kThemeMetricListHeaderHeight, &metric); inBounds.bottom = metric; switch (state) { case COLUMN_STATE_ACTIVE: info.state = kThemeStateActive /* kThemeStateRollover */; break; case COLUMN_STATE_PRESSED: info.state = kThemeStatePressed; break; default: info.state = kThemeStateActive; break; } /* Background window */ if (!tree->isActive) info.state = kThemeStateInactive; info.value = (arrow != 0) ? kThemeButtonOn : kThemeButtonOff; info.adornment = (arrow == 1) ? kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone; (void) GetThemeButtonContentBounds( &inBounds, kThemeListHeaderButton, &info, &outBounds); bounds[0] = outBounds.left - inBounds.left; bounds[1] = outBounds.top - inBounds.top; bounds[2] = inBounds.right - outBounds.right; bounds[3] = inBounds.bottom - outBounds.bottom; return TCL_OK; } int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height) { return TCL_ERROR; } int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height) { MacDrawable *macWin = (MacDrawable *) drawable; Rect bounds; ThemeButtonDrawInfo info; CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; bounds.left = macWin->xOff + x; bounds.top = macWin->yOff + y; bounds.right = bounds.left + width; bounds.bottom = bounds.top + height; info.state = kThemeStateActive; info.value = open ? kThemeDisclosureDown : kThemeDisclosureRight; info.adornment = kThemeAdornmentNone; destPort = TkMacOSXGetDrawablePort(drawable); GetGWorld(&saveWorld, &saveDevice); SetGWorld(destPort, 0); TkMacOSXSetUpClippingRgn(drawable); /* Drawing the disclosure triangles produces a white background. * To avoid this, set the clipping region to the exact area where * pixels are drawn. */ /* Save the old clipping region because we are going to modify it. */ if (oldClip == NULL) oldClip = NewRgn(); GetClip(oldClip); /* Create a clipping region containing the pixels of the button. */ if (boundsRgn == NULL) boundsRgn = NewRgn(); (void) GetThemeButtonRegion(&bounds, kThemeDisclosureButton, &info, boundsRgn); /* Set the clipping region to the intersection of the two regions. */ SectRgn(oldClip, boundsRgn, boundsRgn); SetClip(boundsRgn); (void) DrawThemeButton(&bounds, kThemeDisclosureButton, &info, NULL, /*prevInfo*/ NULL, /*eraseProc*/ NULL, /*labelProc*/ (UInt32)NULL); /*userData*/ /* Restore the original clipping region. */ SetClip(oldClip); SetGWorld(saveWorld,saveDevice); return TCL_OK; } int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr) { SInt32 metric; (void) GetThemeMetric( kThemeMetricDisclosureTriangleWidth, &metric); *widthPtr = metric; (void) GetThemeMetric( kThemeMetricDisclosureTriangleHeight, &metric); *heightPtr = metric; return TCL_OK; } int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr) { return TCL_ERROR; } void TreeTheme_ThemeChanged(TreeCtrl *tree) { } int TreeTheme_Init(TreeCtrl *tree) { return TCL_OK; } int TreeTheme_Free(TreeCtrl *tree) { return TCL_OK; } int TreeTheme_InitInterp(Tcl_Interp *interp) { return TCL_OK; } #else /* MAC_OSX_TK */ int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height) { return TCL_ERROR; } int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]) { return TCL_ERROR; } int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height) { return TCL_ERROR; } int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height) { return TCL_ERROR; } int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr) { return TCL_ERROR; } int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr) { return TCL_ERROR; } void TreeTheme_ThemeChanged(TreeCtrl *tree) { } int TreeTheme_Init(TreeCtrl *tree) { return TCL_OK; } int TreeTheme_Free(TreeCtrl *tree) { return TCL_OK; } int TreeTheme_InitInterp(Tcl_Interp *interp) { return TCL_OK; } #endif /* !WIN32 && !MAC_OSX_TK */ kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeDrag.c0000644000175000017500000004563310674273023024712 0ustar domibeldomibel/* * tkTreeDrag.c -- * * This module implements outline dragging for treectrl widgets. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: tkTreeDrag.c,v 1.2 2007-09-19 19:18:43 barre Exp $ */ #include "tkTreeCtrl.h" typedef struct TreeDragImage_ TreeDragImage_; typedef struct DragElem DragElem; /* * The following structure holds info about a single element of the drag * image. */ struct DragElem { int x, y, width, height; DragElem *next; }; /* * The following structure holds info about the drag image. There is one of * these per TreeCtrl. */ struct TreeDragImage_ { TreeCtrl *tree; Tk_OptionTable optionTable; int visible; int x, y; /* offset to draw at in canvas coords */ int bounds[4]; /* bounds of all DragElems */ DragElem *elem; int onScreen; /* TRUE if is displayed */ int sx, sy; /* Window coords where displayed */ }; #define DRAG_CONF_VISIBLE 0x0001 static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BOOLEAN, "-visible", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeDragImage_, visible), 0, (ClientData) NULL, DRAG_CONF_VISIBLE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; /* *---------------------------------------------------------------------- * * DragElem_Alloc -- * * Allocate and initialize a new DragElem record. Add the record * to the list of records for the drag image. * * Results: * Pointer to allocated DragElem. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static DragElem * DragElem_Alloc( TreeDragImage dragImage /* Drag image record. */ ) { DragElem *elem = (DragElem *) ckalloc(sizeof(DragElem)); DragElem *walk = dragImage->elem; memset(elem, '\0', sizeof(DragElem)); if (dragImage->elem == NULL) dragImage->elem = elem; else { while (walk->next != NULL) walk = walk->next; walk->next = elem; } return elem; } /* *---------------------------------------------------------------------- * * DragElem_Free -- * * Free a DragElem. * * Results: * Pointer to the next DragElem. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static DragElem * DragElem_Free( TreeDragImage dragImage, /* Drag image record. */ DragElem *elem /* Drag element to free. */ ) { DragElem *next = elem->next; WFREE(elem, DragElem); return next; } /* *---------------------------------------------------------------------- * * TreeDragImage_Init -- * * Perform drag-image-related initialization when a new TreeCtrl is * created. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ int TreeDragImage_Init( TreeCtrl *tree /* Widget info. */ ) { TreeDragImage dragImage; dragImage = (TreeDragImage) ckalloc(sizeof(TreeDragImage_)); memset(dragImage, '\0', sizeof(TreeDragImage_)); dragImage->tree = tree; dragImage->optionTable = Tk_CreateOptionTable(tree->interp, optionSpecs); if (Tk_InitOptions(tree->interp, (char *) dragImage, dragImage->optionTable, tree->tkwin) != TCL_OK) { WFREE(dragImage, TreeDragImage_); return TCL_ERROR; } tree->dragImage = (TreeDragImage) dragImage; return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeDragImage_Free -- * * Free drag-image-related resources when a TreeCtrl is deleted. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeDragImage_Free( TreeDragImage dragImage /* Drag image token. */ ) { DragElem *elem = dragImage->elem; while (elem != NULL) elem = DragElem_Free(dragImage, elem); Tk_FreeConfigOptions((char *) dragImage, dragImage->optionTable, dragImage->tree->tkwin); WFREE(dragImage, TreeDragImage_); } /* *---------------------------------------------------------------------- * * TreeDragImage_Display -- * * Draw the drag image if it is not already displayed and if * it's -visible option is TRUE. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeDragImage_Display( TreeDragImage dragImage /* Drag image token. */ ) { TreeCtrl *tree = dragImage->tree; if (!dragImage->onScreen && dragImage->visible) { dragImage->sx = 0 - tree->xOrigin; dragImage->sy = 0 - tree->yOrigin; TreeDragImage_Draw(dragImage, Tk_WindowId(tree->tkwin), dragImage->sx, dragImage->sy); dragImage->onScreen = TRUE; } } /* *---------------------------------------------------------------------- * * TreeDragImage_Undisplay -- * * Erase the drag image if it is displayed. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeDragImage_Undisplay( TreeDragImage dragImage /* Drag image token. */ ) { TreeCtrl *tree = dragImage->tree; if (dragImage->onScreen) { TreeDragImage_Draw(dragImage, Tk_WindowId(tree->tkwin), dragImage->sx, dragImage->sy); dragImage->onScreen = FALSE; } } /* *---------------------------------------------------------------------- * * DragImage_Config -- * * This procedure is called to process an objc/objv list to set * configuration options for a DragImage. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then an error message is left in interp's result. * * Side effects: * Configuration information, such as text string, colors, font, * etc. get set for dragImage; old resources get freed, if there * were any. Display changes may occur. * *---------------------------------------------------------------------- */ static int DragImage_Config( TreeDragImage dragImage, /* Drag image record. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = dragImage->tree; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int mask; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) dragImage, dragImage->optionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* xxx */ Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* xxx */ Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } if (mask & DRAG_CONF_VISIBLE) { TreeDragImage_Undisplay((TreeDragImage) dragImage); TreeDragImage_Display((TreeDragImage) dragImage); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeDragImage_Draw -- * * Draw (or erase) the elements that make up the drag image. * * Results: * None. * * Side effects: * Stuff is drawn (or erased, since this is XOR drawing). * *---------------------------------------------------------------------- */ void TreeDragImage_Draw(TreeDragImage dragImage, Drawable drawable, int x, int y) { TreeCtrl *tree = dragImage->tree; DragElem *elem = dragImage->elem; DotState dotState; /* if (!dragImage->visible) return; */ if (elem == NULL) return; DotRect_Setup(tree, drawable, &dotState); while (elem != NULL) { DotRect_Draw(&dotState, x + dragImage->x + elem->x, y + dragImage->y + elem->y, elem->width, elem->height); elem = elem->next; } DotRect_Restore(&dotState); } /* *---------------------------------------------------------------------- * * DragImageCmd -- * * This procedure is invoked to process the [dragimage] widget * command. See the user documentation for details on what it * does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int DragImageCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; TreeDragImage dragImage = tree->dragImage; static CONST84 char *commandNames[] = { "add", "cget", "clear", "configure", "offset", (char *) NULL }; enum { COMMAND_ADD, COMMAND_CGET, COMMAND_CLEAR, COMMAND_CONFIGURE, COMMAND_OFFSET }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T dragimage add I ?C? ?E ...? */ case COMMAND_ADD: { #if 1 TreeItem item; TreeItemColumn itemColumn; TreeColumn treeColumn; XRectangle rects[128]; DragElem *elem; int i, count, result = TCL_OK; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "item ?column? ?element ...?"); return TCL_ERROR; } if (TreeItem_FromObj(tree, objv[3], &item, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; TreeDragImage_Undisplay(tree->dragImage); /* Every element in every column. */ if (objc == 4) { treeColumn = tree->columns; itemColumn = TreeItem_GetFirstColumn(tree, item); while (itemColumn != NULL) { if (TreeItemColumn_GetStyle(tree, itemColumn) != NULL) { count = TreeItem_GetRects(tree, item, treeColumn, -1, NULL, rects); if (count == -1) { result = TCL_ERROR; goto doneADD; } for (i = 0; i < count; i++) { elem = DragElem_Alloc(dragImage); elem->x = rects[i].x; elem->y = rects[i].y; elem->width = rects[i].width; elem->height = rects[i].height; } } treeColumn = TreeColumn_Next(treeColumn); itemColumn = TreeItemColumn_GetNext(tree, itemColumn); } } else { if (TreeColumn_FromObj(tree, objv[4], &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneADD; } /* Every element in a column. */ if (objc == 5) { objc = -1; objv = NULL; /* List of elements in a column. */ } else { objc -= 5; objv += 5; } count = TreeItem_GetRects(tree, item, treeColumn, objc, objv, rects); if (count == -1) { result = TCL_ERROR; goto doneADD; } for (i = 0; i < count; i++) { elem = DragElem_Alloc(dragImage); elem->x = rects[i].x; elem->y = rects[i].y; elem->width = rects[i].width; elem->height = rects[i].height; } } doneADD: dragImage->bounds[0] = 100000; dragImage->bounds[1] = 100000; dragImage->bounds[2] = -100000; dragImage->bounds[3] = -100000; for (elem = dragImage->elem; elem != NULL; elem = elem->next) { if (elem->x < dragImage->bounds[0]) dragImage->bounds[0] = elem->x; if (elem->y < dragImage->bounds[1]) dragImage->bounds[1] = elem->y; if (elem->x + elem->width > dragImage->bounds[2]) dragImage->bounds[2] = elem->x + elem->width; if (elem->y + elem->height > dragImage->bounds[3]) dragImage->bounds[3] = elem->y + elem->height; } TreeDragImage_Display(tree->dragImage); return result; #else XRectangle staticRects[STATIC_SIZE], *rects = staticRects; TreeItem item; TreeItemColumn itemColumn = NULL; TreeColumn treeColumn; int i, count, columnIndex = -1; int indent, width, totalWidth; int x, y, w, h; DragElem *elem; StyleDrawArgs drawArgs; int result = TCL_OK; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "item ?column? ?element ...?"); return TCL_ERROR; } if (TreeItem_FromObj(tree, objv[3], &item, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; /* Validate all of the arguments, even if the command would exit * early without needing to check those arguments. */ if (objc > 4) { if (TreeItem_ColumnFromObj(tree, item, objv[4], &itemColumn, &columnIndex) != TCL_OK) return TCL_ERROR; if (objc > 5) { if ((itemColumn == NULL) || (TreeItemColumn_GetStyle(tree, itemColumn) == NULL)) { FormatResult(interp, "item %s%d column %s%d has no style", tree->itemPrefix, TreeItem_GetID(tree, item), tree->columnPrefix, TreeColumn_GetID(Tree_FindColumn(tree, columnIndex))); return TCL_ERROR; } if (TreeStyle_ValidateElements(tree, TreeItemColumn_GetStyle(tree, itemColumn), objc - 5, objv + 5) != TCL_OK) return TCL_ERROR; } } if (Tree_ItemBbox(tree, item, COLUMN_LOCK_NONE, &x, &y, &w, &h) < 0) return TCL_OK; if (w < 1 || h < 1) return TCL_OK; drawArgs.tree = tree; drawArgs.drawable = None; /* FIXME: column state too */ drawArgs.state = TreeItem_GetState(tree, item); drawArgs.y = y; drawArgs.height = h; TreeDragImage_Undisplay(tree->dragImage); if (objc > 4) { treeColumn = Tree_FindColumn(tree, columnIndex); if (!TreeColumn_Visible(treeColumn)) goto doneAdd; drawArgs.style = TreeItemColumn_GetStyle(tree, itemColumn); totalWidth = TreeColumn_Offset(treeColumn); if (treeColumn == tree->columnTree) indent = TreeItem_Indent(tree, item); else indent = 0; drawArgs.indent = indent; drawArgs.x = x + totalWidth; drawArgs.width = TreeColumn_UseWidth(treeColumn); drawArgs.justify = TreeColumn_Justify(treeColumn); STATIC_ALLOC(rects, XRectangle, objc - 5); count = TreeStyle_GetElemRects(&drawArgs, objc - 5, objv + 5, rects); if (count == -1) { result = TCL_ERROR; goto doneAdd; } for (i = 0; i < count; i++) { elem = DragElem_Alloc(dragImage); elem->x = rects[i].x; elem->y = rects[i].y; elem->width = rects[i].width; elem->height = rects[i].height; } } else { totalWidth = 0; treeColumn = tree->columns; itemColumn = TreeItem_GetFirstColumn(tree, item); while (itemColumn != NULL) { if (!TreeColumn_Visible(treeColumn)) goto nextColumn; width = TreeColumn_UseWidth(treeColumn); if (treeColumn == tree->columnTree) indent = TreeItem_Indent(tree, item); else indent = 0; drawArgs.style = TreeItemColumn_GetStyle(tree, itemColumn); if (drawArgs.style != NULL) { drawArgs.indent = indent; drawArgs.x = x + totalWidth; drawArgs.width = width; drawArgs.justify = TreeColumn_Justify(treeColumn); count = TreeStyle_NumElements(tree, drawArgs.style); STATIC_ALLOC(rects, XRectangle, count); count = TreeStyle_GetElemRects(&drawArgs, 0, NULL, rects); if (count == -1) { result = TCL_ERROR; goto doneAdd; } for (i = 0; i < count; i++) { elem = DragElem_Alloc(dragImage); elem->x = rects[i].x; elem->y = rects[i].y; elem->width = rects[i].width; elem->height = rects[i].height; } if (rects != staticRects) { ckfree((char *) rects); rects = staticRects; } } totalWidth += width; nextColumn: treeColumn = TreeColumn_Next(treeColumn); itemColumn = TreeItemColumn_GetNext(tree, itemColumn); } } dragImage->bounds[0] = 100000; dragImage->bounds[1] = 100000; dragImage->bounds[2] = -100000; dragImage->bounds[3] = -100000; for (elem = dragImage->elem; elem != NULL; elem = elem->next) { if (elem->x < dragImage->bounds[0]) dragImage->bounds[0] = elem->x; if (elem->y < dragImage->bounds[1]) dragImage->bounds[1] = elem->y; if (elem->x + elem->width > dragImage->bounds[2]) dragImage->bounds[2] = elem->x + elem->width; if (elem->y + elem->height > dragImage->bounds[3]) dragImage->bounds[3] = elem->y + elem->height; } doneAdd: if (rects != staticRects) ckfree((char *) rects); TreeDragImage_Display(tree->dragImage); return result; #endif } /* T dragimage cget option */ case COMMAND_CGET: { Tcl_Obj *resultObjPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(interp, (char *) dragImage, dragImage->optionTable, objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T dragimage clear */ case COMMAND_CLEAR: { if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } if (dragImage->elem != NULL) { DragElem *elem = dragImage->elem; TreeDragImage_Undisplay(tree->dragImage); /* if (dragImage->visible) DragImage_Redraw(dragImage); */ while (elem != NULL) elem = DragElem_Free(dragImage, elem); dragImage->elem = NULL; } break; } /* T dragimage configure ?option? ?value? ?option value ...? */ case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?option? ?value?"); return TCL_ERROR; } if (objc <= 4) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) dragImage, dragImage->optionTable, (objc == 3) ? (Tcl_Obj *) NULL : objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } return DragImage_Config(dragImage, objc - 3, objv + 3); } /* T dragimage offset ?x y? */ case COMMAND_OFFSET: { int x, y; if (objc != 3 && objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "?x y?"); return TCL_ERROR; } if (objc == 3) { FormatResult(interp, "%d %d", dragImage->x, dragImage->y); break; } if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) return TCL_ERROR; TreeDragImage_Undisplay(tree->dragImage); /* if (dragImage->visible) DragImage_Redraw(dragImage); */ dragImage->x = x; dragImage->y = y; TreeDragImage_Display(tree->dragImage); break; } } return TCL_OK; } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/tkTreeMarquee.c0000644000175000017500000003043010674273024025422 0ustar domibeldomibel/* * tkTreeMarquee.c -- * * This module implements the selection rectangle for treectrl widgets. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: tkTreeMarquee.c,v 1.2 2007-09-19 19:18:44 barre Exp $ */ #include "tkTreeCtrl.h" typedef struct TreeMarquee_ TreeMarquee_; /* * The following structure holds info about the selection rectangle. * There is one of these per TreeCtrl. */ struct TreeMarquee_ { TreeCtrl *tree; Tk_OptionTable optionTable; int visible; /* -visible option. */ int x1, y1, x2, y2; /* Opposing corners. */ int onScreen; /* TRUE if it was drawn. */ int sx, sy; /* Offset of canvas from top-left * corner of the window when we * were drawn. */ }; #define MARQ_CONF_VISIBLE 0x0001 static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BOOLEAN, "-visible", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeMarquee_, visible), 0, (ClientData) NULL, MARQ_CONF_VISIBLE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; /* *---------------------------------------------------------------------- * * TreeMarquee_Init -- * * Perform marquee-related initialization when a new TreeCtrl is * created. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ int TreeMarquee_Init( TreeCtrl *tree /* Widget info. */ ) { TreeMarquee marquee; marquee = (TreeMarquee) ckalloc(sizeof(TreeMarquee_)); memset(marquee, '\0', sizeof(TreeMarquee_)); marquee->tree = tree; marquee->optionTable = Tk_CreateOptionTable(tree->interp, optionSpecs); if (Tk_InitOptions(tree->interp, (char *) marquee, marquee->optionTable, tree->tkwin) != TCL_OK) { WFREE(marquee, TreeMarquee_); return TCL_ERROR; } tree->marquee = marquee; return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeMarquee_Free -- * * Free marquee-related resources when a TreeCtrl is deleted. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeMarquee_Free( TreeMarquee marquee /* Marquee token. */ ) { Tk_FreeConfigOptions((char *) marquee, marquee->optionTable, marquee->tree->tkwin); WFREE(marquee, TreeMarquee_); } /* *---------------------------------------------------------------------- * * TreeMarquee_Display -- * * Draw the selection rectangle if it is not already displayed and if * it's -visible option is TRUE. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeMarquee_Display( TreeMarquee marquee /* Marquee token. */ ) { TreeCtrl *tree = marquee->tree; if (!marquee->onScreen && marquee->visible) { marquee->sx = 0 - tree->xOrigin; marquee->sy = 0 - tree->yOrigin; TreeMarquee_Draw(marquee, Tk_WindowId(tree->tkwin), marquee->sx, marquee->sy); marquee->onScreen = TRUE; } } /* *---------------------------------------------------------------------- * * TreeMarquee_Undisplay -- * * Erase the selection rectangle if it is displayed. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeMarquee_Undisplay( TreeMarquee marquee /* Marquee token. */ ) { TreeCtrl *tree = marquee->tree; if (marquee->onScreen) { TreeMarquee_Draw(marquee, Tk_WindowId(tree->tkwin), marquee->sx, marquee->sy); marquee->onScreen = FALSE; } } /* *---------------------------------------------------------------------- * * TreeMarquee_Draw -- * * Draw (or erase) the selection rectangle. * * Results: * None. * * Side effects: * Stuff is drawn (or erased, since this is XOR drawing). * *---------------------------------------------------------------------- */ void TreeMarquee_Draw( TreeMarquee marquee, /* Marquee token. */ Drawable drawable, /* Where to draw. */ int x1, int y1 /* Offset of canvas from top-left corner * of the window. */ ) { TreeCtrl *tree = marquee->tree; int x, y, w, h; DotState dotState; x = MIN(marquee->x1, marquee->x2); w = abs(marquee->x1 - marquee->x2) + 1; y = MIN(marquee->y1, marquee->y2); h = abs(marquee->y1 - marquee->y2) + 1; DotRect_Setup(tree, drawable, &dotState); DotRect_Draw(&dotState, x1 + x, y1 + y, w, h); DotRect_Restore(&dotState); } /* *---------------------------------------------------------------------- * * Marquee_Config -- * * This procedure is called to process an objc/objv list to set * configuration options for a Marquee. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then an error message is left in interp's result. * * Side effects: * Configuration information, such as text string, colors, font, * etc. get set for marquee; old resources get freed, if there * were any. Display changes may occur. * *---------------------------------------------------------------------- */ static int Marquee_Config( TreeMarquee marquee, /* Marquee record. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = marquee->tree; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int mask; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) marquee, marquee->optionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* xxx */ Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* xxx */ Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } if (mask & MARQ_CONF_VISIBLE) { TreeMarquee_Undisplay(marquee); TreeMarquee_Display(marquee); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeMarqueeCmd -- * * This procedure is invoked to process the [marquee] widget * command. See the user documentation for details on what it * does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeMarqueeCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = (TreeCtrl *) clientData; TreeMarquee marquee = tree->marquee; static CONST84 char *commandNames[] = { "anchor", "cget", "configure", "coords", "corner", "identify", (char *) NULL }; enum { COMMAND_ANCHOR, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_COORDS, COMMAND_CORNER, COMMAND_IDENTIFY }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T marquee anchor ?x y?*/ case COMMAND_ANCHOR: { int x, y; if (objc != 3 && objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "?x y?"); return TCL_ERROR; } if (objc == 3) { FormatResult(interp, "%d %d", marquee->x1, marquee->y1); break; } if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) return TCL_ERROR; if ((x == marquee->x1) && (y == marquee->y1)) break; TreeMarquee_Undisplay(tree->marquee); marquee->x1 = x; marquee->y1 = y; TreeMarquee_Display(tree->marquee); break; } /* T marquee cget option */ case COMMAND_CGET: { Tcl_Obj *resultObjPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(interp, (char *) marquee, marquee->optionTable, objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T marquee configure ?option? ?value? ?option value ...? */ case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?option? ?value?"); return TCL_ERROR; } if (objc <= 4) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) marquee, marquee->optionTable, (objc == 3) ? (Tcl_Obj *) NULL : objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } return Marquee_Config(marquee, objc - 3, objv + 3); } /* T marquee coords ?x y x y? */ case COMMAND_COORDS: { int x1, y1, x2, y2; if (objc != 3 && objc != 7) { Tcl_WrongNumArgs(interp, 3, objv, "?x y x y?"); return TCL_ERROR; } if (objc == 3) { FormatResult(interp, "%d %d %d %d", marquee->x1, marquee->y1, marquee->x2, marquee->y2); break; } if (Tcl_GetIntFromObj(interp, objv[3], &x1) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y1) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[5], &x2) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[6], &y2) != TCL_OK) return TCL_ERROR; if (x1 == marquee->x1 && y1 == marquee->y1 && x2 == marquee->x2 && y2 == marquee->y2) break; TreeMarquee_Undisplay(tree->marquee); marquee->x1 = x1; marquee->y1 = y1; marquee->x2 = x2; marquee->y2 = y2; TreeMarquee_Display(tree->marquee); break; } /* T marquee corner ?x y?*/ case COMMAND_CORNER: { int x, y; if (objc != 3 && objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "?x y?"); return TCL_ERROR; } if (objc == 3) { FormatResult(interp, "%d %d", marquee->x2, marquee->y2); break; } if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) return TCL_ERROR; if (x == marquee->x2 && y == marquee->y2) break; TreeMarquee_Undisplay(tree->marquee); marquee->x2 = x; marquee->y2 = y; TreeMarquee_Display(tree->marquee); break; } /* T marquee identify */ case COMMAND_IDENTIFY: { int x1, y1, x2, y2, n = 0; int totalWidth = Tree_TotalWidth(tree); int totalHeight = Tree_TotalHeight(tree); TreeItemList items; Tcl_Obj *listObj; if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } x1 = MIN(marquee->x1, marquee->x2); x2 = MAX(marquee->x1, marquee->x2); y1 = MIN(marquee->y1, marquee->y2); y2 = MAX(marquee->y1, marquee->y2); if (x2 <= 0) break; if (x1 >= totalWidth) break; if (y2 <= 0) break; if (y1 >= totalHeight) break; if (x1 < 0) x1 = 0; if (x2 > totalWidth) x2 = totalWidth; if (y1 < 0) y1 = 0; if (y2 > totalHeight) y2 = totalHeight; Tree_ItemsInArea(tree, &items, x1, y1, x2, y2); if (TreeItemList_Count(&items) == 0) { TreeItemList_Free(&items); break; } listObj = Tcl_NewListObj(0, NULL); for (n = 0; n < TreeItemList_Count(&items); n++) { Tcl_Obj *subListObj = Tcl_NewListObj(0, NULL); TreeItem item = TreeItemList_Nth(&items, n); Tcl_ListObjAppendElement(interp, subListObj, TreeItem_ToObj(tree, item)); TreeItem_Identify2(tree, item, x1, y1, x2, y2, subListObj); Tcl_ListObjAppendElement(interp, listObj, subListObj); } TreeItemList_Free(&items); Tcl_SetObjResult(interp, listObj); break; } } return TCL_OK; } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/generic/qebind.h0000644000175000017500000000573410562100026024107 0ustar domibeldomibel/* * qebind.h -- * * This module is the header for quasi-events. * * Copyright (c) 2002-2006 Tim Baker * * RCS: @(#) $Id: qebind.h,v 1.1 2007-02-06 13:18:14 barre Exp $ */ #ifndef INCLUDED_QEBIND_H #define INCLUDED_QEBIND_H typedef struct QE_BindingTable_ *QE_BindingTable; /* Pass to QE_BindEvent */ typedef struct QE_Event { int type; int detail; ClientData clientData; } QE_Event; typedef struct QE_ExpandArgs { QE_BindingTable bindingTable; char which; ClientData object; Tcl_DString *result; int event; int detail; ClientData clientData; } QE_ExpandArgs; typedef void (*QE_ExpandProc)(QE_ExpandArgs *args); extern QE_BindingTable bindingTable; extern int debug_bindings; extern int QE_BindInit(Tcl_Interp *interp); extern QE_BindingTable QE_CreateBindingTable(Tcl_Interp *interp); extern void QE_DeleteBindingTable(QE_BindingTable bindingTable); extern int QE_InstallEvent(QE_BindingTable bindingTable, char *name, QE_ExpandProc expand); extern int QE_InstallDetail(QE_BindingTable bindingTable, char *name, int eventType, QE_ExpandProc expand); extern int QE_CreateBinding(QE_BindingTable bindingTable, ClientData object, char *eventString, char *command, int append); extern int QE_DeleteBinding(QE_BindingTable bindingTable, ClientData object, char *eventString); extern int QE_GetBinding(QE_BindingTable bindingTable, ClientData object, char *eventString); extern int QE_GetAllBindings(QE_BindingTable bindingTable, ClientData object); extern int QE_GetEventNames(QE_BindingTable bindingTable); extern int QE_GetDetailNames(QE_BindingTable bindingTable, char *eventName); extern int QE_BindEvent(QE_BindingTable bindingTable, QE_Event *eventPtr); extern void QE_ExpandDouble(double number, Tcl_DString *result); extern void QE_ExpandNumber(long number, Tcl_DString *result); extern void QE_ExpandString(char *string, Tcl_DString *result); extern void QE_ExpandEvent(QE_BindingTable bindingTable, int eventType, Tcl_DString *result); extern void QE_ExpandDetail(QE_BindingTable bindingTable, int event, int detail, Tcl_DString *result); extern void QE_ExpandPattern(QE_BindingTable bindingTable, int eventType, int detail, Tcl_DString *result); extern void QE_ExpandUnknown(char which, Tcl_DString *result); extern int QE_BindCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_ConfigureCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_GenerateCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_InstallCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_UnbindCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_UninstallCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_LinkageCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); #endif /* INCLUDED_QEBIND_H */ kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/TkTreeCtrl.cmake0000644000175000017500000000423111037221317024101 0ustar domibeldomibelmacro(TkTreeCtrl_GET_LIBRARY supported sources include_path libs) if(DEFINED ${supported}) set(default_val ${supported}) else(DEFINED ${supported}) set(default_val 0) endif(DEFINED ${supported}) # Visual Studio 6 does not support/provide uxtheme.h # Borland fails on tkTreeDrag.c # (http://public.kitware.com/pipermail/kwwidgets/2007-August/000491.html) if(CMAKE_GENERATOR MATCHES "Visual Studio 6" OR BORLAND) set(default_val 0) endif(CMAKE_GENERATOR MATCHES "Visual Studio 6" OR BORLAND) option(${supported} "Enable TkTreeCtrl support in KWWidgets." ${default_val}) mark_as_advanced(${supported}) set(${sources}) set(${include_path}) set(${libs}) if(${supported}) set(_tktreectrl_path "${KWWidgets_SOURCE_DIR}/Utilities/TkTreeCtrl") set(_tktreectrl_include_path ${VTK_TK_INTERNAL_DIR} ${_tktreectrl_path}/generic ) set(_tktreectrl_srcs ${_tktreectrl_path}/generic/qebind.c ${_tktreectrl_path}/generic/tkTreeColumn.c ${_tktreectrl_path}/generic/tkTreeCtrl.c ${_tktreectrl_path}/generic/tkTreeDisplay.c ${_tktreectrl_path}/generic/tkTreeDrag.c ${_tktreectrl_path}/generic/tkTreeElem.c ${_tktreectrl_path}/generic/tkTreeItem.c ${_tktreectrl_path}/generic/tkTreeMarquee.c ${_tktreectrl_path}/generic/tkTreeNotify.c ${_tktreectrl_path}/generic/tkTreeStyle.c ${_tktreectrl_path}/generic/tkTreeTheme.c ${_tktreectrl_path}/generic/tkTreeUtils.c ) if(WIN32) set(_tktreectrl_win32_srcs ${_tktreectrl_path}/shellicon/shellicon.c ) set(_tktreectrl_srcs ${_tktreectrl_srcs} ${_tktreectrl_win32_srcs}) endif(WIN32) set_source_files_properties(${_tktreectrl_srcs} PROPERTIES LANGUAGE C) if(WIN32) set_source_files_properties(${_tktreectrl_srcs} PROPERTIES COMPILE_FLAGS -DSTDC_HEADERS) endif(WIN32) set(_tktreectrl_srcs ${_tktreectrl_srcs} ${_tktreectrl_path}/vtkKWTkTreeCtrlInit.cxx ) set(${sources} ${_tktreectrl_srcs}) set(${include_path} ${_tktreectrl_include_path}) set(${libs}) endif(${supported}) endmacro(TkTreeCtrl_GET_LIBRARY) kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/vtkKWTkTreeCtrlInit.h0000644000175000017500000000266410562100026025066 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTkTreeCtrlInit.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWTkTreeCtrlInit - class used to initialize TkTreeCtrl // .SECTION Description // This class is used to initialize the TkTreeCtrl library. #ifndef __vtkKWTkTreeCtrlInit_h #define __vtkKWTkTreeCtrlInit_h #include "vtkObject.h" #include "vtkKWWidgets.h" // Needed for export symbols directives #include "vtkTcl.h" // Needed for Tcl interpreter class KWWidgets_EXPORT vtkKWTkTreeCtrlInit : public vtkObject { public: static vtkKWTkTreeCtrlInit* New(); vtkTypeRevisionMacro(vtkKWTkTreeCtrlInit,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Load the TkTreeCtrl library. static void Initialize(Tcl_Interp*); protected: vtkKWTkTreeCtrlInit() {}; ~vtkKWTkTreeCtrlInit() {}; static int Initialized; private: vtkKWTkTreeCtrlInit(const vtkKWTkTreeCtrlInit&); // Not implemented. void operator=(const vtkKWTkTreeCtrlInit&); // Not implemented. }; #endif kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/vtkKWTkTreeCtrlInit.cxx0000644000175000017500000000417510562100026025440 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTkTreeCtrlInit.cxx,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkKWTkTreeCtrlInit.h" #include "vtkObjectFactory.h" #include "vtkKWTkUtilities.h" #include "vtkTk.h" #include "Utilities/TkTreeCtrl/vtkKWTkTreeCtrlTclLibrary.h" extern "C" int Treectrl_Init(Tcl_Interp *interp); #ifdef _WIN32 extern "C" int Shellicon_Init(Tcl_Interp *interp); #endif //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWTkTreeCtrlInit ); vtkCxxRevisionMacro(vtkKWTkTreeCtrlInit, "$Revision: 1.1 $"); int vtkKWTkTreeCtrlInit::Initialized = 0; //---------------------------------------------------------------------------- void vtkKWTkTreeCtrlInit::Initialize(Tcl_Interp* interp) { if (vtkKWTkTreeCtrlInit::Initialized) { return; } if (!interp) { vtkGenericWarningMacro( "An interpreter is needed to initialize the TkTreeCtrl library."); return; } vtkKWTkTreeCtrlInit::Initialized = 1; Treectrl_Init(interp); #ifdef _WIN32 Shellicon_Init(interp); #endif // Evaluate the library vtkKWTkUtilities::EvaluateEncodedString( interp, file_filelist_bindings_tcl, file_filelist_bindings_tcl_length, file_filelist_bindings_tcl_decoded_length); vtkKWTkUtilities::EvaluateEncodedString( interp, file_treectrl_tcl, file_treectrl_tcl_length, file_treectrl_tcl_decoded_length); vtkKWTkUtilities::EvaluateSimpleString( interp, "set ::treectrl_library \"\"\n"); } //---------------------------------------------------------------------------- void vtkKWTkTreeCtrlInit::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/README.txt0000644000175000017500000000040410562100026022543 0ustar domibeldomibelCurrent maintainer: Tim Baker (treectrl@users.sourceforge.net) Website: http://tktreectrl.sourceforge.net/ An extra help document with examples and pictures is available from the main website: http://tktreectrl.sourceforge.net/Understanding%20TkTreeCtrl.html kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/README.kww.txt0000644000175000017500000000310610562100026023354 0ustar domibeldomibelThe changes to TkTreeCtrlk for KWWidgets are: - in generic/tkTreeCtrl.c replace: tcl_findLibrary treectrl " PACKAGE_PATCHLEVEL " " PACKAGE_PATCHLEVEL " treectrl.tcl TREECTRL_LIBRARY treectrl_library\n\ with: tcl_findLibrary treectrl 2.2.1 2.2.1 treectrl.tcl TREECTRL_LIBRARY treectrl_library\n\ and replace: if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_PATCHLEVEL) != TCL_OK) { with: if (Tcl_PkgProvide(interp, "treectrl", "2.2.1") != TCL_OK) { - in shellicon/shellicon.c replace: if (Tcl_PkgRequire(interp, "treectrl", PACKAGE_PATCHLEVEL, TRUE) == NULL) with: if (Tcl_PkgRequire(interp, "treectrl", "2.2.1", TRUE) == NULL) replace: if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_PATCHLEVEL) != TCL_OK) { with: if (Tcl_PkgProvide(interp, "treectrl", "2.2.1") != TCL_OK) { replace: TreeCtrlStubs *stubs; #define TreeCtrl_RegisterElementType(i,t) \ with: TreeCtrlStubs *stubs; extern int BooleanCO_Init(Tk_OptionSpec *, CONST char *); extern int TreeCtrl_RegisterElementType(Tcl_Interp *, ElementType *); #if 0 #define TreeCtrl_RegisterElementType(i,t) \ and: #define StringTableCO_Init(ot,on,ta) \ stubs->StringTableCO_Init(ot,on,ta) with: #define StringTableCO_Init(ot,on,ta) \ stubs->StringTableCO_Init(ot,on,ta) #endif The aim here is to bypass the stubs by putting all #define foo \ stubs->foo inside a #if 0 ... #endif - in library/treectrl.tcl comment: source [file join [file dirname [info script]] filelist-bindings.tcl] - in tkTreeCtrl.h and qebind.c add the following two lines *before* any other #include: #include "vtkTcl.h" #include "vtkTk.h" kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/library/0000755000175000017500000000000011461110203022510 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/library/filelist-bindings.tcl0000644000175000017500000005326310562100027026637 0ustar domibeldomibel# RCS: @(#) $Id: filelist-bindings.tcl,v 1.1 2007-02-06 13:18:15 barre Exp $ bind TreeCtrlFileList { TreeCtrl::FileListEditCancel %W TreeCtrl::DoubleButton1 %W %x %y break } bind TreeCtrlFileList { set TreeCtrl::Priv(selectMode) toggle TreeCtrl::FileListButton1 %W %x %y break } bind TreeCtrlFileList { set TreeCtrl::Priv(selectMode) add TreeCtrl::FileListButton1 %W %x %y break } bind TreeCtrlFileList { set TreeCtrl::Priv(selectMode) set TreeCtrl::FileListButton1 %W %x %y break } bind TreeCtrlFileList { TreeCtrl::FileListMotion1 %W %x %y break } bind TreeCtrlFileList { TreeCtrl::FileListLeave1 %W %x %y break } bind TreeCtrlFileList { TreeCtrl::FileListRelease1 %W %x %y break } ## Bindings for the Entry widget used for editing # Accept edit when we lose the focus bind TreeCtrlEntry { if {[winfo ismapped %W]} { TreeCtrl::EditClose [winfo parent %W] entry 1 0 } } # Accept edit on bind TreeCtrlEntry { TreeCtrl::EditClose [winfo parent %W] entry 1 1 break } # Cancel edit on , use break as we are doing a "closing" action # and don't want that propagated upwards bind TreeCtrlEntry { TreeCtrl::EditClose [winfo parent %W] entry 0 1 break } ## Bindings for the Text widget used for editing # Accept edit when we lose the focus bind TreeCtrlText { if {[winfo ismapped %W]} { TreeCtrl::EditClose [winfo parent %W] text 1 0 } } # Accept edit on bind TreeCtrlText { TreeCtrl::EditClose [winfo parent %W] text 1 1 break } # Cancel edit on , use break as we are doing a "closing" action # and don't want that propagated upwards bind TreeCtrlText { TreeCtrl::EditClose [winfo parent %W] text 0 1 break } namespace eval TreeCtrl { variable Priv set Priv(edit,delay) 500 } proc ::TreeCtrl::IsSensitive {T x y} { variable Priv set id [$T identify $x $y] if {[lindex $id 0] ne "item" || [llength $id] != 6} { return 0 } lassign $id where item arg1 arg2 arg3 arg4 if {![$T item enabled $item]} { return 0 } foreach list $Priv(sensitive,$T) { set C [lindex $list 0] set S [lindex $list 1] set eList [lrange $list 2 end] if {[$T column compare $arg2 != $C]} continue if {[$T item style set $item $C] ne $S} continue if {[lsearch -exact $eList $arg4] == -1} continue return 1 } return 0 } proc ::TreeCtrl::FileListButton1 {T x y} { variable Priv focus $T set id [$T identify $x $y] set marquee 0 set Priv(buttonMode) "" foreach e {text entry} { if {[winfo exists $T.$e] && [winfo ismapped $T.$e]} { EditClose $T $e 1 0 } } FileListEditCancel $T # Click outside any item if {$id eq ""} { set marquee 1 # Click in header } elseif {[lindex $id 0] eq "header"} { ButtonPress1 $T $x $y # Click in item } else { lassign $id where item arg1 arg2 arg3 arg4 switch $arg1 { button - line { ButtonPress1 $T $x $y } column { if {[IsSensitive $T $x $y]} { set Priv(drag,motion) 0 set Priv(drag,click,x) $x set Priv(drag,click,y) $y set Priv(drag,x) [$T canvasx $x] set Priv(drag,y) [$T canvasy $y] set Priv(drop) "" set Priv(drag,wasSel) [$T selection includes $item] set Priv(drag,C) $arg2 set Priv(drag,E) $arg4 $T activate $item if {$Priv(selectMode) eq "add"} { BeginExtend $T $item } elseif {$Priv(selectMode) eq "toggle"} { BeginToggle $T $item } elseif {![$T selection includes $item]} { BeginSelect $T $item } # Changing the selection might change the list if {[$T item id $item] eq ""} return # Click selected item to drag if {[$T selection includes $item]} { set Priv(buttonMode) drag } } else { set marquee 1 } } } } if {$marquee} { set Priv(buttonMode) marquee if {$Priv(selectMode) ne "set"} { set Priv(selection) [$T selection get] } else { $T selection clear set Priv(selection) {} } MarqueeBegin $T $x $y } return } proc ::TreeCtrl::FileListMotion1 {T x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { "drag" - "marquee" { set Priv(autoscan,command,$T) {FileListMotion %T %x %y} AutoScanCheck $T $x $y FileListMotion $T $x $y } default { Motion1 $T $x $y } } return } proc ::TreeCtrl::FileListMotion {T x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { "marquee" { MarqueeUpdate $T $x $y set select $Priv(selection) set deselect {} # Check items covered by the marquee foreach list [$T marque identify] { set item [lindex $list 0] if {![$T item enabled $item]} continue # Check covered columns in this item foreach sublist [lrange $list 1 end] { set column [lindex $sublist 0] set ok 0 # Check covered elements in this column foreach E [lrange $sublist 1 end] { foreach sList $Priv(sensitive,$T) { set sC [lindex $sList 0] set sS [lindex $sList 1] set sEList [lrange $sList 2 end] if {[$T column compare $column != $sC]} continue if {[$T item style set $item $sC] ne $sS} continue if {[lsearch -exact $sEList $E] == -1} continue set ok 1 break } } # Some sensitive elements in this column are covered if {$ok} { # Toggle selected status if {$Priv(selectMode) eq "toggle"} { set i [lsearch -exact $Priv(selection) $item] if {$i == -1} { lappend select $item } else { set i [lsearch -exact $select $item] set select [lreplace $select $i $i] } } else { lappend select $item } } } } $T selection modify $select all } "drag" { if {!$Priv(drag,motion)} { # Detect initial mouse movement if {(abs($x - $Priv(drag,click,x)) <= 4) && (abs($y - $Priv(drag,click,y)) <= 4)} return set Priv(selection) [$T selection get] set Priv(drop) "" $T dragimage clear # For each selected item, add some elements to the dragimage foreach I $Priv(selection) { foreach list $Priv(dragimage,$T) { set C [lindex $list 0] set S [lindex $list 1] if {[$T item style set $I $C] eq $S} { eval $T dragimage add $I $C [lrange $list 2 end] } } } set Priv(drag,motion) 1 TryEvent $T Drag begin {} } # Find the element under the cursor set drop "" set id [$T identify $x $y] if {[IsSensitive $T $x $y]} { set item [lindex $id 1] # If the item is not in the pre-drag selection # (i.e. not being dragged) and it is a directory, # see if we can drop on it if {[lsearch -exact $Priv(selection) $item] == -1} { if {[$T item order $item -visible] < $Priv(DirCnt,$T)} { set drop $item # We can drop if dragged item isn't an ancestor foreach item2 $Priv(selection) { if {[$T item isancestor $item2 $item]} { set drop "" break } } } } } # Select the directory under the cursor (if any) and deselect # the previous drop-directory (if any) $T selection modify $drop $Priv(drop) set Priv(drop) $drop # Show the dragimage in its new position set x [expr {[$T canvasx $x] - $Priv(drag,x)}] set y [expr {[$T canvasy $y] - $Priv(drag,y)}] $T dragimage offset $x $y $T dragimage configure -visible yes } default { Motion1 $T $x $y } } return } proc ::TreeCtrl::FileListLeave1 {T x y} { variable Priv # This gets called when I click the mouse on Unix, and buttonMode is unset if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { default { Leave1 $T $x $y } } return } proc ::TreeCtrl::FileListRelease1 {T x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { "marquee" { AutoScanCancel $T MarqueeEnd $T $x $y } "drag" { AutoScanCancel $T # Some dragging occurred if {$Priv(drag,motion)} { $T dragimage configure -visible no if {$Priv(drop) ne ""} { $T selection modify {} $Priv(drop) TryEvent $T Drag receive \ [list I $Priv(drop) l $Priv(selection)] } TryEvent $T Drag end {} } elseif {$Priv(selectMode) eq "toggle"} { # don't rename # Clicked/released a selected item, but didn't drag } elseif {$Priv(drag,wasSel)} { set I [$T item id active] set C $Priv(drag,C) set E $Priv(drag,E) set S [$T item style set $I $C] set ok 0 foreach list $Priv(edit,$T) { set eC [lindex $list 0] set eS [lindex $list 1] set eEList [lrange $list 2 end] if {[$T column compare $C != $eC]} continue if {$S ne $eS} continue if {[lsearch -exact $eEList $E] == -1} continue set ok 1 break } if {$ok} { FileListEditCancel $T set Priv(editId,$T) \ [after $Priv(edit,delay) [list ::TreeCtrl::FileListEdit $T $I $C $E]] } } } default { Release1 $T $x $y } } set Priv(buttonMode) "" return } proc ::TreeCtrl::FileListEdit {T I C E} { variable Priv array unset Priv editId,$T set lines [$T item element cget $I $C $E -lines] if {$lines eq ""} { set lines [$T element cget $E -lines] } # Scroll item into view $T see $I ; update # Multi-line edit if {$lines ne "1"} { scan [$T item bbox $I $C] "%d %d %d %d" x1 y1 x2 y2 set S [$T item style set $I $C] set padx [$T style layout $S $E -padx] if {[llength $padx] == 2} { set padw [lindex $padx 0] set pade [lindex $padx 1] } else { set pade [set padw $padx] } foreach E2 [$T style elements $S] { if {[lsearch -exact [$T style layout $S $E2 -union] $E] == -1} continue foreach option {-padx -ipadx} { set pad [$T style layout $S $E2 $option] if {[llength $pad] == 2} { incr padw [lindex $pad 0] incr pade [lindex $pad 1] } else { incr padw $pad incr pade $pad } } } TextExpanderOpen $T $I $C $E [expr {$x2 - $x1 - $padw - $pade}] # Single-line edit } else { EntryExpanderOpen $T $I $C $E } TryEvent $T Edit begin [list I $I C $C E $E] return } proc ::TreeCtrl::FileListEditCancel {T} { variable Priv if {[info exists Priv(editId,$T)]} { after cancel $Priv(editId,$T) array unset Priv editId,$T } return } proc ::TreeCtrl::SetDragImage {T listOfLists} { variable Priv foreach list $listOfLists { set column [lindex $list 0] set style [lindex $list 1] set elements [lrange $list 2 end] if {[$T column id $column] eq ""} { error "column \"$column\" doesn't exist" } if {[lsearch -exact [$T style names] $style] == -1} { error "style \"$style\" doesn't exist" } foreach element $elements { if {[lsearch -exact [$T element names] $element] == -1} { error "element \"$element\" doesn't exist" } } } set Priv(dragimage,$T) $listOfLists return } proc ::TreeCtrl::SetEditable {T listOfLists} { variable Priv foreach list $listOfLists { set column [lindex $list 0] set style [lindex $list 1] set elements [lrange $list 2 end] if {[$T column id $column] eq ""} { error "column \"$column\" doesn't exist" } if {[lsearch -exact [$T style names] $style] == -1} { error "style \"$style\" doesn't exist" } foreach element $elements { if {[lsearch -exact [$T element names] $element] == -1} { error "element \"$element\" doesn't exist" } if {[$T element type $element] ne "text"} { error "element \"$element\" is not of type \"text\"" } } } set Priv(edit,$T) $listOfLists return } proc ::TreeCtrl::SetSensitive {T listOfLists} { variable Priv foreach list $listOfLists { set column [lindex $list 0] set style [lindex $list 1] set elements [lrange $list 2 end] if {[$T column id $column] eq ""} { error "column \"$column\" doesn't exist" } if {[lsearch -exact [$T style names] $style] == -1} { error "style \"$style\" doesn't exist" } foreach element $elements { if {[lsearch -exact [$T element names] $element] == -1} { error "element \"$element\" doesn't exist" } } } set Priv(sensitive,$T) $listOfLists return } proc ::TreeCtrl::EntryOpen {T item column element} { variable Priv set Priv(entry,$T,item) $item set Priv(entry,$T,column) $column set Priv(entry,$T,element) $element set Priv(entry,$T,focus) [focus] # Get window coords of the Element scan [$T item bbox $item $column $element] "%d %d" x y # Get the font used by the Element set font [$T item element perstate $item $column $element -font] if {$font eq ""} { set font [$T cget -font] } # Get the text used by the Element. Could check master Element too. set text [$T item element cget $item $column $element -text] # Create the Entry widget if needed set e $T.entry if {[winfo exists $e]} { $e delete 0 end } else { entry $e -borderwidth 1 -relief solid -highlightthickness 0 bindtags $e [linsert [bindtags $e] 1 TreeCtrlEntry] } # Pesky MouseWheel $T notify bind $e { TreeCtrl::EditClose %T entry 0 1 } $e configure -font $font $e insert end $text $e selection range 0 end set ebw [$e cget -borderwidth] set ex [expr {$x - $ebw - 1}] place $e -x $ex -y [expr {$y - $ebw - 1}] -bordermode outside # Make the Entry as wide as the text plus "W" but keep it within the # TreeCtrl borders set width [font measure $font ${text}W] set width [expr {$width + ($ebw + 1) * 2}] scan [$T contentbox] "%d %d %d %d" left top right bottom if {$ex + $width > $right} { set width [expr {$right - $ex}] } scan [$T item bbox $item $column] "%d %d %d %d" left top right bottom if {$ex + $width > $right} { set width [expr {$right - $ex}] } place configure $e -width $width focus $e return } # Like EntryOpen, but Entry widget expands/shrinks during typing proc ::TreeCtrl::EntryExpanderOpen {T item column element} { variable Priv set Priv(entry,$T,item) $item set Priv(entry,$T,column) $column set Priv(entry,$T,element) $element set Priv(entry,$T,focus) [focus] # Get window coords of the Element scan [$T item bbox $item $column $element] "%d %d" x y # Get the font used by the Element set font [$T item element perstate $item $column $element -font] if {$font eq ""} { set font [$T cget -font] } set Priv(entry,$T,font) $font # Get the text used by the Element. Could check master Element too. set text [$T item element cget $item $column $element -text] # Create the Entry widget if needed set e $T.entry if {[winfo exists $e]} { $e delete 0 end } else { entry $e -borderwidth 1 -highlightthickness 0 \ -selectborderwidth 0 -relief solid bindtags $e [linsert [bindtags $e] 1 TreeCtrlEntry] # Resize as user types bind $e { after idle [list TreeCtrl::EntryExpanderKeypress [winfo parent %W]] } } # Pesky MouseWheel $T notify bind $e { TreeCtrl::EditClose %T entry 0 1 } $e configure -font $font -background [$T cget -background] $e insert end $text $e selection range 0 end set ebw [$e cget -borderwidth] set ex [expr {$x - $ebw - 1}] place $e -x $ex -y [expr {$y - $ebw - 1}] \ -bordermode outside # Make the Entry as wide as the text plus "W" but keep it within the # TreeCtrl borders set width [font measure $font ${text}W] set width [expr {$width + ($ebw + 1) * 2}] scan [$T contentbox] "%d %d %d %d" left top right bottom if {$ex + $width > $right} { set width [expr {$right - $ex}] } place configure $e -width $width focus $e return } proc ::TreeCtrl::EditClose {T type accept {refocus 0}} { variable Priv set w $T.$type # We need the double-idle to get winfo ismapped to report properly # so this don't get the FocusOut following Escape immediately update idletasks place forget $w focus $T update idletasks if {$accept} { if {$type eq "entry"} { set t [$w get] } else { set t [$w get 1.0 end-1c] } TryEvent $T Edit accept \ [list I $Priv($type,$T,item) C $Priv($type,$T,column) \ E $Priv($type,$T,element) t $t] } $T notify unbind $w TryEvent $T Edit end \ [list I $Priv($type,$T,item) C $Priv($type,$T,column) \ E $Priv($type,$T,element)] if {$refocus} { focus $Priv($type,$T,focus) } return } proc ::TreeCtrl::EntryExpanderKeypress {T} { variable Priv set font $Priv(entry,$T,font) set text [$T.entry get] set ebw [$T.entry cget -borderwidth] set ex [winfo x $T.entry] set width [font measure $font ${text}W] set width [expr {$width + ($ebw + 1) * 2}] scan [$T contentbox] "%d %d %d %d" left top right bottom if {$ex + $width > $right} { set width [expr {$right - $ex}] } place configure $T.entry -width $width return } proc ::TreeCtrl::TextOpen {T item column element {width 0} {height 0}} { variable Priv set Priv(text,$T,item) $item set Priv(text,$T,column) $column set Priv(text,$T,element) $element set Priv(text,$T,focus) [focus] # Get window coords of the Element scan [$T item bbox $item $column $element] "%d %d %d %d" x1 y1 x2 y2 # Get the font used by the Element set font [$T item element perstate $item $column $element -font] if {$font eq ""} { set font [$T cget -font] } # Get the text used by the Element. Could check master Element too. set text [$T item element cget $item $column $element -text] set justify [$T element cget $element -justify] if {$justify eq ""} { set justify left } set wrap [$T element cget $element -wrap] if {$wrap eq ""} { set wrap word } # Create the Text widget if needed set w $T.text if {[winfo exists $w]} { $w delete 1.0 end } else { text $w -borderwidth 1 -highlightthickness 0 -relief solid bindtags $w [linsert [bindtags $w] 1 TreeCtrlText] } # Pesky MouseWheel $T notify bind $w { TreeCtrl::EditClose %T text 0 1 } $w tag configure TAG -justify $justify $w configure -font $font -background [$T cget -background] -wrap $wrap $w insert end $text $w tag add sel 1.0 end $w tag add TAG 1.0 end set tbw [$w cget -borderwidth] set tx [expr {$x1 - $tbw - 1}] place $w -x $tx -y [expr {$y1 - $tbw - 1}] \ -width [expr {$x2 - $x1 + ($tbw + 1) * 2}] \ -height [expr {$y2 - $y1 + ($tbw + 1) * 2}] \ -bordermode outside focus $w return } # Like TextOpen, but Text widget expands/shrinks during typing proc ::TreeCtrl::TextExpanderOpen {T item column element width} { variable Priv set Priv(text,$T,item) $item set Priv(text,$T,column) $column set Priv(text,$T,element) $element set Priv(text,$T,focus) [focus] # Get window coords of the Element scan [$T item bbox $item $column $element] "%d %d %d %d" x1 y1 x2 y2 set Priv(text,$T,center) [expr {$x1 + ($x2 - $x1) / 2}] # Get the font used by the Element set font [$T item element perstate $item $column $element -font] if {$font eq ""} { set font [$T cget -font] } # Get the text used by the Element. Could check master Element too. set text [$T item element cget $item $column $element -text] set justify [$T element cget $element -justify] if {$justify eq ""} { set justify left } set wrap [$T element cget $element -wrap] if {$wrap eq ""} { set wrap word } # Create the Text widget if needed set w $T.text if {[winfo exists $w]} { $w delete 1.0 end } else { text $w -borderwidth 1 -highlightthickness 0 \ -selectborderwidth 0 -relief solid bindtags $w [linsert [bindtags $w] 1 TreeCtrlText] # Resize as user types bind $w { after idle TreeCtrl::TextExpanderKeypress [winfo parent %W] } } # Pesky MouseWheel $T notify bind $w { TreeCtrl::EditClose %T text 0 1 } $w tag configure TAG -justify $justify $w configure -font $font -background [$T cget -background] -wrap $wrap $w insert end $text $w tag add sel 1.0 end $w tag add TAG 1.0 end set Priv(text,$T,font) $font set Priv(text,$T,justify) $justify set Priv(text,$T,width) $width scan [textlayout $font $text -justify $justify -width $width] \ "%d %d" width height set tbw [$w cget -borderwidth] incr tbw place $w -x [expr {$x1 - $tbw}] -y [expr {$y1 - $tbw}] \ -width [expr {$width + $tbw * 2}] \ -height [expr {$height + $tbw * 2}] \ -bordermode outside focus $w return } proc ::TreeCtrl::TextExpanderKeypress {T} { variable Priv set font $Priv(text,$T,font) set justify $Priv(text,$T,justify) set width $Priv(text,$T,width) set center $Priv(text,$T,center) set text [$T.text get 1.0 end-1c] scan [textlayout $font $text -justify $justify -width $width] \ "%d %d" width height set tbw [$T.text cget -borderwidth] incr tbw place configure $T.text \ -x [expr {$center - ($width + $tbw * 2) / 2}] \ -width [expr {$width + $tbw * 2}] \ -height [expr {$height + $tbw * 2}] $T.text tag add TAG 1.0 end return } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/library/treectrl.tcl0000644000175000017500000011750710562100027025057 0ustar domibeldomibel# RCS: @(#) $Id: treectrl.tcl,v 1.1 2007-02-06 13:18:15 barre Exp $ bind TreeCtrl { TreeCtrl::CursorCheck %W %x %y TreeCtrl::MotionInHeader %W %x %y } bind TreeCtrl { TreeCtrl::CursorCancel %W TreeCtrl::MotionInHeader %W } bind TreeCtrl { TreeCtrl::ButtonPress1 %W %x %y } bind TreeCtrl { TreeCtrl::DoubleButton1 %W %x %y } bind TreeCtrl { TreeCtrl::Motion1 %W %x %y } bind TreeCtrl { TreeCtrl::Release1 %W %x %y } bind TreeCtrl { set TreeCtrl::Priv(buttonMode) normal TreeCtrl::BeginExtend %W [%W item id {nearest %x %y}] } # Command-click should provide a discontinuous selection on OSX switch -- [tk windowingsystem] { "aqua" { set modifier Command } default { set modifier Control } } bind TreeCtrl <$modifier-ButtonPress-1> { set TreeCtrl::Priv(buttonMode) normal TreeCtrl::BeginToggle %W [%W item id {nearest %x %y}] } bind TreeCtrl { TreeCtrl::Leave1 %W %x %y } bind TreeCtrl { TreeCtrl::Enter1 %W %x %y } bind TreeCtrl { TreeCtrl::SetActiveItem %W [TreeCtrl::UpDown %W active -1] } bind TreeCtrl { TreeCtrl::Extend %W above } bind TreeCtrl { TreeCtrl::SetActiveItem %W [TreeCtrl::UpDown %W active 1] } bind TreeCtrl { TreeCtrl::Extend %W below } bind TreeCtrl { TreeCtrl::SetActiveItem %W [TreeCtrl::LeftRight %W active -1] } bind TreeCtrl { TreeCtrl::Extend %W left } bind TreeCtrl { %W xview scroll -1 pages } bind TreeCtrl { TreeCtrl::SetActiveItem %W [TreeCtrl::LeftRight %W active 1] } bind TreeCtrl { TreeCtrl::Extend %W right } bind TreeCtrl { %W xview scroll 1 pages } bind TreeCtrl { %W yview scroll -1 pages if {[%W item id {nearest 0 0}] ne ""} { %W activate {nearest 0 0} } } bind TreeCtrl { %W yview scroll 1 pages if {[%W item id {nearest 0 0}] ne ""} { %W activate {nearest 0 0} } } bind TreeCtrl { %W xview scroll -1 pages } bind TreeCtrl { %W xview scroll 1 pages } bind TreeCtrl { %W xview moveto 0 } bind TreeCtrl { %W xview moveto 1 } bind TreeCtrl { TreeCtrl::SetActiveItem %W [%W item id {first visible state enabled}] } bind TreeCtrl { TreeCtrl::DataExtend %W [%W item id {first visible state enabled}] } bind TreeCtrl { TreeCtrl::SetActiveItem %W [%W item id {last visible state enabled}] } bind TreeCtrl { TreeCtrl::DataExtend %W [%W item id {last visible state enabled}] } bind TreeCtrl <> { if {[string equal [selection own -displayof %W] "%W"]} { clipboard clear -displayof %W clipboard append -displayof %W [selection get -displayof %W] } } bind TreeCtrl { TreeCtrl::BeginSelect %W [%W item id active] } bind TreeCtrl { TreeCtrl::BeginSelect %W [%W item id active] } bind TreeCtrl { TreeCtrl::BeginExtend %W [%W item id active] } bind TreeCtrl { TreeCtrl::BeginExtend %W [%W item id active] } bind TreeCtrl { TreeCtrl::Cancel %W } bind TreeCtrl { TreeCtrl::SelectAll %W } bind TreeCtrl { if {[string compare [%W cget -selectmode] "browse"]} { %W selection clear } } bind TreeCtrl { %W item expand [%W item id active] } bind TreeCtrl { %W item collapse [%W item id active] } bind TreeCtrl { %W item toggle [%W item id active] } # Additional Tk bindings that aren't part of the Motif look and feel: bind TreeCtrl { TreeCtrl::ScanMark %W %x %y } bind TreeCtrl { TreeCtrl::ScanDrag %W %x %y } if {$tcl_platform(platform) eq "windows"} { bind TreeCtrl { TreeCtrl::ScanMark %W %x %y } bind TreeCtrl { TreeCtrl::ScanDrag %W %x %y } } # MouseWheel if {[string equal "x11" [tk windowingsystem]]} { # Support for mousewheels on Linux/Unix commonly comes through mapping # the wheel to the extended buttons. If you have a mousewheel, find # Linux configuration info at: # http://www.inria.fr/koala/colas/mouse-wheel-scroll/ bind TreeCtrl <4> { if {!$tk_strictMotif} { %W yview scroll -5 units } } bind TreeCtrl <5> { if {!$tk_strictMotif} { %W yview scroll 5 units } } } elseif {[string equal [tk windowingsystem] "aqua"]} { bind TreeCtrl { %W yview scroll [expr {- (%D)}] units } } else { bind TreeCtrl { %W yview scroll [expr {- (%D / 120) * 4}] units } } namespace eval ::TreeCtrl { variable Priv array set Priv { prev {} } if {[info procs ::lassign] eq ""} { proc lassign {values args} { uplevel 1 [list foreach $args [linsert $values end {}] break] lrange $values [llength $args] end } } } # Retrieve filelist bindings from this dir #source [file join [file dirname [info script]] filelist-bindings.tcl] # ::TreeCtrl::ColumnCanResizeLeft -- # # Return 1 if the given column should be resized by the left edge. # # Arguments: # w The treectrl widget. # column The column. proc ::TreeCtrl::ColumnCanResizeLeft {w column} { if {[$w column cget $column -lock] eq "right"} { if {[$w column compare $column == "first visible lock right"]} { return 1 } if {[$w column compare $column == "last visible lock right"]} { return 1 } } return 0 } # ::TreeCtrl::ColumnCanMoveHere -- # # Return 1 if the given column can be moved before another. # # Arguments: # w The treectrl widget. # column The column. # before The column to place 'column' before. proc ::TreeCtrl::ColumnCanMoveHere {w column before} { if {[$w column compare $column == $before] || ([$w column order $column] == [$w column order $before] - 1)} { return 0 } set lock [$w column cget $column -lock] return [expr {[$w column compare $before >= "first lock $lock"] && [$w column compare $before <= "last lock $lock next"]}] } # ::TreeCtrl::ColumnDragFindBefore -- # # This is called when dragging a column header. The result is 1 if the given # coordinates are near a column header before which the dragged column can # be moved. # # Arguments: # w The treectrl widget. # x Window x-coord. # y Window y-coord. # dragColumn The column being dragged. # indColumn_ Out: what to set -indicatorcolumn to. # indSide_ Out: what to set -indicatorside to. proc ::TreeCtrl::ColumnDragFindBefore {w x y dragColumn indColumn_ indSide_} { upvar $indColumn_ indColumn upvar $indSide_ indSide switch -- [$w column cget $dragColumn -lock] { left {set area left} none {set area content} right {set area right} } scan [$w bbox $area] "%d %d %d %d" minX y1 maxX y2 if {$x < $minX} { set x $minX } if {$x >= $maxX} { set x [expr {$maxX - 1}] } set id [$w identify $x $y] if {[lindex $id 0] ne "header"} { return 0 } set indColumn [lindex $id 1] set before $indColumn set prev [$w column id "$dragColumn prev visible"] set next [$w column id "$dragColumn next visible"] if {[$w column compare $indColumn == "tail"]} { set indSide left } elseif {$prev ne "" && [$w column compare $prev == $indColumn]} { set indSide left } elseif {$next ne "" && [$w column compare $next == $indColumn]} { set before [$w column id "$indColumn next visible"] set indSide right } else { scan [$w column bbox $indColumn] "%d %d %d %d" x1 y1 x2 y2 if {$x < $x1 + ($x2 - $x1) / 2} { set indSide left } else { set before [$w column id "$indColumn next visible"] set indSide right } } return [ColumnCanMoveHere $w $dragColumn $before] } # ::TreeCtrl::CursorAction -- # # If the given point is at the left or right edge of a resizable column, the # result is "column resize C". If the given point is in a header with -button # TRUE, the result is "column button C". # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::CursorAction {w x y} { variable Priv set id [$w identify $x $y] if {[lindex $id 0] eq "header"} { set column [lindex $id 1] set side [lindex $id 2] if {$side eq "left"} { if {[$w column compare $column == tail]} { set column2 [$w column id "last visible lock none"] if {$column2 ne "" && [$w column cget $column2 -resize]} { return "column resize $column2" } # Can't -resize or -button the tail column return "" } if {[ColumnCanResizeLeft $w $column]} { if {[$w column cget $column -resize]} { return "column resize $column" } } else { # Resize the previous column set lock [$w column cget $column -lock] if {[$w column compare $column != "first visible lock $lock"]} { set column2 [$w column id "$column prev visible"] if {[$w column cget $column2 -resize]} { return "column resize $column2" } } } } elseif {$side eq "right"} { if {![ColumnCanResizeLeft $w $column]} { if {[$w column cget $column -resize]} { return "column resize $column" } } } if {[$w column compare $column == "tail"]} { # nothing } elseif {[$w column cget $column -button]} { return "column button $column" } } return "" } # ::TreeCtrl::CursorCheck -- # # Sees if the given pointer coordinates are near the edge of a resizable # column in the header. If so and the treectrl's cursor is not already # set to sb_h_double_arrow, then the current cursor is saved and changed # to sb_h_double_arrow, and an [after] callback to CursorCheckAux is # scheduled. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::CursorCheck {w x y} { variable Priv set action [CursorAction $w $x $y] if {[lindex $action 1] ne "resize"} { CursorCancel $w return } set cursor sb_h_double_arrow if {$cursor ne [$w cget -cursor]} { if {![info exists Priv(cursor,$w)]} { set Priv(cursor,$w) [$w cget -cursor] } $w configure -cursor $cursor } if {[info exists Priv(cursor,afterId,$w)]} { after cancel $Priv(cursor,afterId,$w) } set Priv(cursor,afterId,$w) [after 150 [list TreeCtrl::CursorCheckAux $w]] return } # ::TreeCtrl::CursorCheckAux -- # # Get's the location of the pointer and calls CursorCheck if the treectrl's # cursor was previously set to sb_h_double_arrow. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::CursorCheckAux {w} { variable Priv set x [winfo pointerx $w] set y [winfo pointery $w] if {[info exists Priv(cursor,$w)]} { set x [expr {$x - [winfo rootx $w]}] set y [expr {$y - [winfo rooty $w]}] CursorCheck $w $x $y } return } # ::TreeCtrl::CursorCancel -- # # Restores the treectrl's cursor if it was changed to sb_h_double_arrow. # Cancels any pending [after] callback to CursorCheckAux. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::CursorCancel {w} { variable Priv if {[info exists Priv(cursor,$w)]} { $w configure -cursor $Priv(cursor,$w) unset Priv(cursor,$w) } if {[info exists Priv(cursor,afterId,$w)]} { after cancel $Priv(cursor,afterId,$w) unset Priv(cursor,afterId,$w) } return } # ::TreeCtrl::MotionInHeader -- # # This procedure updates the active/normal states of columns as the pointer # moves in and out of column headers. Typically this results in visual # feedback by changing the appearance of the headers. # # Arguments: # w The treectrl widget. # args x y coords if the pointer is in the window, or an empty list. proc ::TreeCtrl::MotionInHeader {w args} { variable Priv if {[llength $args]} { set x [lindex $args 0] set y [lindex $args 1] set action [CursorAction $w $x $y] } else { set action "" } if {[info exists Priv(inheader,$w)]} { set prevColumn $Priv(inheader,$w) } else { set prevColumn "" } set column "" if {[lindex $action 0] eq "column"} { set column [lindex $action 2] } if {$column ne $prevColumn} { if {$prevColumn ne ""} { $w column configure $prevColumn -state normal } if {$column ne ""} { $w column configure $column -state active set Priv(inheader,$w) $column } else { unset Priv(inheader,$w) } } return } # ::TreeCtrl::ButtonPress1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::ButtonPress1 {w x y} { variable Priv focus $w set id [$w identify $x $y] if {$id eq ""} { return } if {[lindex $id 0] eq "item"} { lassign $id where item arg1 arg2 if {$arg1 eq "button"} { $w item toggle $item return } elseif {$arg1 eq "line"} { $w item toggle $arg2 return } } set Priv(buttonMode) "" if {[lindex $id 0] eq "header"} { set action [CursorAction $w $x $y] if {[lindex $action 1] eq "resize"} { set column [lindex $action 2] set Priv(buttonMode) resize set Priv(column) $column set Priv(x) $x set Priv(y) $y set Priv(width) [$w column width $column] return } set column [lindex $id 1] if {[lindex $action 1] eq "button"} { set Priv(buttonMode) header $w column configure $column -state pressed } else { if {[$w column compare $column == "tail"]} return if {![$w column dragcget -enable]} return set Priv(buttonMode) dragColumnWait } set Priv(column) $column set Priv(columnDrag,x) $x set Priv(columnDrag,y) $y return } set item [lindex $id 1] if {![$w item enabled $item]} { return } # If the initial mouse-click is in a locked column, restrict scrolling # to the vertical. scan [$w contentbox] "%d %d %d %d" x1 y1 x2 y2 if {$x >= $x1 && $x < $x2} { set Priv(autoscan,direction,$w) xy } else { set Priv(autoscan,direction,$w) y } set Priv(buttonMode) normal BeginSelect $w $item return } # ::TreeCtrl::DoubleButtonPress1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::DoubleButton1 {w x y} { set id [$w identify $x $y] if {$id eq ""} { return } if {[lindex $id 0] eq "item"} { lassign $id where item arg1 arg2 if {$arg1 eq "button"} { $w item toggle $item return } elseif {$arg1 eq "line"} { $w item toggle $arg2 return } } if {[lindex $id 0] eq "header"} { set action [CursorAction $w $x $y] # Double-click between columns to set default column width if {[lindex $action 1] eq "resize"} { set column [lindex $action 2] $w column configure $column -width "" CursorCheck $w $x $y MotionInHeader $w $x $y } else { ButtonPress1 $w $x $y } } return } # ::TreeCtrl::Motion1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::Motion1 {w x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { header { set id [$w identify $x $y] if {![string match "header $Priv(column)*" $id]} { if {[$w column cget $Priv(column) -state] eq "pressed"} { $w column configure $Priv(column) -state normal } } else { if {[$w column cget $Priv(column) -state] ne "pressed"} { $w column configure $Priv(column) -state pressed } if {[$w column dragcget -enable] && (abs($Priv(columnDrag,x) - $x) > 4)} { $w column dragconfigure \ -imagecolumn $Priv(column) \ -imageoffset [expr {$x - $Priv(columnDrag,x)}] set Priv(buttonMode) dragColumn TryEvent $w ColumnDrag begin [list C $Priv(column)] } } } dragColumnWait { if {(abs($Priv(columnDrag,x) - $x) > 4)} { $w column dragconfigure \ -imagecolumn $Priv(column) \ -imageoffset [expr {$x - $Priv(columnDrag,x)}] set Priv(buttonMode) dragColumn TryEvent $w ColumnDrag begin [list C $Priv(column)] } } dragColumn { scan [$w bbox header] "%d %d %d %d" x1 y1 x2 y2 if {$y < $y1 - 30 || $y >= $y2 + 30} { set inside 0 } else { set inside 1 } if {$inside && ([$w column dragcget -imagecolumn] eq "")} { $w column dragconfigure -imagecolumn $Priv(column) } elseif {!$inside && ([$w column dragcget -imagecolumn] ne "")} { $w column dragconfigure -imagecolumn "" -indicatorcolumn "" } if {$inside} { $w column dragconfigure -imageoffset [expr {$x - $Priv(columnDrag,x)}] if {[ColumnDragFindBefore $w $x $Priv(columnDrag,y) $Priv(column) indColumn indSide]} { $w column dragconfigure -indicatorcolumn $indColumn \ -indicatorside $indSide } else { $w column dragconfigure -indicatorcolumn "" } } if {[$w column cget $Priv(column) -lock] eq "none"} { ColumnDragScrollCheck $w $x $y } } normal { set Priv(x) $x set Priv(y) $y SelectionMotion $w [$w item id [list nearest $x $y]] set Priv(autoscan,command,$w) {SelectionMotion %T [%T item id "nearest %x %y"]} AutoScanCheck $w $x $y } resize { if {[ColumnCanResizeLeft $w $Priv(column)]} { set width [expr {$Priv(width) + $Priv(x) - $x}] } else { set width [expr {$Priv(width) + $x - $Priv(x)}] } set minWidth [$w column cget $Priv(column) -minwidth] set maxWidth [$w column cget $Priv(column) -maxwidth] if {$minWidth eq ""} { set minWidth 0 } if {$width < $minWidth} { set width $minWidth } if {($maxWidth ne "") && ($width > $maxWidth)} { set width $maxWidth } if {$width == 0} { incr width } switch -- [$w cget -columnresizemode] { proxy { scan [$w column bbox $Priv(column)] "%d %d %d %d" x1 y1 x2 y2 if {[ColumnCanResizeLeft $w $Priv(column)]} { # Use "ne" because -columnproxy could be "" if {$x ne [$w cget -columnproxy]} { $w configure -columnproxy $x } } else { if {($x1 + $width - 1) ne [$w cget -columnproxy]} { $w configure -columnproxy [expr {$x1 + $width - 1}] } } } realtime { if {[$w column cget $Priv(column) -width] != $width} { $w column configure $Priv(column) -width $width } } } } } return } # ::TreeCtrl::Leave1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::Leave1 {w x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { header { if {[$w column cget $Priv(column) -state] eq "pressed"} { $w column configure $Priv(column) -state normal } } } return } # ::TreeCtrl::Enter1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::Enter1 {w x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { default {} } return } # ::TreeCtrl::Release1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::Release1 {w x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { header { if {[$w column cget $Priv(column) -state] eq "pressed"} { $w column configure $Priv(column) -state active TryEvent $w Header invoke [list C $Priv(column)] } } dragColumn { AutoScanCancel $w $w column configure $Priv(column) -state normal if {[$w column dragcget -imagecolumn] ne ""} { set visible 1 } else { set visible 0 } set column [$w column dragcget -indicatorcolumn] $w column dragconfigure -imagecolumn "" -indicatorcolumn "" if {$visible && ($column ne "")} { set side [$w column dragcget -indicatorside] if {$side eq "right"} { set column [$w column id "$column next visible"] } TryEvent $w ColumnDrag receive [list C $Priv(column) b $column] } set id [$w identify $x $y] if {[lindex $id 0] eq "header"} { set column [lindex $id 1] if {($column ne "") && [$w column compare $column != "tail"]} { if {[$w column cget $column -button]} { $w column configure $column -state active } } } TryEvent $w ColumnDrag end [list C $Priv(column)] } normal { AutoScanCancel $w set nearest [$w item id [list nearest $x $y]] if {$nearest ne ""} { $w activate $nearest } set Priv(prev) "" } resize { if {[$w cget -columnproxy] ne ""} { scan [$w column bbox $Priv(column)] "%d %d %d %d" x1 y1 x2 y2 if {[ColumnCanResizeLeft $w $Priv(column)]} { set width [expr {$x2 - [$w cget -columnproxy]}] } else { set width [expr {[$w cget -columnproxy] - $x1 + 1}] } $w configure -columnproxy {} $w column configure $Priv(column) -width $width } CursorCheck $w $x $y } } unset Priv(buttonMode) return } # ::TreeCtrl::BeginSelect -- # # This procedure is typically invoked on button-1 presses. It begins # the process of making a selection in the treectrl. Its exact behavior # depends on the selection mode currently in effect for the treectrl. # # Arguments: # w The treectrl widget. # item The item for the selection operation (typically the # one under the pointer). proc ::TreeCtrl::BeginSelect {w item} { variable Priv if {$item eq ""} return if {[string equal [$w cget -selectmode] "multiple"]} { if {[$w selection includes $item]} { $w selection clear $item } else { $w selection add $item } } else { $w selection anchor $item $w selection modify $item all set Priv(selection) {} set Priv(prev) $item } return } # ::TreeCtrl::SelectionMotion -- # # This procedure is called to process mouse motion events while # button 1 is down. It may move or extend the selection, depending # on the treectrl's selection mode. # # Arguments: # w The treectrl widget. # item- The item under the pointer. proc ::TreeCtrl::SelectionMotion {w item} { variable Priv if {$item eq ""} return if {$item eq $Priv(prev)} return if {![$w item enabled $item]} return switch [$w cget -selectmode] { browse { $w selection modify $item all set Priv(prev) $item } extended { set i $Priv(prev) set select {} set deselect {} if {$i eq ""} { set i $item lappend select $item set hack [$w item compare $item == anchor] } else { set hack 0 } if {[$w selection includes anchor] || $hack} { set deselect [concat $deselect [$w range $i $item]] set select [concat $select [$w range anchor $item]] } else { set deselect [concat $deselect [$w range $i $item]] set deselect [concat $deselect [$w range anchor $item]] } if {![info exists Priv(selection)]} { set Priv(selection) [$w selection get] } while {[$w item compare $i < $item] && [$w item compare $i < anchor]} { if {[lsearch $Priv(selection) $i] >= 0} { lappend select $i } set i [$w item id "$i next visible"] } while {[$w item compare $i > $item] && [$w item compare $i > anchor]} { if {[lsearch $Priv(selection) $i] >= 0} { lappend select $i } set i [$w item id "$i prev visible"] } set Priv(prev) $item $w selection modify $select $deselect } } return } # ::TreeCtrl::BeginExtend -- # # This procedure is typically invoked on shift-button-1 presses. It # begins the process of extending a selection in the treectrl. Its # exact behavior depends on the selection mode currently in effect # for the treectrl. # # Arguments: # w The treectrl widget. # item- The item for the selection operation (typically the # one under the pointer). proc ::TreeCtrl::BeginExtend {w item} { if {[string equal [$w cget -selectmode] "extended"]} { if {[$w selection includes anchor]} { SelectionMotion $w $item } else { # No selection yet; simulate the begin-select operation. BeginSelect $w $item } } return } # ::TreeCtrl::BeginToggle -- # # This procedure is typically invoked on control-button-1 presses. It # begins the process of toggling a selection in the treectrl. Its # exact behavior depends on the selection mode currently in effect # for the treectrl. # # Arguments: # w The treectrl widget. # item The item for the selection operation (typically the # one under the pointer). proc ::TreeCtrl::BeginToggle {w item} { variable Priv if {$item eq ""} return if {[string equal [$w cget -selectmode] "extended"]} { set Priv(selection) [$w selection get] set Priv(prev) $item $w selection anchor $item if {[$w selection includes $item]} { $w selection clear $item } else { $w selection add $item } } return } # ::TreeCtrl::AutoScanCheck -- # # Sees if the given pointer coords are outside the content area of the # treectrl (ie, not including borders or column headers) or within # -scrollmargin distance of the edges of the content area. If so and # auto-scanning is not already in progress, then the window is scrolled # and an [after] callback to AutoScanCheckAux is scheduled. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::AutoScanCheck {w x y} { variable Priv scan [$w contentbox] "%d %d %d %d" x1 y1 x2 y2 set margin [winfo pixels $w [$w cget -scrollmargin]] if {![info exists Priv(autoscan,direction,$w)]} { set Priv(autoscan,direction,$w) xy } set scrollX [string match *x* $Priv(autoscan,direction,$w)] set scrollY [string match *y* $Priv(autoscan,direction,$w)] if {($scrollX && (($x < $x1 + $margin) || ($x >= $x2 - $margin))) || ($scrollY && (($y < $y1 + $margin) || ($y >= $y2 - $margin)))} { if {[info exists Priv(autoscan,afterId,$w)]} return if {$scrollY && $y >= $y2 - $margin} { $w yview scroll 1 units set delay [$w cget -yscrolldelay] } elseif {$scrollY && $y < $y1 + $margin} { $w yview scroll -1 units set delay [$w cget -yscrolldelay] } elseif {$scrollX && $x >= $x2 - $margin} { $w xview scroll 1 units set delay [$w cget -xscrolldelay] } elseif {$scrollX && $x < $x1 + $margin} { $w xview scroll -1 units set delay [$w cget -xscrolldelay] } set count [scan $delay "%d %d" d1 d2] if {[info exists Priv(autoscan,scanning,$w)]} { if {$count == 2} { set delay $d2 } } else { if {$count == 2} { set delay $d1 } set Priv(autoscan,scanning,$w) 1 } if {$Priv(autoscan,command,$w) ne ""} { set command [string map [list %T $w %x $x %y $y] $Priv(autoscan,command,$w)] eval $command } set Priv(autoscan,afterId,$w) [after $delay [list TreeCtrl::AutoScanCheckAux $w]] return } AutoScanCancel $w return } # ::TreeCtrl::AutoScanCheckAux -- # # Gets the location of the pointer and calls AutoScanCheck. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::AutoScanCheckAux {w} { variable Priv # Not quite sure how this can happen if {![info exists Priv(autoscan,afterId,$w)]} return unset Priv(autoscan,afterId,$w) set x [winfo pointerx $w] set y [winfo pointery $w] set x [expr {$x - [winfo rootx $w]}] set y [expr {$y - [winfo rooty $w]}] AutoScanCheck $w $x $y return } # ::TreeCtrl::AutoScanCancel -- # # Cancels any pending [after] callback to AutoScanCheckAux. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::AutoScanCancel {w} { variable Priv if {[info exists Priv(autoscan,afterId,$w)]} { after cancel $Priv(autoscan,afterId,$w) unset Priv(autoscan,afterId,$w) } unset -nocomplain Priv(autoscan,scanning,$w) return } # ::TreeCtrl::ColumnDragScrollCheck -- # # Sees if the given pointer coords are outside the left or right edges of # the content area of the treectrl (ie, not including borders). If so and # auto-scanning is not already in progress, then the window is scrolled # horizontally and the column drag-image is repositioned, and an [after] # callback to ColumnDragScrollCheckAux is scheduled. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::ColumnDragScrollCheck {w x y} { variable Priv scan [$w contentbox] "%d %d %d %d" x1 y1 x2 y2 if {($x < $x1) || ($x >= $x2)} { if {![info exists Priv(autoscan,afterId,$w)]} { set bbox1 [$w column bbox $Priv(column)] if {$x >= $x2} { $w xview scroll 1 units } else { $w xview scroll -1 units } set bbox2 [$w column bbox $Priv(column)] if {[lindex $bbox1 0] != [lindex $bbox2 0]} { incr Priv(columnDrag,x) [expr {[lindex $bbox2 0] - [lindex $bbox1 0]}] $w column dragconfigure -imageoffset [expr {$x - $Priv(columnDrag,x)}] if {[ColumnDragFindBefore $w $x $Priv(columnDrag,y) $Priv(column) indColumn indSide]} { $w column dragconfigure -indicatorcolumn $indColumn \ -indicatorside $indSide } else { $w column dragconfigure -indicatorcolumn "" } } set Priv(autoscan,afterId,$w) [after 50 [list TreeCtrl::ColumnDragScrollCheckAux $w]] } return } AutoScanCancel $w return } # ::TreeCtrl::ColumnDragScrollCheckAux -- # # Gets the location of the pointer and calls ColumnDragScrollCheck. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::ColumnDragScrollCheckAux {w} { variable Priv # Not quite sure how this can happen if {![info exists Priv(autoscan,afterId,$w)]} return unset Priv(autoscan,afterId,$w) set x [winfo pointerx $w] set y [winfo pointery $w] set x [expr {$x - [winfo rootx $w]}] set y [expr {$y - [winfo rooty $w]}] ColumnDragScrollCheck $w $x $y return } # ::TreeCtrl::UpDown -- # # Returns the id of an item above or below the given item that the active # item could be set to. If the given item isn't visible, the first visible # enabled item is returned. An attempt is made to choose an item in the # same column over repeat calls; this gives a better result if some rows # have less items than others. Only enabled items are considered. # # Arguments: # w The treectrl widget. # item Item to move from, typically the active item. # n +1 to move down, -1 to move up. proc ::TreeCtrl::UpDown {w item n} { variable Priv set rnc [$w item rnc $item] if {$rnc eq ""} { return [$w item id {first visible state enabled}] } scan $rnc "%d %d" row col set Priv(keyNav,row,$w) [expr {$row + $n}] if {![info exists Priv(keyNav,rnc,$w)] || $rnc ne $Priv(keyNav,rnc,$w)} { set Priv(keyNav,col,$w) $col } set item2 [$w item id "rnc $Priv(keyNav,row,$w) $Priv(keyNav,col,$w)"] if {[$w item compare $item == $item2]} { set Priv(keyNav,row,$w) $row if {![$w item enabled $item2]} { return "" } } else { set Priv(keyNav,rnc,$w) [$w item rnc $item2] if {![$w item enabled $item2]} { return [UpDown $w $item2 $n] } } return $item2 } # ::TreeCtrl::LeftRight -- # # Returns the id of an item left or right of the given item that the active # item could be set to. If the given item isn't visible, the first visible # enabled item is returned. An attempt is made to choose an item in the # same row over repeat calls; this gives a better result if some columns # have less items than others. Only enabled items are considered. # # Arguments: # w The treectrl widget. # item Item to move from, typically the active item. # n +1 to move right, -1 to move left. proc ::TreeCtrl::LeftRight {w item n} { variable Priv set rnc [$w item rnc $item] if {$rnc eq ""} { return [$w item id {first visible state enabled}] } scan $rnc "%d %d" row col set Priv(keyNav,col,$w) [expr {$col + $n}] if {![info exists Priv(keyNav,rnc,$w)] || $rnc ne $Priv(keyNav,rnc,$w)} { set Priv(keyNav,row,$w) $row } set item2 [$w item id "rnc $Priv(keyNav,row,$w) $Priv(keyNav,col,$w)"] if {[$w item compare $item == $item2]} { set Priv(keyNav,col,$w) $col if {![$w item enabled $item2]} { return "" } } else { set Priv(keyNav,rnc,$w) [$w item rnc $item2] if {![$w item enabled $item2]} { return [LeftRight $w $item2 $n] } } return $item2 } # ::TreeCtrl::SetActiveItem -- # # Sets the active item, scrolls it into view, and makes it the only selected # item. If -selectmode is extended, makes the active item the anchor of any # future extended selection. # # Arguments: # w The treectrl widget. # item The new active item, or "". proc ::TreeCtrl::SetActiveItem {w item} { if {$item eq ""} return $w activate $item $w see active $w selection modify active all switch [$w cget -selectmode] { extended { $w selection anchor active set Priv(prev) [$w item id active] set Priv(selection) {} } } return } # ::TreeCtrl::Extend -- # # Does nothing unless we're in extended selection mode; in this # case it moves the location cursor (active item) up, down, left or # right, and extends the selection to that point. # # Arguments: # w The treectrl widget. # dir up, down, left or right proc ::TreeCtrl::Extend {w dir} { variable Priv if {[string compare [$w cget -selectmode] "extended"]} { return } if {![info exists Priv(selection)]} { $w selection add active set Priv(selection) [$w selection get] } switch -- $dir { above { set item [UpDown $w active -1] } below { set item [UpDown $w active 1] } left { set item [LeftRight $w active -1] } right { set item [LeftRight $w active 1] } } if {$item eq ""} return $w activate $item $w see active SelectionMotion $w [$w item id active] return } # ::TreeCtrl::DataExtend # # This procedure is called for key-presses such as Shift-KEndData. # If the selection mode isn't multiple or extended then it does nothing. # Otherwise it moves the active item and, if we're in # extended mode, extends the selection to that point. # # Arguments: # w The treectrl widget. # item Item to become new active item. proc ::TreeCtrl::DataExtend {w item} { if {$item eq ""} return set mode [$w cget -selectmode] if {[string equal $mode "extended"]} { $w activate $item $w see $item if {[$w selection includes anchor]} { SelectionMotion $w $item } } elseif {[string equal $mode "multiple"]} { $w activate $item $w see $item } return } # ::TreeCtrl::Cancel # # This procedure is invoked to cancel an extended selection in # progress. If there is an extended selection in progress, it # restores all of the items between the active one and the anchor # to their previous selection state. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::Cancel w { variable Priv if {[string compare [$w cget -selectmode] "extended"]} { return } set first [$w item id anchor] set last $Priv(prev) if { [string equal $last ""] } { # Not actually doing any selection right now return } if {[$w item compare $first > $last]} { set tmp $first set first $last set last $tmp } $w selection clear $first $last while {[$w item compare $first <= $last]} { if {[lsearch $Priv(selection) $first] >= 0} { $w selection add $first } set first [$w item id "$first next visible"] } return } # ::TreeCtrl::SelectAll # # This procedure is invoked to handle the "select all" operation. # For single and browse mode, it just selects the active item. # Otherwise it selects everything in the widget. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::SelectAll w { set mode [$w cget -selectmode] if {[string equal $mode "single"] || [string equal $mode "browse"]} { $w selection modify active all } else { $w selection add all } return } # ::TreeCtrl::MarqueeBegin -- # # Shows the selection rectangle at the given coords. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::MarqueeBegin {w x y} { set x [$w canvasx $x] set y [$w canvasy $y] $w marquee coords $x $y $x $y $w marquee configure -visible yes return } # ::TreeCtrl::MarqueeUpdate -- # # Resizes the selection rectangle. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::MarqueeUpdate {w x y} { set x [$w canvasx $x] set y [$w canvasy $y] $w marquee corner $x $y return } # ::TreeCtrl::MarqueeEnd -- # # Hides the selection rectangle. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::MarqueeEnd {w x y} { $w marquee configure -visible no return } # ::TreeCtrl::ScanMark -- # # Marks the start of a possible scan drag operation. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::ScanMark {w x y} { variable Priv $w scan mark $x $y set Priv(x) $x set Priv(y) $y set Priv(mouseMoved) 0 return } # ::TreeCtrl::ScanDrag -- # # Performs a scan drag if the mouse moved. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::ScanDrag {w x y} { variable Priv if {![info exists Priv(x)]} { set Priv(x) $x } if {![info exists Priv(y)]} { set Priv(y) $y } if {($x != $Priv(x)) || ($y != $Priv(y))} { set Priv(mouseMoved) 1 } if {[info exists Priv(mouseMoved)] && $Priv(mouseMoved)} { $w scan dragto $x $y } return } # ::TreeCtrl::TryEvent -- # # This procedure is used to cause a treectrl to generate a dynamic event. # If the treectrl doesn't have the event defined (because you didn't call # the [notify install] command) nothing happens. TreeCtrl::PercentsCmd is # used to perform %-substitution on any scripts bound to the event. # # Arguments: # T The treectrl widget. # event Name of event. # detail Name of detail or "". # charMap %-char substitution list (even number of elements). proc ::TreeCtrl::TryEvent {T event detail charMap} { if {[lsearch -exact [$T notify eventnames] $event] == -1} return if {$detail ne ""} { if {[lsearch -exact [$T notify detailnames $event] $detail] == -1} return $T notify generate <$event-$detail> $charMap "::TreeCtrl::PercentsCmd $T" } else { $T notify generate <$event> $charMap "::TreeCtrl::PercentsCmd $T" } return } # ::TreeCtrl::PercentsCmd -- # # This command is passed to [notify generate] to perform %-substitution on # scripts bound to dynamic events. It supports the same set of substitution # characters as the built-in static events (plus any event-specific chars). # # Arguments: # T The treectrl widget. # char %-char to be replaced in bound scripts. # object Same arg passed to [notify bind]. # event Name of event. # detail Name of detail or "". # charMap %-char substitution list (even number of elements). proc ::TreeCtrl::PercentsCmd {T char object event detail charMap} { if {$detail ne ""} { set pattern <$event-$detail> } else { set pattern <$event> } switch -- $char { d { return $detail } e { return $event } P { return $pattern } W { return $object } T { return $T } ? { array set map $charMap array set map [list T $T W $object P $pattern e $event d $detail] return [array get map] } default { array set map [list $char $char] array set map $charMap return $map($char) } } return } kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/ConvertResources.sh0000644000175000017500000000021010562100026024707 0ustar domibeldomibelKWConvertImageToHeader --zlib --base64 \ vtkKWTkTreeCtrlTclLibrary.h \ library/filelist-bindings.tcl \ library/treectrl.tcl kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/vtkKWTkTreeCtrlTclLibrary.h0000644000175000017500000004477310562100026026241 0ustar domibeldomibel/* * Resource generated for file: * filelist-bindings.tcl (zlib, base64) (text file) */ static const unsigned long file_filelist_bindings_tcl_length = 6112; static const unsigned long file_filelist_bindings_tcl_decoded_length = 21670; static const unsigned char file_filelist_bindings_tcl[] = "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" "hMXU1J0rrpnUH9GyVVKzw="; /* * Resource generated for file: * treectrl.tcl (zlib, base64) (text file) */ static const unsigned long file_treectrl_tcl_length = 11008; static const unsigned long file_treectrl_tcl_decoded_length = 39930; static const unsigned char file_treectrl_tcl[] = "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" "aA3jR9AOp/AYfMBco="; kwwidgets-1.0.0~cvs20100930/Utilities/TkTreeCtrl/license.terms0000644000175000017500000000414710562100026023553 0ustar domibeldomibelThis software is copyrighted by Tim Baker and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. kwwidgets-1.0.0~cvs20100930/Utilities/Doxygen/0000755000175000017500000000000011461110202020435 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/Doxygen/CMakeLists.txt0000644000175000017500000000243311006107370023206 0ustar domibeldomibel# # Build the documentation # include (${CMAKE_ROOT}/Modules/Documentation.cmake) if (BUILD_DOCUMENTATION) option (DOCUMENTATION_DOWNLOAD_VTK_TAGFILE "Download the VTK tag file." ON) mark_as_advanced ( DOCUMENTATION_DOWNLOAD_VTK_TAGFILE ) # Backward compat if(NOT DEFINED DOXYGEN AND DEFINED DOXYGEN_EXECUTABLE) set(DOXYGEN ${DOXYGEN_EXECUTABLE}) endif(NOT DEFINED DOXYGEN AND DEFINED DOXYGEN_EXECUTABLE) if(NOT DEFINED DOT AND DEFINED DOXYGEN_DOT_EXECUTABLE) set(DOT ${DOXYGEN_DOT_EXECUTABLE}) endif(NOT DEFINED DOT AND DEFINED DOXYGEN_DOT_EXECUTABLE) # # Configure the script and the doxyfile, then add target # set(HAVE_DOT_YESNO NO) if(DOT) set(HAVE_DOT_YESNO YES) if(NOT DOT_PATH) get_filename_component(DOT_PATH ${DOT} PATH) endif(NOT DOT_PATH) endif(DOT) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/doxyfile) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/doc_makeall.sh.in ${CMAKE_CURRENT_BINARY_DIR}/doc_makeall.sh) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/doc_mainpage.dox.in ${CMAKE_CURRENT_BINARY_DIR}/doc_mainpage.dox) add_custom_target(KWWidgetsDoxygenDoc ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/doc_makeall.sh) endif (BUILD_DOCUMENTATION) kwwidgets-1.0.0~cvs20100930/Utilities/Doxygen/doc_mainpage.dox.in0000644000175000017500000000051010363014267024176 0ustar domibeldomibel/*! @mainpage ${PROJECT_NAME} ${KWWidgets_MAJOR_VERSION}.${KWWidgets_MINOR_VERSION} Documentation @image html KWWidgetsSplashScreen.png @li KWWidgets Home: http://www.kwwidgets.org @li KWWidgets API: http://www.kwwidgets.org/doc/nightly/html/ Additional Sections: - @subpage kwwidgets_autogenerated_page */ kwwidgets-1.0.0~cvs20100930/Utilities/Doxygen/doxyfile.in0000644000175000017500000001523510516156055022636 0ustar domibeldomibel# ------------------------------------------------------------------------- # doxyfile for KWWidgets # modified by S. Barre (Time-stamp: <2006-04-21 10:37:44 barre> # ------------------------------------------------------------------------- PROJECT_NAME = KWWidgets BRIEF_MEMBER_DESC = NO DETAILS_AT_TOP = YES FULL_PATH_NAMES = YES STRIP_FROM_PATH = dox "@KWWidgets_SOURCE_DIR@" WARN_IF_UNDOCUMENTED = NO GENERATE_TREEVIEW = NO GENERATE_TODOLIST = YES GENERATE_BUGLIST = YES GENERATE_HTML = YES GENERATE_HTMLHELP = YES GENERATE_LATEX = NO GENERATE_MAN = NO GENERATE_RTF = NO GENERATE_TAGFILE = "@KWWidgets_BINARY_DIR@/Utilities/Doxygen/KWWidgets.tag" HAVE_DOT = @HAVE_DOT_YESNO@ DOT_PATH = "@DOT_PATH@" CLASS_GRAPH = YES COLLABORATION_GRAPH = YES TEMPLATE_RELATIONS = YES INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CLASS_DIAGRAMS = YES GENERATE_LEGEND = YES GRAPHICAL_HIERARCHY = YES ALLEXTERNALS = NO IMAGE_PATH = "@KWWidgets_SOURCE_DIR@/Utilities/Doxygen" "@KWWidgets_SOURCE_DIR@/Examples/Resources" OUTPUT_DIRECTORY = "@KWWidgets_BINARY_DIR@/Utilities/Doxygen/doc" INPUT = \ "@KWWidgets_SOURCE_DIR@/Utilities/Doxygen/doc_autogenerated.dox" \ "@KWWidgets_BINARY_DIR@/Utilities/Doxygen/doc_mainpage.dox" \ "@KWWidgets_BINARY_DIR@/Utilities/Doxygen/dox" \ "@KWWidgets_BINARY_DIR@/Utilities/Doxygen/dox/AutoGeneratedClasses" \ "@KWWidgets_BINARY_DIR@/Utilities/Doxygen/dox/doc_KWWidgets_index.dox" \ "@KWWidgets_BINARY_DIR@/Utilities/Doxygen/dox/doc_KWWidgets_events2.dox" \ "@KWWidgets_BINARY_DIR@/Utilities/Doxygen/dox/doc_KWWidgets_events.dox" TAGFILES = "@KWWidgets_BINARY_DIR@/Utilities/Doxygen/vtkNightlyDoc.tag=http://www.vtk.org/doc/nightly/html" ENABLED_SECTIONS = section_public section_protected section_private EXTRACT_ALL = YES EXTRACT_PRIVATE = NO EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = YES ALWAYS_DETAILED_SEC = NO SOURCE_BROWSER = YES INLINE_SOURCES = NO CASE_SENSE_NAMES = YES VERBATIM_HEADERS = NO SHOW_INCLUDE_FILES = YES JAVADOC_AUTOBRIEF = YES SORT_MEMBER_DOCS = NO DISTRIBUTE_GROUP_DOC = YES TAB_SIZE = 3 SHOW_DIRECTORIES = YES FILE_PATTERNS = *.h RECURSIVE = NO EXCLUDE = Common/vtkSetGet.h EXCLUDE_PATTERNS = HTML_ALIGN_MEMBERS = YES ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 3 IGNORE_PREFIX = vtkKW vtkPV vtkSM vtk ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES SEARCH_INCLUDES = YES INCLUDE_PATH = EXPAND_ONLY_PREDEF = YES PREDEFINED = "vtkSetMacro(name,type)= \ virtual void Set##name (type);" \ "vtkGetMacro(name,type)= \ virtual type Get##name ();" \ "vtkSetStringMacro(name)= \ virtual void Set##name (const char*);" \ "vtkGetStringMacro(name)= \ virtual char* Get##name ();" \ "vtkSetClampMacro(name,type,min,max)= \ virtual void Set##name (type);" \ "vtkSetObjectMacro(name,type)= \ virtual void Set##name (type*);" \ "vtkGetObjectMacro(name,type)= \ virtual type *Get##name ();" \ "vtkBooleanMacro(name,type)= \ virtual void name##On (); \ virtual void name##Off ();" \ "vtkSetVector2Macro(name,type)= \ virtual void Set##name (type, type); \ void Set##name (type [2]);" \ "vtkGetVector2Macro(name,type)= \ virtual type *Get##name (); \ virtual void Get##name (type &, type &); \ virtual void Get##name (type [2]);" \ "vtkSetVector3Macro(name,type)= \ virtual void Set##name (type, type, type); \ virtual void Set##name (type [3]);" \ "vtkGetVector3Macro(name,type)= \ virtual type *Get##name (); \ virtual void Get##name (type &, type &, type &); \ virtual void Get##name (type [3]);" \ "vtkSetVector4Macro(name,type)= \ virtual void Set##name (type, type, type, type); \ virtual void Set##name (type [4]);" \ "vtkGetVector4Macro(name,type)= \ virtual type *Get##name (); \ virtual void Get##name (type &, type &, type &, type &); \ virtual void Get##name (type [4]);" \ "vtkSetVector6Macro(name,type)= \ virtual void Set##name (type, type, type, type, \ type, type); \ virtual void Set##name (type [6]);" \ "vtkGetVector6Macro(name,type)= \ virtual type *Get##name (); \ virtual void Get##name (type &, type &, type &, \ type &, type &, type &); \ virtual void Get##name (type [6]);" \ "vtkSetVectorMacro(name,type,count)= \ virtual void Set##name(type data[]);" \ "vtkGetVectorMacro(name,type,count)= \ virtual type *Get##name (); \ virtual void Get##name(type data[##count]);" \ "vtkWorldCoordinateMacro(name)= \ virtual vtkCoordinate *Get##name##Coordinate (); \ virtual void Set##name(float x[3]); \ virtual void Set##name(float x, float y, float z); \ virtual float *Get##name();" \ "vtkViewportCoordinateMacro(name)= \ virtual vtkCoordinate *Get##name##Coordinate (); \ virtual void Set##name(float x[2]); \ virtual void Set##name(float x, float y); \ virtual float *Get##name();" \ "vtkTypeMacro(thisClass,superclass)= \ typedef superclass Superclass; \ virtual const char *GetClassName(); \ static int IsTypeOf(const char *type); \ virtual int IsA(const char *type); \ static thisClass* SafeDownCast(vtkObject *o);" \ "vtkTypeRevisionMacro(thisClass,superclass)= \ typedef superclass Superclass; \ virtual const char *GetClassName(); \ static int IsTypeOf(const char *type); \ virtual int IsA(const char *type); \ static thisClass* SafeDownCast(vtkObject *o);" \ "VTK_LEGACY(x)= x" kwwidgets-1.0.0~cvs20100930/Utilities/Doxygen/doc_autogenerated.dox0000644000175000017500000000314410363014267024645 0ustar domibeldomibel/*! @defgroup kwwidgets_autogenerated_group KWWidgets Auto-Generated Classes */ /*! @defgroup kwwidgets_autogenerated_widget_with_label_group KWWidgets Auto-Generated Classes: Widget With label @ingroup kwwidgets_autogenerated_group */ /*! @defgroup kwwidgets_autogenerated_widget_set_group KWWidgets Auto-Generated Classes: Widget Set @ingroup kwwidgets_autogenerated_group */ /*! @defgroup kwwidgets_autogenerated_widget_with_spinbuttons_group KWWidgets Auto-Generated Classes: Widget With Spin-Buttons @ingroup kwwidgets_autogenerated_group */ /*! @defgroup kwwidgets_autogenerated_widget_with_scrollbars_group KWWidgets Auto-Generated Classes: Widget With Scrollbars @ingroup kwwidgets_autogenerated_group */ /*! @page kwwidgets_autogenerated_page KWWidgets Auto-Generated Classes A fair amount of KWWidgets classes is generated automatically from "file templates" at build-time. This allows the creation of related classes without the use of C++ templates, a construct that is not yet fully supported by our Tcl Wrapping framework. Such classes include "widget with labels", "widget set", "widget with scrollbars", etc. By using templates we ensure, for example, that a vtkKWPushButtonSet, i.e. a set of vtkKWPushButton, uses the same basic API as a vtkKWLabelSet, i.e. a set of vtkKWLabel. The documentation for any of these auto-generated classes explicitly specifies which templates they were based on, and provides a link to the group of classes that were created from the same template. The auto-generated classes groups are listed in the \ref kwwidgets_autogenerated_group section. */ kwwidgets-1.0.0~cvs20100930/Utilities/Doxygen/doc_makeall.sh.in0000644000175000017500000002710710522471502023652 0ustar domibeldomibel# ------------------------------------------------------------------------- # Doxygen documentation batch # modified by S. Barre (Time-stamp: <2006-11-02 17:30:47 barre> # ------------------------------------------------------------------------- # Path to several tools (_PROG to avoid the typical GZIP env var pb) # Example: # DOXYGEN_PROG=@DOXYGEN@ (INCLUDE(FindDoxygen.cmake)) # GZIP_PROG=@GZIP@ (INCLUDE(FindCygwin.cmake)) # HHC_PROG=@HTML_HELP_COMPILER@ (INCLUDE(FindHTMLHelp.cmake)) # MV_PROG=@MV@ (INCLUDE(FindCygwin.cmake)) # PERL_PROG=@PERL@ (INCLUDE(FindPerl.cmake)) # RM_PROG=@RM@ (INCLUDE(FindCygwin.cmake)) # TAR_PROG=@TAR@ (INCLUDE(FindCygwin.cmake)) # WGET_PROG=@WGET@ (INCLUDE(FindWget.cmake)) # export DOXYGEN_PROG="@DOXYGEN@" # Doxygen export GZIP_PROG="@GZIP@" # gzip (Unix-like 'gzip compressor') export GNUPLOT_PROG="@GNUPLOT@" # gnuplot (data plotting program) export HHC_PROG="@HTML_HELP_COMPILER@" # HTML Help Compiler export MV_PROG="@MV@" # mv (Unix-like 'move/rename files') export PERL_PROG="@PERL@" # Perl export RM_PROG="@RM@" # rm (Unix-like 'remove files') export TAR_PROG="@TAR@" # tar (Unix-like 'archiver') export WGET_PROG="@WGET@" # wget (remote file retrieval) # PROJECT_NAME: # Documentation/project name. Used in some of the resulting file names and # xrefs to uniquify two or more projects linked together through their # Doxygen's tag files. Mandatory for each documentation set. # Note: might be the same as the doxyfile's PROJECT_NAME # Example: # PROJECT_NAME=VTK # export PROJECT_NAME=KWWidgets # PATH_TO_VTK_DOX_SCRIPTS: # Path to the directory holding the Perl scripts used to produce the VTK doc # in Doxygen format. You need the VTK source files or a local copy of # these scripts. # Example: # PATH_TO_VTK_DOX_SCRIPTS=@VTK_DOXYGEN_HOME@ # export PATH_TO_VTK_DOX_SCRIPTS="@VTK_DOXYGEN_HOME@" # SOURCE_DIR: # Source directory. The top directory of the source files. # Example: # SOURCE_DIR=@KWWidgets_SOURCE_DIR@ # export SOURCE_DIR="@KWWidgets_SOURCE_DIR@" # REL_PATH_TO_TOP: # Relative path from the top directory of the source files to the directory # (or top directory) holding the files to document. Useful if several parts # of the same source directory should be documented separately. # Example: # REL_PATH_TO_TOP=. # REL_PATH_TO_TOP=framework/src # export REL_PATH_TO_TOP=. # INTERMEDIATE_DOX_DIR: # Directory where the intermediate Doxygen files should be stored (mainly # these headers files converted from the VTK format to the Doxygen format). # This directory is erased at the end of this script, unless you comment # the corresponding line. # DOXTEMP might be used to simplify the syntax. # Example: # DOXTEMP=DOXTEMP=@KWWidgets_BINARY_DIR@/Utilities/Doxygen # INTERMEDIATE_DOX_DIR=$DOXTEMP/dox # export DOXTEMP="@KWWidgets_BINARY_DIR@/Utilities/Doxygen" export INTERMEDIATE_DOX_DIR="$DOXTEMP/dox" # CVSWEB_CHECKOUT, CVSWEB_CHECKOUT_SUFFIX: # URL to the CVSWeb of the project, in checkout mode (i.e. appending a file # name to this URL will retrieve the contents of the file). In the same way # CVSWEB_CHECKOUT_SUFFIX is appended to the result. # Example: # CVSWEB_CHECKOUT=http://public.kitware.com/cgi-bin/cvsweb.cgi/~checkout~/VTK # CVSWEB_CHECKOUT_SUFFIX=?cvsroot=CMake # export CVSWEB_CHECKOUT="http://public.kitware.com/cgi-bin/cvsweb.cgi/~checkout~/KWWidgets/" export CVSWEB_CHECKOUT_SUFFIX="?cvsroot=KWWidgets" # DOXYFILE: # Path to the Doxygen configuration file (i.e. doxyfile). # Example: # DOXYFILE=$DOXTEMP/doxyfile # export DOXYFILE="$DOXTEMP/doxyfile" # OUTPUT_DIRECTORY ALLOW_ERASE_OUTPUT_DIRECTORY: # Path to the Doxygen output directory (where the resulting doc is stored). # Note: should be the same as your doxyfile's OUTPUT_DIRECTORY # If ON, allows the output directory to be erased when some advanced output # file have been produced (HTML Help, or TAR archive for example). # Example: # OUTPUT_DIRECTORY=$DOXTEMP/doc # ALLOW_ERASE_OUTPUT_DIRECTORY=ON # export OUTPUT_DIRECTORY="$DOXTEMP/doc" export ALLOW_ERASE_OUTPUT_DIRECTORY=ON # COMPILE_HTML_HELP RESULTING_HTML_HELP_FILE: # Compile the CHM (Compressed HTML) HTML Help file, name of the resulting # file. If set to ON and name is non-empty these options will actually # trigger the HTML-Help compiler to create the CHM. The resulting # file (usually index.chm) will be renamed to this name. # Note: if ON, the whole $OUTPUT_DIRECTORY will be erased at the end of # this script, since this file is considered to be one of the # advanced final output, unless ALLOW_ERASE_OUTPUT_DIRECTORY is OFF # Note: your doxyfile should be configured to enable HTML Help creation # (using GENERATE_HTML = YES, GENERATE_HTMLHELP = YES) # Example: # COMPILE_HTML_HELP=ON # COMPILE_HTML_HELP=@DOCUMENTATION_HTML_HELP@ # RESULTING_HTML_HELP_FILE=$DOXTEMP/vtk4.chm # export COMPILE_HTML_HELP=@DOCUMENTATION_HTML_HELP@ export RESULTING_HTML_HELP_FILE="$DOXTEMP/$PROJECT_NAME.chm" # CREATE_HTML_TARZ_ARCHIVE RESULTING_HTML_TARZ_ARCHIVE_FILE: # Create a compressed (gzip) tar archive of the html directory (located # under the OUTPUT_DIRECTORY), and name of the resulting archive file. # Note: your doxyfile should be configured to enable HTML creation # (using GENERATE_HTML = YES) # Example: # CREATE_HTML_TARZ_ARCHIVE=ON # CREATE_HTML_TARZ_ARCHIVE=@DOCUMENTATION_HTML_TARZ@ # RESULTING_HTML_TARZ_ARCHIVE_FILE=$DOXTEMP/vtk4-html.tar.gz # export CREATE_HTML_TARZ_ARCHIVE=@DOCUMENTATION_HTML_TARZ@ export RESULTING_HTML_TARZ_ARCHIVE_FILE="$DOXTEMP/$PROJECT_NAME-html.tar.gz" # DOWNLOAD_VTK_TAGFILE VTK_TAGFILE VTK_TAGFILE_REMOTE_DIR VTK_TAGFILE_DEST_DIR: # Download the VTK tag file, name, remote location and destination dir of this # tag file. If set to ON, the tag file is retrieved from its remote location # using wget and stored in the destination dir. # The tag file is expected to be compressed using gzip, but DO NOT include # the .gz extension in VTK_TAGFILE. # Note: your doxyfile must be tailored to make use-of or create this tag file. # (using TAGFILES = vtk4-nightly.tag=http://www.vtk.org/doc/nightly/html # or GENERATE_TAGFILE = "@FOO_BINARY_DIR@/Utilities/Doxygen/vtk4.tag") # Example: # DOWNLOAD_VTK_TAGFILE=OFF # VTK_TAGFILE=vtk4-nightly.tag # VTK_TAGFILE_REMOTE_DIR=http://www.vtk.org/doc/nightly/html # VTK_TAGFILE_DEST_DIR=$DOXTEMP # export DOWNLOAD_VTK_TAGFILE=@DOCUMENTATION_DOWNLOAD_VTK_TAGFILE@ export VTK_TAGFILE=vtkNightlyDoc.tag export VTK_TAGFILE_REMOTE_DIR="http://www.vtk.org/files/nightly" export VTK_TAGFILE_DEST_DIR="$DOXTEMP" # ---------------------------------------------------------------------------- # Convert the VTK headers to the Doxygen format. if test "x$PERL_PROG" != "xNOTFOUND" ; then "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_header2doxygen.pl" \ --to "$INTERMEDIATE_DOX_DIR" \ --conds \ --relativeto "$SOURCE_DIR/$REL_PATH_TO_TOP" \ "$SOURCE_DIR/$REL_PATH_TO_TOP" "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_header2doxygen.pl" \ --to "$INTERMEDIATE_DOX_DIR" \ --relativeto "@KWWidgets_BINARY_DIR@" \ "@KWWidgets_BINARY_DIR@/AutoGeneratedClasses" fi # ---------------------------------------------------------------------------- # Build the full-text index. if test "x$PERL_PROG" != "xNOTFOUND" ; then "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_index.pl" \ --project "$PROJECT_NAME" \ --stop "$PATH_TO_VTK_DOX_SCRIPTS/doc_index.stop" \ --store "doc_""$PROJECT_NAME""_index.dox" \ --to "$INTERMEDIATE_DOX_DIR" \ "$SOURCE_DIR/$REL_PATH_TO_TOP" \ "@KWWidgets_BINARY_DIR@/AutoGeneratedClasses" fi # ---------------------------------------------------------------------------- # Build the Events invocation list. if test "x$PERL_PROG" != "xNOTFOUND" ; then "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_codematch.pl" \ --codematch "\w(?:->|\.)InvokeEvent\s*\(\s*(\w+::\w+)[\s,]" \ --label "Events" \ --project "$PROJECT_NAME" \ --sectionmatch "^\w+::(\w)" \ --store "doc_""$PROJECT_NAME""_events.dox" \ --title "Event to $PROJECT_NAME Classes" \ --sectionmatch2 "^vtk(?:KW)?(\w)" \ --store2 "doc_""$PROJECT_NAME""_events2.dox" \ --title2 "$PROJECT_NAME Class to Events" \ --to "$INTERMEDIATE_DOX_DIR" \ --unique "v" \ "$SOURCE_DIR/$REL_PATH_TO_TOP" \ "@KWWidgets_BINARY_DIR@/AutoGeneratedClasses" fi # ---------------------------------------------------------------------------- # Retrieve the (gziped) VTK 4 tag file and decompress it if test "x$DOWNLOAD_VTK_TAGFILE" == "xON" ; then if test "x$VTK_TAGFILE" != "x" ; then if test "x$WGET_PROG" != "xNOTFOUND" ; then $WGET_PROG -nd -nH \ "$VTK_TAGFILE_REMOTE_DIR/$VTK_TAGFILE.gz" \ -O "$VTK_TAGFILE_DEST_DIR/$VTK_TAGFILE.gz" if test "x$GZIP_PROG" != "xNOTFOUND" ; then $GZIP_PROG -d "$VTK_TAGFILE_DEST_DIR/$VTK_TAGFILE.gz" fi fi fi fi # ---------------------------------------------------------------------------- # Create the Doxygen doc. if test "x$DOXYGEN_PROG" != "xNOTFOUND" ; then if test "x$RM_PROG" != "xNOTFOUND" ; then $RM_PROG -fr "$OUTPUT_DIRECTORY" fi $DOXYGEN_PROG "$DOXYFILE" fi # ---------------------------------------------------------------------------- # Clean the HTML pages to remove the path to the intermediate Doxygen dir. if test "x$PERL_PROG" != "xNOTFOUND" ; then "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_rmpath.pl" \ --to "$INTERMEDIATE_DOX_DIR" \ --html "$OUTPUT_DIRECTORY/html" fi # ---------------------------------------------------------------------------- # Create the CHM HTML HELP doc. if test "x$COMPILE_HTML_HELP" == "xON" ; then if test "x$RESULTING_HTML_HELP_FILE" != "x" ; then cd "$OUTPUT_DIRECTORY/html" if test "x$HHC_PROG" != "xNOTFOUND" ; then $HHC_PROG index.hhp if test "x$MV_PROG" != "xNOTFOUND" ; then $MV_PROG -f index.chm "$RESULTING_HTML_HELP_FILE" fi fi fi fi # ---------------------------------------------------------------------------- # Create the compressed tar archive. if test "x$CREATE_HTML_TARZ_ARCHIVE" == "xON" ; then if test "x$RESULTING_HTML_TARZ_ARCHIVE_FILE" != "x" ; then cd "$OUTPUT_DIRECTORY" if test "x$TAR_PROG" != "xNOTFOUND" ; then if test "x$RM_PROG" != "xNOTFOUND" ; then $RM_PROG -f html.tar fi $TAR_PROG -cf html.tar html if test "x$GZIP_PROG" != "xNOTFOUND" ; then if test "x$RM_PROG" != "xNOTFOUND" ; then $RM_PROG -f html.tar.gz fi $GZIP_PROG html.tar $MV_PROG -f html.tar.gz "$RESULTING_HTML_TARZ_ARCHIVE_FILE" fi fi fi fi # ---------------------------------------------------------------------------- # Clean-up. if test "x$RM_PROG" != "xNOTFOUND" ; then $RM_PROG -fr "$INTERMEDIATE_DOX_DIR" if test "x$DOWNLOAD_VTK_TAGFILE" == "xON" ; then if test "x$VTK_TAGFILE" != "x" ; then $RM_PROG -f "$VTK_TAGFILE_DEST_DIR/$VTK_TAGFILE" fi fi if test "x$COMPILE_HTML_HELP" == "xON" ; then if test "x$RESULTING_HTML_HELP_FILE" != "x" ; then if test "x$ALLOW_ERASE_OUTPUT_DIRECTORY" == "xON" ; then $RM_PROG -fr "$OUTPUT_DIRECTORY" fi fi fi fi kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/0000755000175000017500000000000011461110203020744 5ustar domibeldomibelkwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/CHANGES.txt0000644000175000017500000015414611070725164022606 0ustar domibeldomibelWhat is new in Tablelist 4.10? ------------------------------ 1. Support for individual binding scripts controlling the interactive cell editing, with the aid of the new "editwintag" subcommand (thanks to Óscar Fuentes for his valuable input). 2. Complemented the "attrib" subcommand with the new subcommands "hasattrib" and "unsetattrib". 3. Support for column-, row-, and cell-specific attributes, with the aid of the new subcommands "columnattrib", "hascolumnattrib", "unsetcolumnattrib", "rowattrib", "hasrowattrib", "unsetrowattrib", "cellattrib", "hascellattrib", and "unsetcellattrib". 4. Support for interactive cell editing with the aid of the new mentry widget of type "DateTime", introduced in version 3.2 of the Mentry package (thanks to Florian Murr for his proposal). 5. Made sure that the default bindings are set up immediately when loading the package, prior to creating any tablelist widget (thanks to Schelte Bron for his proposal and discussions on this topic). 6. Re-established the support for tile widgets as edit windows in non- tile-based tablelist widgets (again, thanks to Schelte Bron for reporting that this was broken in the last few Tablelist versions). 7. Adapted the handling of the tile checkbutton as edit window in the "xpnative" theme to some changes made in tile 0.8 (thanks to Jeff Godfrey for his bug report). 8. Guarded against potential widget deletion from within user-defined binding scripts or "update (idletasks)" (thanks to Schelte Bron and Jan Kandziora for their bug reports). 9. Updated the (very rarely needed) distribution file "repair.tcl" to work with current Tablelist versions (thanks to Robert Stollf for his bug report). 10. Corrected the description of the "-height" option in the reference manual (thanks to Glenn Herteg for his bug report concerning the case "-height 0"). 11. Improved the color handling in the "disabled" state (thanks to Rolf Ade for his bug report and discussions on this topic). 12. Made the handling of elided text more robust (thanks to Jos Decoster for his bug report and valuable contribution). 13. Several further improvements and minor bug fixes (thanks to Albrecht Mucha for his valuable input). What was new in Tablelist 4.9? ------------------------------ 1. Added the "-wrap" column configuration option, which makes it possible to display long texts in word-wrapped multi-line rather than snipped form (thanks to Alexander Schöpe and Anant Adke for their proposals). Also, added support for interactive cell editing with a word- or char-wrapped text widget when using Tk 8.5 (thanks to Juberi Rajib for discussions on this topic). 2. Support for dynamic-width embedded windows, with the aid of the new "-stretchwindow" cell configuration option (thanks to Kurt Kurczyk, Bryan Oakley, and Rasmus Debitsch for their proposals). The demo script "embeddedWindows.tcl" and its tile-based counterpart now make use of this option. 3. New "formatinfo" subcommand, returning information about the cell whose content is being formatted by a command specified as the value of the "-formatcommand" column configuration option (thanks to Goran Ivankovic and Sebastien Barre for their proposals). 4. Changed the default value of the "-activestyle" configuration option from "underline" to "frame" and that of the "-setfocus" option from 0 to 1, making them conform to similar changes in Tk 8.5 related to the listbox widget. 5. Improved the appearance of the header labels for the "aqua" theme (thanks to Torsten Berg for discussing this topic on the Wiki). 6. Eliminated the potential invocation of the "unknown" command from within the Tablelist code (thanks to Roger Niva for discussions on this topic). 7. When starting the interactive cell editing with the aid of a combobox widget, the list associated with the latter is only dropped down if the combobox is read-only (thanks to Bryan Oakley for his proposal). 8. The "setThemeDefaults" command no longer throws an error if the current theme is not explicitly supported by Tablelist. Instead, it uses the options set by the current theme and falls back to the "default" one for the rest (thanks to Schelte Bron for his valuable contribution). 9. Improved the tablelist widget's appearance when the header labels are not shown (thanks to Mark Garvey for his input). 10. Fixed two bugs related to the optimized item insertion (thanks to Harold Campbell and Bryan Oakley for their bug reports). 11. Fixed a bug related to the "-showlinenumbers" column configuration option (thanks to Martin Lemburg for his bug report). 12. Several further improvements and minor bug fixes. What was new in Tablelist 4.8? ------------------------------ This release fixes a few nasty bugs related to the optimized item insertion, introduced in the previous Tablelist version (thanks to Harold Campbell, Roger Niva, and Jörg Klingseisen for their bug reports). What was new in Tablelist 4.7? ------------------------------ 1. Significant performance improvements related to the "insert", "rowconfigure", "sort", "sortbycolumn", and "sortbycolumnlist" subcommands (thanks to Harold Campbell for his valuable contribution to speeding up the item insertion). The extent of the speed-up depends on the configuration options present at column, row, and cell levels. 2. Support for cell- and column label-specific balloon help, with the aid of the new configuration options "-tooltipaddcommand" and "-tooltipdelcommand". 3. New subcommands "iselemsnipped" and "istitlesnipped", which make it very easy to display the full cell texts and column titles as tooltips for cells and header labels with snipped contents. 4. New subcommands "configcolumnlist", "configcolumns", "configrowlist", "configrows", "configcelllist", and "configcells", which allow you to configure several columns/rows/cells with a single command invocation (thanks to Harold Campbell, Jeff Godfrey, and Paul Obermeier for their proposals). 5. Worked around some performance problems regarding the "switch" command in Tcl 8.5a6/8.5b1 and ActiveTcl 8.4.14. 6. Made sure that ActiveState's "style::as" package won't break the mousewheel bindings (thanks to Michael Schlenker for drawing my attention to this problem). 7. Improved the focus handling when resizing a column interactively (thanks to Jorge Enderr for his bug report). 8. Corrected a typo in the adaptation of vertical scrolling to the text widget changes made in Tk 8.5 (thanks to Julian M Noble for his posting on the Wiki related to this subject). 9. Fixed a bug related to hidden rows when having "-selecttype cell", introduced in Tablelist version 4.3 (thanks to Harold Campbell for his bug report and discussions on this subject). 10. Fixed a bug in the "cellconfigure" subcommand, introduced in the previous Tablelist release (thanks to Roy Terry for reporting this problem on the Wiki). 11. Fixed a bug in the "-changesnipside" option (thanks to Kai Morich for his bug report). 12. Numerous further improvements in the code and documentation. What was new in Tablelist 4.6? ------------------------------ 1. Tablelist_tile now supports tile 0.8 and Tk 8.5a6/8.5b1 (where tile is integrated in the core). The new commands "tablelist::setTheme", "tablelist::getCurrentTheme", and "tablelist::getThemes" enable you to set and get the current theme and to query the available ones, without having to worry about the incompatibilities between the various tile versions. 2. New column configuration option "-changesnipside", which allows you to override the alignment-specific default snip side (thanks to Georgios Petasis for his proposal). 3. New "columnwidth" subcommand, with the options "-requested", "-stretched", and "-total" (thanks to Matthew Callaghan, Richard Finstad, Lieven Forrez, and Tom Roeder for their proposals). 4. Support for the new virtual event <>, generated after resizing a column interactively (thanks to Kurt Kurczyk for his proposal). 5. Visual improvement: Within an active row, the gap to the left or right of an embedded image or window no longer appears underlined (when the "-activestyle" option has its default value "underline"). 6. Embedded images and windows are no longer hidden during interactive cell editing (except the editing with the aid of a Tk or tile checkbutton widget). 7. Significantly improved the redraw and stretching behavior when resizing a column interactively. 8. Eliminated some annoying visual effects caused by hidden columns when displaying the items of an already visible tablelist widget (thanks to Rolf Ade for discussions on this topic). 9. Adapted the implementation of vertical scrolling to the text widget changes made in Tk 8.5 (thanks to Julian M Noble for his posting on the Wiki related to this subject). 10. Fixed a bug related to hidden rows, introduced in Tablelist version 4.3 (thanks to Matthew Callaghan for his bug report). 11. Eliminated the possible endless loop caused by some option database settings in the "seecell" subcommand (thanks to Erik Allaert and Mauro Comin for reporting this bug). 12. Added a detailed performance-related hint to the description of the "-listvariable" configuration option. 13. Numerous further improvements and minor bug fixes. What was new in Tablelist 4.5? ------------------------------ 1. Static-width columns are now displayed much faster than in earlier Tablelist releases. 2. Quite significantly reduced the performance penalty imposed by various column, row, and cell configuration options when sorting, redisplaying, moving, or deleting tablelist items. 3. Embedded images are now handled much more efficiently and are displayed much faster than in earlier Tablelist versions. 4. New column configuration option "-showlinenumbers" (thanks to Rolf Schroedter and Sean Xu for their proposals and to Kathrin Kläs for testing the implementation). 5. Support for tile-based multi-entry widgets (introduced in Mentry 3.0) used as edit windows. 6. Significantly improved the handling of the <> virtual event. 7. Defined more reasonable windowing system- and theme-specific default values for the "-arrowdisabledcolor" option. 8. Improved and simplified the package loading mechanism (thanks to Andreas Kupries for his valuable contribution). 9. Eliminated the "togglevisibility" subcommand, which was deprecated in the previous Tablelist version in favor of "togglecolumnhide". 10. Fixed a bug in the implementation of the "deletecolumns" subcommand, introduced in the previous Tablelist release (thanks to Kai Morich, Kurt Kurczyk, and Dave Leslie for their bug reports). 11. Fixed two binding-related bugs (thanks to Mark Garvey and Kurt Kurczyk for their bug reports). 12. Fixed a bug related to the handling of the "tileqt" theme (thanks to Andres Garcia for his bug report). 13. Fixed a small but annoying bug related to the "-maxwidth" column configuration option, introduced in the previous Tablelist version. 14. Numerous further improvements and minor bug fixes (thanks to Patrick Fradin and Georgios Petasis for their valuable feedback). What was new in Tablelist 4.4? ------------------------------ 1. New row configuration option "-hide" (thanks to Jeff Godfrey, Patrick Fradin. Hemang Lavana, and Martyn Smith for their proposals, and especially to Harold Campbell for providing the initial implementation and testing the final one.) For performance reasons this option is implemented by using elided text in the underlying text widget, and therefore it is not supported for Tk versions earlier than 8.3. 2. New subcommand "togglerowhide" for hiding/unhiding several rows at a time (not supported for Tk versions earlier than 8.3). 3. Renamed the "togglevisibility" subcommand to "togglecolumnhide". The old name is still supported, but will be eliminated in the next Tablelist release. 4. New command "tablelist::setThemeDefaults", which can be used to make sure that classical Tk widgets, e.g., text, will have a theme- specific appearance, just like the tile widgets. The tile-based demo scripts now make use of this command. 5. When using the "tileqt" theme, the version number of TileQt must be 0.3 or higher (thanks to Georgios Petasis for providing the new "tileqt" features used in this Tablelist release). 6. For Tk 8.3 or later, hidden columns are now handled by using elided text, which results in very significant performance improvements (thanks to Harold Campbell for his valuable contribution). 7. Improved the handling of the "-listvariable" option in connection with snit widgetadaptors (thanks to Rolf Ade for his bug-fix). 8. Corrected a typo in the implementation of the "move" subcommand, introduced in the previous release (thanks to Jérome Siot for his bug report). 9. Improved the handling of the virtual event <> (thanks to Wofgang Großer for his bug report). 10. Fixed a long-standing bug related to hidden columns (thanks to Dave Leslie for his bug report). 11. Worked around a peculiarity of the "place" command on Windows, which caused refresh problems in column labels with images (thanks to Sebastien Barre for his bug report). 12. Numerous further improvements and minor bug fixes. What was new in Tablelist 4.3? ------------------------------ 1. Support for multi-line cells: Newline characters now force line breaks when displaying the items (thanks to Sebastien Barre, Tillmann Basien, Cameron Laird, Kai Morich, and Vaclav Snajdr for their proposals). In addition, interactive cell editing can now take place with the aid of a text widget, too (this has caused a few minor changes in the default key bindings for the edit window). 2. Support for multi-column sorting with the aid of the new subcommands "sortbycolumnlist", "sortcolumnlist", and "sortorderlist", as well as of the new command "tablelist::addToSortColumns". The latter is designed to be specified as the value of the new widget and column configuration option "-labelcommand2", whose value is invoked on events. Multi-column sorting is visualized by means of multiple sort arrows, which are displayed together with the corresponding sort ranks. (Thanks to Harold Campbell for proposing most of these features, providing the initial implementation, and testing the final one.) 3. New configuration option "-setfocus", specifying whether mouse button 1 should set the focus to the tablelist's body (thanks to Tillmann Basien for discussions on this topic). 4. Replaced the contents of the directory "images" with a script file containing procedures that create the bitmap images from inline data (thanks to Mats Bengtsson, Patrick Fradin, and Kai Morich for their proposals). 5. Fixed a bug related to the use of a tile entry within a non-tile- based tablelist widget on Windows XP (thanks to Schelte Bron for his bug report). 6. The handling of events during interactive cell editing is now explicitly restricted to Mac OS Classic and Mac OS X Aqua, because, strangely enough, on Windows these events are generated by simple keypresses if Num Lock is active. 7. Numerous further code improvements, minor bug-fixes, and support for several recent changes in tile. 8. Cleaned up the documentation, to make sure that the HTML files generated for the ActiveTcl distribution with the tool HTML Tidy will be syntactically identical to the original ones. What was new in Tablelist 4.2? ------------------------------ 1. The resize area of the header labels now consists of a few pixels on both sides of the right edge (thanks to Bryan Oakley for suggesting this improvement). 2. Made sure that the header labels have the right appearance in the "aqua" theme when using tile version 0.6.4 or later (thanks to Bryan Oakley for his bug report). 3. Several further improvements related to Mac OS X Aqua (for example, support for the "Command" key during keyboard navigation between the editable cells). 4. Fixed a very long-standing bug in the "containing" subcommand (thanks to Mats Bengtsson, Schelte Bron, and Mark Garvey for their bug reports). 5. Fixed a bug related to the "xpnative" theme, introduced in the previous release (thanks to Mark Garvey, Jeff Godfrey, and Uwe Koloska for their bug reports). 6. Fixed another very long-standing bug, related to insertion and deletion of columns having images in their labels (thanks to Sebastien Barre for his bug report). 7. Fixed an old bug related to embedding images or windows into hidden cells (again, thanks to Sebastien Barre for reporting this bug). 8. The demo scripts now work independently of their location (this small improvement reflects the fact that Tablelist is now included in tklib, where the examples are in a location different from "$tablelist::library/demos"). 9. Adapted two tile-based demo scripts to the recently released tile version 0.7. 10. Several further improvements in the code and documentation (thanks to Patrick Fradin for his valuable contribution). What was new in Tablelist 4.1? ------------------------------ 1. Significantly extended the tile support in the Tablelist_tile package: Header labels now look and behave like the column headings of treeview widgets, and over a dozen configuration options have theme-specific default values (thanks to Paul Obermeier for his excellent "poImgview" application, which helped me a lot during this work, as well as to Georgios Petasis for his Qt-related hints). 2. Header labels containing the mouse cursor are now set into active state. Their appearance is controlled in the Tablelist package by the new configuration options "-labelactivebackground" and "-labelactiveforeground", while the Tablelist_tile package uses theme-specific background and foreground colors for the active and pressed states of the labels. 3. New configuration option "-arrowstyle", specifying the flat or sunken relief and the dimensions of the arrow indicating the sorting order. This option has windowing system- and theme- specific default values. 4. New configuration option "-protecttitlecolumns", used to protect the title column boundary from being crossed when moving a column interactively (thanks to Schelte Bron for his proposal). 5. New configuration option "-spacing", specifying additional space to provide above and below each tablelist row (thanks to Sebastien Barre for his proposal). 6. New column configuration option "-stretchable", complementing the global "-stretch" option (thanks to Sebastien Barre for his proposal). 7. New row configuration option "-name", whose value can also be used as a row index and as the first component of a cell index (thanks to John Kozura for his proposal). 8. New cell configuration option "-windowdestroy", specifying a script to be invoked when a window embedded into the cell is destroyed (thanks to Sebastien Barre for his proposal). 9. New "imagelabelpath" subcommand (thanks to Schelte Bron for his proposal). 10. Keyboard navigation during interactive cell editing now works on Mac OS X Aqua, too. 11. Restored the support for Tcl/Tk versions earlier than 8.3, by cleaning up the handling of the "-titlecolumns" option (thanks to Andreas Flach and Brian O'Hagan for their bug reports). 12. Restored the support for Tcl/Tk versions earlier than 8.0.4, which has been broken since release 3.5, due to the use of the event, introduced in Tk 8.0.4 (thanks to Brian O'Hagan for his valuable contribution). 13. Worked around a peculiarity of the text widget's "dump -window" command (thanks to Greg Reynolds for his bug-fix). 14. Fixed a binding-related bug in "extended" selection mode (thanks to David Mattinson for his bug-fix). 15. Numerous further improvements and minor bug fixes (thanks to Schelte Bron, Patrick Fradin, Silas Justiniano, and Uwe Koloska for their bug reports and valuable contributions). What was new in Tablelist 4.0? ------------------------------ 1. Support for the tile entry, combobox, and checkbutton widgets for interactive cell editing (thanks to Miguel Bagnon, Andy Black, Adrian Chan, and Mark Garvey for their proposals and to Mats Bengtsson and Kevin Walzer for their support on the Macintosh). See the new reference page "tablelistTile.html" for details. 2. Support for tile-compatibility: By just specifying "package require Tablelist_tile" instead of "package require Tablelist", the tablelist widgets will have a modern theme-specific appearance (again, thanks to the above-mentioned Tablelist users for their suggestions and assistance). See the "How to use it?" and "More on Tablelist_tile" sections of the tutorial "tablelist.html" for details. 3. New demo script "tileWidgets.tcl", illustrating the use of tile widgets for interactive cell editing and of the Tablelist_tile package. All the other demo scripts are now provided in both a traditional and a tile-based version. See the "Tile-based demo scripts" section of the tutorial "tablelist.html" for an example and some screenshots. 4. The Tk checkbutton used for interactive cell editing is now a platform-specific checkbutton widget on Windows and the Macintosh (thanks to Mats Bengtsson for his help related to the Macintosh platform). 5. The "-editwindow" option is now available at cell level, too (thanks to Kenneth Green for his proposal). 6. New subcommand "togglevisibility" for hiding/unhiding several columns at a time (thanks to Stefan Finzel and Kai Morich for their proposals). 7. Support for the new virtual event <>, generated when a tablelist widget having "-exportselection 1" loses the selection (thanks to Aldo Buratti for his proposal). 8. After sorting the items, the "most important" row is automatically brought into view (thanks to Kai Morich for his valuable input). 9. Worked around a peculiarity of Tk for Windows, related to mouse events (thanks to Tore Morkemo and Mike Collins for their bug reports). 10. Worked around a problem related to the visibility of the up/down- arrow on Mac OS X Aqua (thanks to Kevin Walzer for his bug report). 11. Fixed a bug in the "seecell" subcommand, introduced in Tablelist version 3.7 (thanks to Stefan Finzel for his bug report). 12. Fixed a bug in the "rowconfigure" subcommand, introduced in the previous Tablelist release (thanks to Tore Morkemo for his bug report). 13. Eliminated the memory leak caused by incomplete cleanup on deleting rows with embedded windows (thanks to David Cockerell for his bug report). 14. Fixed a small timing-related bug in the "editcell" subcommand (thanks to Kenneth Green for his bug report). 15. Numerous further improvements and minor bug fixes (thanks to Greg Reynolds for his valuable input). What was new in Tablelist 3.8? ------------------------------ 1. New configuration option "-forceeditendcommand", controlling the invocation of the script corresponding to the value of the "-editendcommand" option (thanks to Nestor Patino for his proposal). 2. New subcommands "getcells" and "windowpath" (thanks to Jeff Godfrey and Mike Collins for their proposals). 3. Support for the new virtual event <>, generated by the "cancelediting" subcommand. 4. Significantly improved the performance of the "delete", "deletecolumns", and "movecolumn" subcommands for tablelist widgets having color or font options set at column, row, or cell level (thanks to Michael Bahr for his valuable feedback). 5. Improved the autoscrolling with the left mouse button in both the body and the header of a tablelist widget having title columns. 6. Fixed a bug related to the "-titlecolumns" option, introduced in the previous Tablelist release (thanks to Alexander Schöpe for his bug report). 7. Fixed a typo in the implementation of the "seecell" subcommand, introduced in the previous Tablelist release (thanks to Patrick Fradin for his bug report). 8. Improved the demo script "embeddedWindows.tcl" (thanks to Patrick Fradin for his valuable input). 9. Several further improvements and minor bug fixes. What was new in Tablelist 3.7? ------------------------------ 1. New configuration option "-titlecolumns", specifying the number of the non-scrollable columns at the left edge of the window (thanks to Goran Ivankovic, Paul Kienzle, Hemang Lavana, and Takeshi Sakamoto for their proposals). For technical reasons (the use of the "-elide" option for a text widget tag), this option is not supported for Tk versions earlier than 8.3. 2. Extended the "separatorpath" and "separators" subcommands, to support the new special separator, which is displayed to mark the end of the title columns, independently of the value of the "-showseparators" option. 3. The "-stripebackground" and "-stripeforeground" options now have a higher priority than the "-background" and "-foreground" column configuration options, respectively (see the demo script "styles.tcl", which has been extended to illustrate this change). 4. Improved the handling of embedded images with transparent background, complementing the changes made in the previous Tablelist release (thanks to Kai Morich for his valuable contribution). 5. Improved the implementation of the "seecell" subcommand for centered and right-aligned columns. 6. Fixed two bugs related to the "rowconfigure" subcommand, introduced in Tablelist version 3.5 (thanks to Ted Branscomb and Roger Niva for their bug reports). 7. Fixed an old bug related to the "movecolumn" subcommand. 8. Several further improvements and minor bug fixes. What was new in Tablelist 3.6? ------------------------------ 1. Support for embedded windows, with the aid of the new cell configuration option "-window" (thanks to Wolf Grossi, Glenn Herteg, Takeshi Sakamoto, and Keesang Song for proposing this option). 2. New demo script "embeddedWindows.tcl" illustrating the use of embedded windows in tablelist widgets; this is discussed in a new section of the tutorial "tablelist.html". 3. Significantly improved and optimized the handling of embedded images. 4. Simplified the support for user-defined binding scripts with the aid of the new commands "tablelist::getTablelistPath" and "tablelist::convEventFields", as well as of a new binding tag whose name is returned by the new "bodytag" subcommand (which is now used in the demo script "browse.tcl"). 5. Support for the new virtual events <>, <>, <> and <> (thanks to John Vidolich for his proposal). In addition, the new virtual event <> can now be used instead of <> (which is supported for compatibility reasons). 6. New subcommand "itemlistvar", for accessing the tablelist widget's internal list (thanks to Patrick Fradin for his valuable input). 7. Fixed a bug related to the "-listvariable" option, introduced in the previous Tablelist release (thanks to Torsten Reincke for his bug report). 8. Fixed two bugs related to the "cellselection" subcommand (thanks to John Vidolich for his bug report). 9. Fixed a few typos and minor bugs in the default binding scripts (thanks to Patrick Fradin, Tore Morkemo, and Torsten Reincke for their bug reports). 10. Numerous further improvements and minor bug fixes. What was new in Tablelist 3.5? ------------------------------ 1. New configuration option "-selecttype" with the values "row" and "cell", and new binding scripts supporting these two selection types (thanks to Kevin Partin for his proposal and to Dietmar Müller for his valuable contribution). 2. New subcommands "activatecell", "cellselection", and "curcellselection", used in the binding scripts mentioned above. 3. The words "active" and "anchor" are now recognized as valid column and cell indices, too. 4. New configuration options "-movablerows" and "-movecursor", and new mouse bindings for moving a row interactively (thanks to Dan Rogahn for his valuable contribution). 5. The key sequences used for navigation between the editable cells now also move the active item or element and change the (cell)selection and the (cell)selection anchor in the body of the tablelist widget. 6. Improved the handling and appearance of the checkbutton widget when used as edit window (thanks to Kevin Partin for reporting a problem experienced when the tablelist is embedded into an Iwidgets dialogshell). 7. The "-listvariable" option now supports variable names returned by the "itcl::scope" command, too (thanks to Nicolae Mihalache for his bug report). 8. Fixed a very long-standing bug related to horizontal scrolling when using a non-default font (thanks to Brand Hilton for his bug report and fix). 9. Fixed another very long-standing bug, related to list variables (thanks to Dr. Detlef Groth and John R. Smith for their bug reports). 10. Numerous further improvements and minor bug fixes (thanks to Patrick Fradin for his valuable input). What was new in Tablelist 3.4? ------------------------------ 1. New column configuration option "-editwindow", specifying the widget type used for interactive cell editing in the respective column (thanks to Damon Courtney, Patrick Fradin, and Keesang Song for their proposals and to Mats Bengtsson and Benny Riefenstein for their help related to the Macintosh platform). The edit window may be a Tk core entry, spinbox, or checkbutton, or one of the 16 supported widgets from the packages BWidget, Iwidgets, combobox (by Bryan Oakley), and Mentry. 2. New subcommand "editwinpath". 3. Three new demo scripts illustrating the use of the "-editwindow" option; these are discussed in a new section of the tutorial "tablelist.html". 4. New column configuration option "-maxwidth" (thanks to Tore Morkemo for his proposal). 5. The event in a column label now restores the column's last static width (thanks to Dietmar Müller for his valuable input). 6. Changing a tablelist's font now updates the column widths accordingly. 7. Improved the handling of the "-setgrid" option. 8. Improved the error handling related to the option database in the general mega-widget utility module "mwutil.tcl". 9. Fixed a minor bug in the "containingcolumn" subcommand (thanks to David Mattinson for his bug report). 10. Restored the support for Tcl/Tk versions earlier than 8.0.4, which has been broken since release 3.0, due to the use of the event, introduced in Tk 8.0.4. 11. Further code improvements (thanks to Patrick Fradin for his valuable input). 12. Many improvements in the documentation, including a new Quick Reference section (thanks to Dietmar Müller for his valuable contribution). What was new in Tablelist 3.3? ------------------------------ 1. New column configuration option "-text" (thanks to Paul Kienzle for his proposal). 2. New subcommands "containing", "containingcolumn", "containingcell", and "fillcolumn". 3. New subcommands "deletecolumns", "insertcolumns", and "insertcolumnlist" (thanks to Kevin Partin and Paul Kienzle for their proposals). 4. Renamed the subcommands "getcolumn" and "getkey" to "getcolumns" and "getkeys", respectively. (This won't break any existing scripts, because the old command names are abbreviations of the new ones.) 5. Restored the support for Tcl/Tk versions earlier than 8.4, which was broken in Tablelist 3.1 and 3.2, due to the use of the improved syntax of the "place configure" command, introduced in Tk 8.4 (thanks to David Mattinson, Kurt Braganza, and Alexander Baath for reporting this problem). 6. Fixed a bug in the "editcell" subcommand, introduced in Tablelist 3.1 (thanks to Damon Courtney for his bug report). 7. Improved the demo script "config.tcl" (thanks to Mats Bengtsson for his input). 8. Restructured the code by moving several procedures from the distribution file "tablelistWidget.tcl" into smaller, more manageable modules. 9. Numerous further improvements and minor bug fixes. What was new in Tablelist 3.2? ------------------------------ 1. The key associated with a tablelist item can now be used as a row index and as the first component of a cell index of the form "row,col". 2. The "delete", "get", "getcolumn", "getkey", "selection clear", and "selection set" subcommands now also accept a list of indices as single argument (thanks to Damon Courtney and Erik Leunissen for their proposals). 3. Made the interactive "movecolumn" operation more intuitive and compatible with the behavior exhibited by similar actions in popular applications on various platforms (thanks to Paul Kienzle for his suggestion). For example, the target position of the column being moved is now indicated by a temporary gap displayed in the tablelist's header. 4. New configuration option "-targetcolor", used to set the color of the gap mentioned above. 5. Fixed a bug related to the event, caused by a missing close-bracket in the last release (thanks to Patrick Fradin for his bug report). 6. Fixed a bug that raised an error in the "movecolumn" command for an empty tablelist widget (thanks to Paul Kienzle for his bug report). 7. The workaround in the "xview" and "yview" subcommands for a Tk bug under Mac OS X Aqua is now only activated for that windowing system, since (as reported by Patrick Fradin) it caused problems on some other systems. 8. Further minor code improvements. What was new in Tablelist 3.1? ------------------------------ 1. New configuration options "-movablecolumns" and "-movecolumncursor". 2. New column configuration option "-name", whose value can also be used as a column index and as the second component of a cell index of the form "row,col". 3. New subcommands "move", "movecolumn", "getcolumn", "getkey", and "finishediting" (thanks to Damon Courtney, Daniel Fehrenbach, Jeff Godfrey, and Kevin Partin for their proposals). 4. Extended the scope of the "cancelediting" subcommand. 5. New mouse bindings for moving a column interactively. 6. The autoscrolling, as described in the "DEFAULT BINDINGS" section of the "listbox" manual entry, is now implemented for the header of a tablelist widget, too. 7. The interactive cell editing is now finished by any mouse click in the tablelist's body, outside the cell just being edited (thanks to Patrick Fradin and Jeff Godfrey for this suggestion). 8. The value returned by the "selection includes" command no longer depends on the tablelist's state. 9. Worked around a bug in Tk 8.4.0 and 8.4.1 related to the "selection handle" command, which caused crashes under KDE 3.0 (thanks to Andres Garcia for reporting this and to Joe English for suggesting the workaround and fixing the bug in Tk 8.4.2). 10. Improved the support of Mac OS X Aqua and Mac OS Classic (thanks to Mats Bengtsson, Raymond Calande, Techin Alex Kang, Bernhard Spinnler, and especially to Benny Riefenstein for their valuable contributions). 11. Fixed a bug related to the invocation of the "cellconfigure" subcommand from within a pre-edit callback (thanks to Dr. Johannes- Heinrich Vogeler for his bug report). 12. Several performance improvements (thanks to Patrick Fradin for his valuable suggestions). 13. Improved the platform-specific stuff in the demo scripts "config.tcl" and "browse.tcl". 14. Numerous further improvements in the code and documentation. What was new in Tablelist 3.0? ------------------------------ The main new feature provided by this release is the support for interactive cell editing (thanks to Juri Shimon, Dr. Johannes-Heinrich Vogeler, and Jeff Godfrey for their proposal). The first three items below are related to this subject: 1. New configuration options "-editstartcommand" and "-editendcommand". 2. New column and cell configuration option "-editable". 3. New subcommands "editcell", "entrypath", "cancelediting", and "rejectinput". Further changes: 4. New subcommands "seecolumn" and "seecell". 5. Tabulator and newline characters are now retained in the internal list, displayed as "\t" and "\n", and supported by interactive cell editing (thanks to Jacek Jenrysik for his query concerning multi- line items). 6. The redisplay and sorting of tablelist items have become dramatically faster (thanks to Matt Becker for his input that determined me to optimize these operations, and also for his testing). 7. Further performance improvements (thanks to Patrick Fradin for his valuable contribution). 8. The option values displayed by the demo script "config.tcl" can now be edited interactively. 9. Minor improvements in the code and documentation. What was new in Tablelist 2.8? ------------------------------ 1. The trailing or leading ellipsis ("...") used when displaying the elements that don't fit into their cells can now be replaced with an arbitrary string specified with the aid of the new "-snipstring" configuration option (thanks to Tore Morkemo for his proposal). 2. New value "none" for the "-activestyle" configuration option. 3. When exporting the selection, the elements of the hidden columns are now skipped and the contents of the visible cells are transformed according to the value of the "-formatcommand" option for the corresponding columns. 4. Improved and simplified the focus control (thanks to Juri Shimon and Gopal Reddy for their bug reports). 5. Further minor code improvements. What was new in Tablelist 2.7? ------------------------------ 1. Increased the speed of the "insert" and "insertlist" subcommands as well as that of item insertions with the aid of the "-listvariable" option by a factor of about 1.3. The "insert" subcommand is now about 2.3 times faster than in version 2.4. Compared to version 2.4, item insertion with the aid of the "-listvariable" option has become more than 10 times faster. 2. The number of pixels by which a column is stretched is now proportional to its width in pixels. Based on this change, significantly improved the stretching behavior after an interactive column resize operation (thanks to Mats Bengtsson for his valuable suggestions). 3. Fixed a bug in the "-(label)font" and "-labelborderwidth" configuration options, introduced in version 2.5 (thanks to Bastien Chevreux for his bug report). 4. Fixed a bug in the "columncget", "rowcget", and "cellcget" subcommands, introduced in version 2.3 (again, thanks to Bastien Chevreux for reporting this bug). 5. Fixed a bug in the binding scripts for the binding tag "TablelistBody" (thanks to Miguel Bañón for his bug report). 6. Applied a patch proposed by Jeff Adamczak that works around a bug in the "lsort" command, present in Tcl versions 8.0 - 8.3.2. 7. Applied a patch proposed (in a slightly different form) by Mats Bengtsson that works around a bug in the "info script" command on the Macintosh. 8. Further minor code improvements. What was new in Tablelist 2.6? ------------------------------ The only change in this version is a bug-fix eliminating a rather nasty bug in the "insert" and "insertlist" subcommands, introduced in the previous release. Thanks to Mats Bengtsson for his bug report and to Jeffrey Hobbs for suggesting me to bump the version number to 2.6. What was new in Tablelist 2.5? ------------------------------ 1. Increased the speed of the "insert" subcommand by a factor of about 1.8 and that of item insertions with the aid of the "-listvariable" option by a factor of about 8. (These figures are based on speed measurements made with two tablelist widgets: one having 1000 rows and 10 columns and another one with 5000 rows and 20 columns.) 2. The "delete", "sort", and "sortbycolumn" subcommands, as well as row and cell updates with the aid of the "rowconfigure" and "cellconfigure" operations have also become significantly faster. 3. New "insertlist" subcommand. 4. New "-stripeheight" configuration option (thanks to Gregory Samoluk for his proposal). 5. If no columns are to be stretched then the blank space following the header labels is now filled with a dummy, insensitive label having the same background, borderwidth, and relief as the "normal" header labels. 6. Fixed a bug concerning the placement of the arrow indicating the sorting order (thanks to Robert Minichino for his bug report). 7. Improved the handling of header labels with embedded images, to eliminate some peculiarities experienced on Windows. 8. Several further improvements and minor bug fixes. What was new in Tablelist 2.4? ------------------------------ 1. New column configuration option "-formatcommand" (thanks to Jeff Godfrey for his proposal). This option is now used in the demo script "browse.tcl". 2. New row configuration option "-selectable" (thanks to Tore Morkemo for this proposal). 3. Significantly improved the performance of the row and cell updates, as well as of the "delete" subcommand (thanks to Emanuele Lupi for her input that determined me to optimize these operations). 4. The widget implementation is now fully compatible with the recent changes made in Tk 8.4a4 (thanks to Patrick Fradin for his input). 5. Pop-up menus as children of a tablelist widget cause no problem any longer (thanks to Andres Garcia and Bastien Chevreux for reporting this bug, introduced in the previous release). 6. Fixed a bug caused by the delayed redisplay after changing the number of columns (thanks to Tore Morkemo for his bug report). 7. Minor improvements in the code and documentation. What was new in Tablelist 2.3? ------------------------------ 1. New configuration option "-activestyle", enabling to surround the active item with a frame instead of underlining it. 2. The columns can now be separated with borders, by making use of the new configuration option "-showseparators". 3. A nice distinguishing effect for the rows can now be obtained with the aid of the new configuration options "-stripebackground" and "-stripeforeground". 4. New tablelist widget subcommands "separatorpath" and "separators". 5. Fixed a bug related to the column index if the header labels are hidden (thanks to Emanuele Lupi for her bug report). 6. New demo script "styles.tcl", showing several ways to improve the appearance of a tablelist widget. 7. The demo scripts "config.tcl" and "browse.tcl" now make use of the new "-stripebackground" option. 8. Numerous further improvements and minor bug fixes (thanks to Patrick Fradin for his valuable input). What was new in Tablelist 2.2? ------------------------------ 1. The "-font" configuration option can now be specified at column, row, and cell level, too (this was proposed and partly implemented by Patrick Fradin). The data will be aligned properly, no matter if the fonts are of different sizes. 2. Significantly improved the performance of the Tcl command associated with a tablelist widget, especially that of the "delete", "sort", and "sortbycolumn" subcommands for a large number (i.e., several thousands) of items. 3. Corrected the creation of the arrow indicating the sorting order, to make sure that it works under all supported Tcl/Tk versions (thanks to Juri Shimon and Andres Garcia for their bug reports). 4. Several improvements in the demo scripts "config.tcl" and "browse.tcl". Among others, the GUIs generated by these scripts now have a better platform-specific look & feel (many thanks to Mats Bengtsson for his valuable suggestions concerning the Macintosh platform). 5. Further minor improvements in the code. What was new in Tablelist 2.1? ------------------------------ 1. The up- or down-arrow indicating the sorting order now has a 3-D border, giving the arrow a sunken relief. 2. Due to the new 3-D look of the arrow, the default values of the "-arrowcolor" and "-arrowdisabledcolor" configuration options have been changed to an empty string, indicating that the arrow will inherit the background color of the label in which it is placed. 3. Several improvements in the demo script "browse.tcl". 4. Minor improvements in the code and documentation. 5. The distribution file "tablelist2_1.zip" for Windows now includes the "tablelist2.1" directory, hence it is no longer necessary to create this folder before unpacking the distribution file (thanks to Kevin Partin for this suggestion). What was new in Tablelist 2.0? ------------------------------ 1. New cell configuration option "-image", used to set and retrieve the image to be displayed (by itself or together with a text) in a cell of a tablelist widget. 2. New column configuration option "-labelimage" specifying the image to be displayed (by itself or combined with a text) in a column label. 3. The alignment of a header label can now be defined to be different from that of the elements contained in its column, by using the new column configuration option "-labelalign". 4. Renamed the column configuration option "-justify" to "-align", because (at least in the case of the header labels) this actually specifies not only the justification, but also the anchor point. Hopefully, this POTENTIAL INCOMPATIBILITY will not break too many existing applications, because the column alignments are usually specified within the "-columns" global option. 5. Fixed a bug that raised an error when some configuration options were specified at widget creation time before the "-columns" option (thanks to Bastien Chevreux for his bug report). 6. Reverted the implementation of the focus control to that contained in the pre-1.6 Tablelist releases, because its simplified version from the last release failed to work as expected if a tablelist was the only widget taking the focus during keyboard traversal (thanks to Juri Shimon for his bug report). 7. Fixed a bug that caused an erronous return value of the "labels" subcommand if the arrow indicating the sorting order was displayed. 8. Several performance improvements, kindly contributed by Patrick Fradin. 9. To improve the performance even further, the invocations of "info exists" for array elements are no longer replaced with a call to a helper procedure (introduced in Tablelist 1.2), because the Tcl bug that made this necessary for Tcl versions 8.2, 8.3.0 - 8.3.2, and 8.4a1 was fixed in Tcl 8.3.3 and 8.4a2. If for some reason you cannot upgrade your Tcl/Tk version, then you should patch the file "tablelistWidget.tcl" with the aid of the script "repair.tcl", as described in the files "README.txt" and "tablelist.html". 10. The demo script "browse.tcl" now inserts an image into the first cell of each row of the tablelist widget. 11. Numerous further improvements and minor bug fixes. What was new in Tablelist 1.6? ------------------------------ 1. The value of the "-stretch" configuration option is now ignored if the width of the tablelist widget was specified as zero or less. This change was necessary in order to improve the behavior of dynamic-width tablelist widgets with the "-setgrid" option set to true. 2. By pressing mouse button 1 over a header label, the label's relief is now only changed to "sunken" if the value of the global or column-specific "-labelcommand" option is nonempty. 3. Several improvements concerning hidden columns (thanks to Juri Shimon for his bug report). 4. Made the focus control more straight-forward. 5. Extended the "How to use it?" section of the tutorial "tablelist.html". What was new in Tablelist 1.5? ------------------------------ This version contains mainly bug fixes and small improvements. Many thanks to Andres Garcia, Bastien Chevreux, and Patrick Fradin for their valuable contributions. 1. Fixed a bug concerning the "-label*" configuration options. 2. Fixed the erronous invocation of "getSubCmd" in the selection handler "fetchSelection" (this bug was introduced in version 1.1). 3. Elements that don't fit into their cells are now displayed with a trailing or leading ellipsis ("..."), depending on the column alignment. 4. Several further improvements and minor bug fixes. What was new in Tablelist 1.4? ------------------------------ 1. New "-stretch" configuration option specifying the columns that are to be stretched in order to eliminate the blank space that might appear at the right of the table. 2. Improved the error handling in the "attrib", "configure", "columnconfigure", "rowconfigure", and "cellconfigure" subcommands. 3. Improved the demo scripts "browse.tcl" and "config.tcl". What was new in Tablelist 1.3? ------------------------------ 1. The "sortbycolumn" subcommand now per default places an up- or down-arrow indicating the sorting order into the respective column's label. This can be enabled or disabled with the new "-showarrow" configuration option, at both widget and column level. 2. New configuration options "-arrowcolor", "-arrowdisabledcolor", and "-incrarrowtype" to control the appearance of the arrow mentioned above. 3. New "resetsortinfo" subcommand, used to reset the information about the sorting of the items. 4. Improved the demo script "browse.tcl". 5. Further improvements in the code and documentation. What was new in Tablelist 1.2? ------------------------------ 1. Whereever possible, eliminated the invocations of "info exists" for array elements. This works around a severe bug in Tcl versions 8.2 and 8.3 (fixed in 8.4a2), which causes excessive memory use when calling "info exists" on a non-existent array element. Some serious memory leaks in earlier Tablelist versions when run under Tcl/Tk 8.2 or 8.3 (reported by Henning Hanusa and Christian Burrini) could be tracked down to this very annoying Tcl bug (which I was not aware of until recently). 2. The help variables used in the initialization of the "tablelist" namespace are now declared with the "variable" keyword, in order to avoid any conflicts with global variables. 3. Improved the parsing of configuration and command options. What was new in Tablelist 1.1? ------------------------------ This version contains mainly bug fixes and small improvements. Many thanks to Patrick Fradin, Bastien Chevreux, and Mats Bengtsson for their valuable contributions. 1. Fixed some bugs in the implementation of the "-listvariable" option. Also, the value of this option can now be an array element, not only a scalar variable. 2. Fixed a bug in the implementation of the "get" subcommand. 3. New "sortcolumn" and "sortorder" subcommands to query the arguments of the last sorting. 4. Improved the look & feel of tablelist widgets on the Macintosh. 5. Worked around a bug in Tk 8.3.0 (fixed in 8.3.1) concerning listbox widgets with configured "-cursor" option. 6. Several further improvements and minor bug fixes. What was new in Tablelist 1.0? ------------------------------ 1. New "-resizable" option for the "columnconfigure" subcommand. 2. New "labels" subcommand. returning the list of the header labels. 3. The "-disabledforeground" and "-state" configuration options no longer require Tk version 8.3 or higher. 4. All "-label*" column configuration options can now have an empty string as value, meaning that the corresponding global option will be used instead of the column-specific one. 5. Improved the output of the "columnconfigure" subcommand. 6. The help variables used in the coordinate transformations within the scripts defined for the "TablelistBody" binding tag have been moved into the "tablelist" namespace, in order to avoid any conflicts with global variables. 7. Improved cross-platform support with the aid of the new <> virtual event. 8. Fixed a bug in the "compareAsSet" procedure of the demo script "config.tcl". 9. New demo script "browse.tcl", containing a simple widget browser based on a tablelist. 10. Both demo scripts now use a namespace for their procedures, to avoid any conflicts when evaluating them with the "source" command. 11. The tutorial "tablelist.html" is now completed and includes a detailed discussion of both demo scripts mentioned above. 12. Numerous further improvements in the code and documentation. What was new in Tablelist 0.9? ------------------------------ 1. The documentation now includes the tutorial "tablelist.html" (part of which is still work in progress), as well as reference pages for the two exported commands "tablelist::tablelist" and "tablelist::sortByColumn". 2. The "-listvariable" configuration option is now fully implemented. 3. A column of a tablelist widget can now be made invisible by using the new "-hide" option of the "columnconfigure" subcommand. 4. The contents of a row can now be updated with the new "-text" option of the "rowconfigure" subcommand. 5. For Tk versions 8.3 or higher the "tablelist::tablelist" command now supports the "-disabledforeground", "-labeldisabledforeground", and "-state" configuration options. 6. Replaced "[focus]" with "[focus -displayof $win]", so that the code will work properly in applications using multiple displays. Similarly, the "font measure" command is now invoked with the "-displayof $win" option. This also works around a peculiarity of the "font measure" command. 7. Renamed "tablelistBindingTag" to "Tablelist". 8. Fixed a bug in the private procedure "colIndex", for arguments of the form "@x,y". This procedure is invoked (directly or indirectly) in the implementation of all commands that take a column or cell index or an x coordinate as argument. 9. Numerous further improvements and minor bug fixes. kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistThemes.tcl0000644000175000017500000014656311070725164024636 0ustar domibeldomibel#============================================================================== # Contains procedures that populate the array themeDefaults with theme-specific # default values of some tablelist configuration options. # # Structure of the module: # - Public procedures related to tile themes # - Private procedures related to tile themes # - Private procedures performing RGB <-> HSV conversions # - Private procedures related to global KDE configuration options # # Copyright (c) 2005-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== # # Public procedures related to tile themes # ======================================== # #------------------------------------------------------------------------------ # tablelist::getCurrentTheme # # Returns the current tile theme. #------------------------------------------------------------------------------ proc tablelist::getCurrentTheme {} { if {[info exists ttk::currentTheme]} { return $ttk::currentTheme } else { return $tile::currentTheme } } #------------------------------------------------------------------------------ # tablelist::setThemeDefaults # # Populates the array themeDefaults with theme-specific default values of some # tablelist configuration options and updates the array configSpecs. #------------------------------------------------------------------------------ proc tablelist::setThemeDefaults {} { variable themeDefaults if {[catch {[getCurrentTheme]Theme}] != 0} { # # Fall back to the "default" theme (which is the root of all # themes) and then override the options set by the current one # defaultTheme array set themeDefaults [style configure .] } if {[string compare $themeDefaults(-arrowcolor) ""] == 0} { set themeDefaults(-arrowdisabledcolor) "" } else { set themeDefaults(-arrowdisabledcolor) $themeDefaults(-labeldisabledFg) } variable configSpecs foreach opt {-background -foreground -disabledforeground -stripebackground -selectbackground -selectforeground -selectborderwidth -font -labelbackground -labelforeground -labelfont -labelborderwidth -labelpady -arrowcolor -arrowdisabledcolor -arrowstyle} { if {[llength $configSpecs($opt)] < 4} { lappend configSpecs($opt) $themeDefaults($opt) } else { lset configSpecs($opt) 3 $themeDefaults($opt) } } } # # Private procedures related to tile themes # ========================================= # #------------------------------------------------------------------------------ # tablelist::altTheme #------------------------------------------------------------------------------ proc tablelist::altTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #a3a3a3 \ -stripebackground "" \ -selectbackground #4a6984 \ -selectforeground #ffffff \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground #d9d9d9 \ -labeldisabledBg #d9d9d9 \ -labelactiveBg #ececec \ -labelpressedBg #ececec \ -labelforeground black \ -labeldisabledFg #a3a3a3 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor "" \ -arrowstyle sunken10x9 \ ] } #------------------------------------------------------------------------------ # tablelist::aquaTheme #------------------------------------------------------------------------------ proc tablelist::aquaTheme {} { # # Get an approximation of alternateSelectedControlColor # switch [winfo rgb . systemHighlight] { "51143 53456 56281" { set selectBg #738499 } "50887 50887 50887" { set selectBg #7f7f7f } "46516 54741 65535" { set selectBg #3875d7 } "64506 60908 29556" { set selectBg #ffc11f } "65535 45487 35978" { set selectBg #f34648 } "65535 53968 33154" { set selectBg #ff8a22 } "50114 63994 37263" { set selectBg #66c547 } "59879 47290 65535" { set selectBg #8c4eb8 } default { set rgb [winfo rgb . systemHighlight] foreach {h s v} [eval rgb2hsv $rgb] {} set s [expr {$s*4.0/3.0}] if {$s > 1.0} { set s 1.0 } set v [expr {$v*3.0/4.0}] if {$v > 1.0} { set v 1.0 } set rgb [hsv2rgb $h $s $v] set selectBg [eval format "#%04x%04x%04x" $rgb] } } variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #a3a3a3 \ -stripebackground "" \ -selectbackground $selectBg \ -selectforeground white \ -selectborderwidth 0 \ -font {"Lucida Grande" 12} \ -labelbackground #f4f4f4 \ -labeldisabledBg #f4f4f4 \ -labelactiveBg #f4f4f4 \ -labelpressedBg #e4e4e4 \ -labelforeground black \ -labeldisabledFg #a3a3a3 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont {"Lucida Grande" 11} \ -labelborderwidth 1 \ -labelpady 1 \ -arrowcolor #777777 \ -arrowstyle flat7x7 \ ] } #------------------------------------------------------------------------------ # tablelist::AquativoTheme #------------------------------------------------------------------------------ proc tablelist::AquativoTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground black \ -stripebackground "" \ -selectbackground #000000 \ -selectforeground #ffffff \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground #fafafa \ -labeldisabledBg #fafafa \ -labelactiveBg #fafafa \ -labelpressedBg #fafafa \ -labelforeground black \ -labeldisabledFg black \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor #777777 \ -arrowstyle flat7x7 \ ] } #------------------------------------------------------------------------------ # tablelist::blueTheme #------------------------------------------------------------------------------ proc tablelist::blueTheme {} { variable themeDefaults array set themeDefaults [list \ -background #e6f3ff \ -foreground black \ -disabledforeground #666666 \ -stripebackground "" \ -selectbackground #ffff33 \ -selectforeground #000000 \ -selectborderwidth 1 \ -font TkTextFont \ -labelbackground #6699cc \ -labeldisabledBg #6699cc \ -labelactiveBg #6699cc \ -labelpressedBg #6699cc \ -labelforeground black \ -labeldisabledFg #666666 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor "" \ -arrowstyle sunken10x9 \ ] } #------------------------------------------------------------------------------ # tablelist::clamTheme #------------------------------------------------------------------------------ proc tablelist::clamTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #999999 \ -stripebackground "" \ -selectbackground #4a6984 \ -selectforeground #ffffff \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground #dcdad5 \ -labeldisabledBg #dcdad5 \ -labelactiveBg #eeebe7 \ -labelpressedBg #eeebe7 \ -labelforeground black \ -labeldisabledFg #999999 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor "" \ -arrowstyle sunken10x9 \ ] } #------------------------------------------------------------------------------ # tablelist::classicTheme #------------------------------------------------------------------------------ proc tablelist::classicTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #a3a3a3 \ -stripebackground "" \ -selectbackground #c3c3c3 \ -selectforeground #000000 \ -selectborderwidth 1 \ -font TkTextFont \ -labelbackground #d9d9d9 \ -labeldisabledBg #d9d9d9 \ -labelactiveBg #ececec \ -labelpressedBg #ececec \ -labelforeground black \ -labeldisabledFg #a3a3a3 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor "" \ -arrowstyle sunken10x9 \ ] if {[info exists tile::version] && [string compare $tile::version 0.8] < 0} { set themeDefaults(-font) TkClassicDefaultFont set themeDefaults(-labelfont) TkClassicDefaultFont } } #------------------------------------------------------------------------------ # tablelist::defaultTheme #------------------------------------------------------------------------------ proc tablelist::defaultTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #a3a3a3 \ -stripebackground "" \ -selectbackground #4a6984 \ -selectforeground #ffffff \ -selectborderwidth 1 \ -font TkTextFont \ -labelbackground #d9d9d9 \ -labeldisabledBg #d9d9d9 \ -labelactiveBg #ececec \ -labelpressedBg #ececec \ -labelforeground black \ -labeldisabledFg #a3a3a3 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 1 \ -labelpady 1 \ -arrowcolor "" \ -arrowstyle sunken10x9 \ ] } #------------------------------------------------------------------------------ # tablelist::keramikTheme #------------------------------------------------------------------------------ proc tablelist::keramikTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #aaaaaa \ -stripebackground "" \ -selectbackground #000000 \ -selectforeground #ffffff \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground #cccccc \ -labeldisabledBg #cccccc \ -labelactiveBg #cccccc \ -labelpressedBg #cccccc \ -labelforeground black \ -labeldisabledFg #aaaaaa \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor black \ -arrowstyle flat8x5 \ ] } #------------------------------------------------------------------------------ # tablelist::krocTheme #------------------------------------------------------------------------------ proc tablelist::krocTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #b2b2b2 \ -stripebackground "" \ -selectbackground #000000 \ -selectforeground #ffffff \ -selectborderwidth 1 \ -font TkTextFont \ -labelbackground #fcb64f \ -labeldisabledBg #fcb64f \ -labelactiveBg #694418 \ -labelpressedBg #694418 \ -labelforeground black \ -labeldisabledFg #b2b2b2 \ -labelactiveFg #ffe7cb \ -labelpressedFg #ffe7cb \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor "" \ -arrowstyle sunken10x9 \ ] } #------------------------------------------------------------------------------ # tablelist::plastikTheme #------------------------------------------------------------------------------ proc tablelist::plastikTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #aaaaaa \ -stripebackground "" \ -selectbackground #657a9e \ -selectforeground #ffffff \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground #cccccc \ -labeldisabledBg #cccccc \ -labelactiveBg #cccccc \ -labelpressedBg #cccccc \ -labelforeground black \ -labeldisabledFg #aaaaaa \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor black \ -arrowstyle flat7x4 \ ] } #------------------------------------------------------------------------------ # tablelist::srivTheme #------------------------------------------------------------------------------ proc tablelist::srivTheme {} { variable themeDefaults array set themeDefaults [list \ -background #e6f3ff \ -foreground black \ -disabledforeground #666666 \ -stripebackground "" \ -selectbackground #ffff33 \ -selectforeground #000000 \ -selectborderwidth 1 \ -font TkTextFont \ -labelbackground #a0a0a0 \ -labeldisabledBg #a0a0a0 \ -labelactiveBg #a0a0a0 \ -labelpressedBg #a0a0a0 \ -labelforeground black \ -labeldisabledFg #666666 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor "" \ -arrowstyle sunken10x9 \ ] } #------------------------------------------------------------------------------ # tablelist::srivlgTheme #------------------------------------------------------------------------------ proc tablelist::srivlgTheme {} { variable themeDefaults array set themeDefaults [list \ -background #e6f3ff \ -foreground black \ -disabledforeground #666666 \ -stripebackground "" \ -selectbackground #ffff33 \ -selectforeground #000000 \ -selectborderwidth 1 \ -font TkTextFont \ -labelbackground #6699cc \ -labeldisabledBg #6699cc \ -labelactiveBg #6699cc \ -labelpressedBg #6699cc \ -labelforeground black \ -labeldisabledFg #666666 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor "" \ -arrowstyle sunken10x9 \ ] } #------------------------------------------------------------------------------ # tablelist::stepTheme #------------------------------------------------------------------------------ proc tablelist::stepTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #808080 \ -stripebackground "" \ -selectbackground #fdcd00 \ -selectforeground #ffffff \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground #a0a0a0 \ -labeldisabledBg #a0a0a0 \ -labelactiveBg #aeb2c3 \ -labelpressedBg #aeb2c3 \ -labelforeground black \ -labeldisabledFg #808080 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor "" \ -arrowstyle sunken10x9 \ ] } #------------------------------------------------------------------------------ # tablelist::tileqtTheme # # Tested with the following Qt styles: # # Acqua KDE_XP Motif Plus SGI # B3/KDE Keramik MS Windows 9x System-Series # Baghira Light Style, 2nd revision Phase System++ # CDE Light Style, 3rd revision Plastik ThinKeramik # HighColor Classic Lipstik Platinum # HighContrast Marble QtCurve # KDE Classic Motif RISC OS # # Supported color schemes: # # Aqua Blue Ice (FreddyK) Point Reyes Green # Aqua Graphite KDE 1 Pumpkin # Atlas Green KDE 2 Redmond 2000 # BeOS Keramik Redmond 95 # Blue Slate Keramik Emerald Redmond XP # CDE Keramik White Solaris # Dark Blue Lipstik Noble Storm # Desert Red Lipstik Standard SuSE, old & new # Digital CDE Lipstik White SUSE-kdm # EveX Media Peach System # High Contrast Black Text Next Thin Keramik, old & new # High Contrast Yellow on Blue Pale Gray Thin Keramik II # High Contrast White Text Plastik #------------------------------------------------------------------------------ proc tablelist::tileqtTheme {} { set bg [tileqt_currentThemeColour -background] set fg [tileqt_currentThemeColour -foreground] set tableBg [tileqt_currentThemeColour -base] set tableFg [tileqt_currentThemeColour -text] set tableDisFg [tileqt_currentThemeColour -disabled -text] set selectBg [tileqt_currentThemeColour -highlight] set selectFg [tileqt_currentThemeColour -highlightedText] set labelBg [tileqt_currentThemeColour -button] set labelFg [tileqt_currentThemeColour -buttonText] set labelDisFg [tileqt_currentThemeColour -disabled -buttonText] set style [string tolower [tileqt_currentThemeName]] set pressedBg $labelBg # # For most Qt styles the label colors depend on the color scheme: # switch "$bg $labelBg" { "#fafafa #6188d7" { ;# color scheme "Aqua Blue" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #d0d0d0 } "baghira" { set labelBg #f5f5f5; set pressedBg #9ec2fa } "highcolor" { set labelBg #628ada; set pressedBg #6188d7 } "keramik" { set labelBg #8fabe4; set pressedBg #7390cc } "phase" { set labelBg #6188d7; set pressedBg #d0d0d0 } "plastik" { set labelBg #666bd6; set pressedBg #5c7ec2 } "qtcurve" { set labelBg #f4f4f4; set pressedBg #d0d0d0 } "thinkeramik" { set labelBg #f4f4f4; set pressedBg #dedede } } } "#ffffff #89919b" { ;# color scheme "Aqua Graphite" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #d4d4d4 } "baghira" { set labelBg #f5f5f5; set pressedBg #c3c7cd } "highcolor" { set labelBg #8b949e; set pressedBg #89919b } "keramik" { set labelBg #acb1b8; set pressedBg #91979e } "phase" { set labelBg #89919b; set pressedBg #d4d4d4 } "plastik" { set labelBg #8c949d; set pressedBg #7f868e } "qtcurve" { set labelBg #f6f6f6; set pressedBg #d4d4d4 } "thinkeramik" { set labelBg #f4f4f4; set pressedBg #e2e2e2 } } } "#afb49f #afb49f" { ;# color scheme "Atlas Green" switch -- $style { "light, 3rd revision" { set pressedBg #c1c6af } "platinum" { set pressedBg #929684 } "baghira" { set labelBg #e5e8dc; set pressedBg #dadcd0 } "highcolor" { set labelBg #b2b6a1; set pressedBg #afb49f } "keramik" { set labelBg #c7cabb; set pressedBg #adb1a1 } "phase" { set labelBg #a7b49f; set pressedBg #929684 } "plastik" { set labelBg #acb19c; set pressedBg #959987 } "qtcurve" { set labelBg #adb19e; set pressedBg #939881 } "thinkeramik" { set labelBg #c1c4b6; set pressedBg #a5a999 } } } "#d9d9d9 #d9d9d9" { ;# color scheme "BeOS" switch -- $style { "light, 3rd revision" { set pressedBg #eeeeee } "platinum" { set pressedBg #b4b4b4 } "baghira" { set labelBg #f2f2f2; set pressedBg #e9e9e9 } "highcolor" { set labelBg #dcdcdc; set pressedBg #d9d9d9 } "keramik" { set labelBg #e5e5e5; set pressedBg #cdcdcd } "phase" { set labelBg #dadada; set pressedBg #b4b4b4 } "plastik" { set labelBg #d6d6d6; set pressedBg #b6b6b6 } "qtcurve" { set labelBg #d6d6d6; set pressedBg #b5b5b5 } "thinkeramik" { set labelBg #dddddd; set pressedBg #c5c5c5 } } } "#9db9c8 #9db9c8" { ;# color scheme "Blue Slate" switch -- $style { "light, 3rd revision" { set pressedBg #adcbdc } "platinum" { set pressedBg #8299a6 } "baghira" { set labelBg #ddeff6; set pressedBg #d0e1ea } "highcolor" { set labelBg #9fbbcb; set pressedBg #9db9c8 } "keramik" { set labelBg #baced9; set pressedBg #a0b5c1 } "phase" { set labelBg #9db9c9; set pressedBg #8299a6 } "plastik" { set labelBg #99b6c5; set pressedBg #869fab } "qtcurve" { set labelBg #9bb7c6; set pressedBg #7c9cad } "thinkeramik" { set labelBg #b5c8d2; set pressedBg #98adb8 } } } "#999999 #999999" { ;# color scheme "CDE" switch -- $style { "light, 3rd revision" { set pressedBg #a8a8a8 } "platinum" { set pressedBg #7f7f7f } "baghira" { set labelBg #d5d5d5; set pressedBg #cccccc } "highcolor" { set labelBg #9b9b9b; set pressedBg #999999 } "keramik" { set labelBg #b7b7b7; set pressedBg #9d9d9d } "phase" { set labelBg #999999; set pressedBg #7f7f7f } "plastik" { set labelBg #979797; set pressedBg #808080 } "qtcurve" { set labelBg #979797; set pressedBg #7f7f7f } "thinkeramik" { set labelBg #b3b3b3; set pressedBg #959595 } } } "#426794 #426794" { ;# color scheme "Dark Blue" switch -- $style { "light, 3rd revision" { set pressedBg #4871a2 } "platinum" { set pressedBg #37567b } "baghira" { set labelBg #8aafdc; set pressedBg #82a3cc } "highcolor" { set labelBg #436895; set pressedBg #426794 } "keramik" { set labelBg #7994b4; set pressedBg #5b7799 } "phase" { set labelBg #426795; set pressedBg #37567b } "plastik" { set labelBg #406592; set pressedBg #36547a } "qtcurve" { set labelBg #416692; set pressedBg #3c5676 } "thinkeramik" { set labelBg #7991af; set pressedBg #546f91 } } } "#d6cdbb #d6cdbb" { ;# color scheme "Desert Red" switch -- $style { "light, 3rd revision" { set pressedBg #ebe1ce } "platinum" { set pressedBg #b2ab9c } "baghira" { set labelBg #f7f4ec; set pressedBg #edeae0 } "highcolor" { set labelBg #d9d0be; set pressedBg #d6cdbb } "keramik" { set labelBg #e3dcd0; set pressedBg #cbc5b7 } "phase" { set labelBg #d6cdbb; set pressedBg #b2ab9c } "plastik" { set labelBg #d3cbb8; set pressedBg #bab3a3 } "qtcurve" { set labelBg #d4cbb8; set pressedBg #b8ac94 } "thinkeramik" { set labelBg #dbd5ca; set pressedBg #c2bbae } } } "#4b7b82 #4b7b82" { ;# color scheme "Digital CDE" switch -- $style { "light, 3rd revision" { set pressedBg #52878f } "platinum" { set pressedBg #3e666c } "baghira" { set labelBg #97c3c9; set pressedBg #8eb6bc } "highcolor" { set labelBg #4b7d84; set pressedBg #4b7b82 } "keramik" { set labelBg #80a2a7; set pressedBg #62868c } "phase" { set labelBg #4b7b82; set pressedBg #3e666c } "plastik" { set labelBg #49787f; set pressedBg #3d666c } "qtcurve" { set labelBg #4a7980; set pressedBg #416468 } "thinkeramik" { set labelBg #7f97a3; set pressedBg #5a7e83 } } } "#e6dedc #e4e4e4" { ;# color scheme "EveX" switch -- $style { "light, 3rd revision" { set pressedBg #fdf4f2 } "platinum" { set pressedBg #bfb8b7 } "baghira" { set labelBg #f6f5f5; set pressedBg #ededed } "highcolor" { set labelBg #e7e7e7; set pressedBg #e4e4e4 } "keramik" { set labelBg #ededed; set pressedBg #d6d6d6 } "phase" { set labelBg #e7e0dd; set pressedBg #bfb8b7 } "plastik" { set labelBg #e2e2e2; set pressedBg #c0bfbf } "qtcurve" { set labelBg #e4dcd9; set pressedBg #c5b7b4 } "thinkeramik" { set labelBg #e6e1df; set pressedBg #c7c9c7 } } } "#ffffff #ffffff" { ;# color scheme "High Contrast Black Text" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #d4d4d4 } "baghira" { set labelBg #f5f5f5; set pressedBg #f2f2f2 } "highcolor" { set labelBg #f5f5f5; set pressedBg #ffffff } "keramik" { set labelBg #fbfbfb; set pressedBg #e8e8e8 } "phase" { set labelBg #f7f7f7; set pressedBg #d4d4d4 } "plastik" { set labelBg #f8f8f8; set pressedBg #d8d8d8 } "qtcurve" { set labelBg #f6f6f6; set pressedBg #d6d6d6 } "thinkeramik" { set labelBg #f4f4f4; set pressedBg #e2e2e2 } } } "#0000ff #0000ff" { ;# color scheme "High Contrast Yellow on Blue" switch -- $style { "light, 3rd revision" { set pressedBg #1919ff } "platinum" { set pressedBg #0000d4 } "baghira" { set labelBg #4848ff; set pressedBg #4646ff } "highcolor" { set labelBg #0e0ef5; set pressedBg #0000ff } "keramik" { set labelBg #4949fb; set pressedBg #2929e8 } "phase" { set labelBg #0909f7; set pressedBg #0000d4 } "plastik" { set labelBg #0505f8; set pressedBg #0000d8 } "qtcurve" { set labelBg #0909f2; set pressedBg #0f0fc5 } "thinkeramik" { set labelBg #5151f4; set pressedBg #2222e2 } } } "#000000 #000000" { ;# color scheme "High Contrast White Text" switch -- $style { "light, 3rd revision" { set pressedBg #000000 } "platinum" { set pressedBg #000000 } "baghira" { set labelBg #818181; set pressedBg #7f7f7f } "highcolor" { set labelBg #000000; set pressedBg #000000 } "keramik" { set labelBg #494949; set pressedBg #292929 } "phase" { set labelBg #000000; set pressedBg #000000 } "plastik" { set labelBg #000000; set pressedBg #000000 } "qtcurve" { set labelBg #000000; set pressedBg #000000 } "thinkeramik" { set labelBg #4d4d4d; set pressedBg #222222 } } } "#f6f6ff #e4eeff" { ;# color scheme "Ice (FreddyK)" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #cdcdd4 } "baghira" { set labelBg #f6f6f6; set pressedBg #f2f4f6 } "highcolor" { set labelBg #e8edf5; set pressedBg #e4eeff } "keramik" { set labelBg #edf3fb; set pressedBg #d6dde8 } "phase" { set labelBg #f3f3f7; set pressedBg #cdcdd4 } "plastik" { set labelBg #e3eaf8; set pressedBg #c0c9d8 } "qtcurve" { set labelBg #ebebfc; set pressedBg #b3b3f0 } "thinkeramik" { set labelBg #f1f1f4; set pressedBg #dbdbe2 } } } "#c0c0c0 #c0c0c0" { ;# color schemes "KDE 1" and "Storm" switch -- $style { "light, 3rd revision" { set pressedBg #d3d3d3 } "platinum" { set pressedBg #a0a0a0 } "baghira" { set labelBg #e9e9e9; set pressedBg #dedede } "highcolor" { set labelBg #c2c2c2; set pressedBg #c0c0c0 } "keramik" { set labelBg #d3d3d3; set pressedBg #bababa } "phase" { set labelBg #c1c1c1; set pressedBg #a0a0a0 } "plastik" { set labelBg #bebebe; set pressedBg #a2a2a2 } "qtcurve" { set labelBg #bebebe; set pressedBg #a0a0a0 } "thinkeramik" { set labelBg #cccccc; set pressedBg #b2b2b2 } } } "#dcdcdc #e4e4e4" { ;# color scheme "KDE 2" switch -- $style { "light, 3rd revision" { set pressedBg #d3d3d3 } "platinum" { set pressedBg #b7b7b7 } "baghira" { set labelBg #f3f3f3; set pressedBg #ededed } "highcolor" { set labelBg #e7e7e7; set pressedBg #e4e4e4 } "keramik" { set labelBg #ededed; set pressedBg #d6d6d6 } "phase" { set labelBg #dddddd; set pressedBg #b7b7b7 } "plastik" { set labelBg #e2e2e2; set pressedBg #c0c0c0 } "qtcurve" { set labelBg #d9d9d9; set pressedBg #b8b8b8 } "thinkeramik" { set labelBg #dfdfdf; set pressedBg #c7c7c7 } } } "#eae9e8 #e6f0f9" { ;# color scheme "Keramik" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #c3c2c1 } "baghira" { set labelBg #f4f4f4; set pressedBg #f1f3f5 } "highcolor" { set labelBg #eaeef2; set pressedBg #e6f0f9 } "keramik" { set labelBg #eef4f8; set pressedBg #d7dfe5 } "phase" { set labelBg #ebeae9; set pressedBg #c3c2c1 } "plastik" { set labelBg #e3ecf3; set pressedBg #c0c9d2 } "qtcurve" { set labelBg #e8e6e6; set pressedBg #c5c3c1 } "thinkeramik" { set labelBg #e8e8e7; set pressedBg #d2d1d0 } } } "#eeeee6 #eeeade" { ;# color scheme "Keramik Emerald" switch -- $style { "light, 3rd revision" { set pressedBg #fffffc } "platinum" { set pressedBg #c6c6bf } "baghira" { set labelBg #f6f6f6; set pressedBg #f3f2ee } "highcolor" { set labelBg #eeeae1; set pressedBg #eeeade } "keramik" { set labelBg #f3f1e8; set pressedBg #dddad1 } "phase" { set labelBg #efefef; set pressedBg #c6c6bf } "plastik" { set labelBg #ebe7dc; set pressedBg #c9c6bc } "qtcurve" { set labelBg #ecece3; set pressedBg #cdcdbb } "thinkeramik" { set labelBg #ebebe5; set pressedBg #d5d5cf } } } "#e9e9e9 #f6f6f6" { ;# color scheme "Keramik White" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #c2c2c2 } "baghira" { set labelBg #f4f4f4; set pressedBg #f1f1f1 } "highcolor" { set labelBg #f1f1f1; set pressedBg #f6f6f6 } "keramik" { set labelBg #f7f7f7; set pressedBg #e3e3e3 } "phase" { set labelBg #eaeaea; set pressedBg #c2c2c2 } "plastik" { set labelBg #f1f1f1; set pressedBg #cfcfcf } "qtcurve" { set labelBg #e6e6e6; set pressedBg #c3c3c3 } "thinkeramik" { set labelBg #e8e8e8; set pressedBg #d1d1d1 } } } "#ebe9e9 #f6f4f4" { ;# color scheme "Lipstik Noble" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #c3c1c1 } "baghira" { set labelBg #f4f4f4; set pressedBg #f1f1f1 } "highcolor" { set labelBg #f1f0f0; set pressedBg #f6f4f4 } "keramik" { set labelBg #f7f6f6; set pressedBg #e3e1e1 } "phase" { set labelBg #f5f4f4; set pressedBg #c3c1c1 } "plastik" { set labelBg #f2f2f2; set pressedBg #d3d2d2 } "qtcurve" { set labelBg #e9e6e6; set pressedBg #c5c1c1 } "thinkeramik" { set labelBg #e9e8e8; set pressedBg #d3d1d1 } } } "#eeeee6 #eeeade" { ;# color scheme "Lipstik Standard" switch -- $style { "light, 3rd revision" { set pressedBg #fffffc } "platinum" { set pressedBg #c6c6bf } "baghira" { set labelBg #f6f6f6; set pressedBg #f3f2ee } "highcolor" { set labelBg #eeeae1; set pressedBg #eeeade } "keramik" { set labelBg #f3f1e8; set pressedBg #dddad1 } "phase" { set labelBg #eeeade; set pressedBg #c6c6bf } "plastik" { set labelBg #ebe7dc; set pressedBg #ccc9c0 } "qtcurve" { set labelBg #ecece3; set pressedBg #ccccba } "thinkeramik" { set labelBg #ebebe5; set pressedBg #d5d5cf } } } "#eeeff2 #f7faff" { ;# color scheme "Lipstik White" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #c6c7c9 } "baghira" { set labelBg #f5f5f5; set pressedBg #f2f2f3 } "highcolor" { set labelBg #f1f2f5; set pressedBg #f1faff } "keramik" { set labelBg #f8f9fb; set pressedBg #e3e5e8 } "phase" { set labelBg #f4f5f7; set pressedBg #c6c7c9 } "plastik" { set labelBg #f3f4f7; set pressedBg #d0d3d8 } "qtcurve" { set labelBg #ebecf0; set pressedBg #c4c7ce } "thinkeramik" { set labelBg #ebecee; set pressedBg #d5d6d8 } } } "#f4ddb2 #f4ddb2" { ;# color scheme "Media Peach" switch -- $style { "light, 3rd revision" { set pressedBg #ffebc7 } "platinum" { set pressedBg #cbb894 } "baghira" { set labelBg #fcfced; set pressedBg #faf6df } "highcolor" { set labelBg #f0dbb6; set pressedBg #f4ddb2 } "keramik" { set labelBg #f6e8c9; set pressedBg #e1d0b0 } "phase" { set labelBg #f4ddb2; set pressedBg #cbb894 } "plastik" { set labelBg #ffdbaf; set pressedBg #d5c19c } "qtcurve" { set labelBg #f2dbaf; set pressedBg #e0bd7f } "thinkeramik" { set labelBg #efe0c3; set pressedBg #d9c8a7 } } } "#a8a8a8 #a8a8a8" { ;# color scheme "Next" switch -- $style { "light, 3rd revision" { set pressedBg #b8b8b8 } "platinum" { set pressedBg #8c8c8c } "baghira" { set labelBg #dedede; set pressedBg #d3d3d3 } "highcolor" { set labelBg #aaaaaa; set pressedBg #a8a8a8 } "keramik" { set labelBg #c2c2c2; set pressedBg #a8a8a8 } "phase" { set labelBg #a9a9a9; set pressedBg #8c8c8c } "plastik" { set labelBg #a5a5a5; set pressedBg #898989 } "qtcurve" { set labelBg #a6a6a6; set pressedBg #8d8d8d } "thinkeramik" { set labelBg #bdbdbd; set pressedBg #a0a0a0 } } } "#d6d6d6 #d6d6d6" { ;# color scheme "Pale Gray" switch -- $style { "light, 3rd revision" { set pressedBg #ebebeb } "platinum" { set pressedBg #b2b2b2 } "baghira" { set labelBg #f2f2f2; set pressedBg #e8e8e8 } "highcolor" { set labelBg #d9d9d9; set pressedBg #d6d6d6 } "keramik" { set labelBg #e3e3e3; set pressedBg #cbcbcb } "phase" { set labelBg #d6d6d6; set pressedBg #b2b2b2 } "plastik" { set labelBg #d3d3d3; set pressedBg #bababa } "qtcurve" { set labelBg #d4d4d4; set pressedBg #b1b1b1 } "thinkeramik" { set labelBg #dbdbdb; set pressedBg #c2c2c2 } } } "#efefef #dddfe4" { ;# color scheme "Plastik" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #c7c7c7 } "baghira" { set labelBg #f5f5f5; set pressedBg #ececee } "highcolor" { set labelBg #e0e1e7; set pressedBg #dddfe4 } "keramik" { set labelBg #e8e9ed; set pressedBg #d0d2d6 } "phase" { set labelBg #dee0e5; set pressedBg #c7c7c7 } "plastik" { set labelBg #dbdde2; set pressedBg #babcc0 } "qtcurve" { set labelBg #ececec; set pressedBg #c9c9c9 } "thinkeramik" { set labelBg #ececec; set pressedBg #d6d6d6 } } } "#d3c5be #aba09a" { ;# color scheme "Point Reyes Green" switch -- $style { "light, 3rd revision" { set pressedBg #e8d9d1 } "platinum" { set pressedBg #afa49e } "baghira" { set labelBg #f5efed; set pressedBg #d7d0cd } "highcolor" { set labelBg #ada29d; set pressedBg #aba09a } "keramik" { set labelBg #c4bcb8; set pressedBg #aba29e } "phase" { set labelBg #d3c5be; set pressedBg #afa49e } "plastik" { set labelBg #ab9f99; set pressedBg #9b908a } "qtcurve" { set labelBg #d1c3bc; set pressedBg #b3a197 } "thinkeramik" { set labelBg #d9d0cc; set pressedBg #c0b6b1 } } } "#eed8ae #eed8ae" { ;# color scheme "Pumpkin" switch -- $style { "light, 3rd revision" { set pressedBg #ffe0c0 } "platinum" { set pressedBg #c6b390 } "baghira" { set labelBg #fcfbea; set pressedBg #f9f4dd } "highcolor" { set labelBg #eed8b1; set pressedBg #eed8ae } "keramik" { set labelBg #f3e4c6; set pressedBg #ddcdad } "phase" { set labelBg #eed8ae; set pressedBg #c6b390 } "plastik" { set labelBg #ebd5ac; set pressedBg #cfbc96 } "qtcurve" { set labelBg #ebd6ab; set pressedBg #d7b980 } "thinkeramik" { set labelBg #ebdcc0; set pressedBg #d5c4a4 } } } "#d4d0c8 #d4d0c8" { ;# color scheme "Redmond 2000" switch -- $style { "light, 3rd revision" { set pressedBg #e9e5dc } "platinum" { set pressedBg #b0ada6 } "baghira" { set labelBg #f3f2ef; set pressedBg #eae8e4 } "highcolor" { set labelBg #d7d3cb; set pressedBg #d4d0c8 } "keramik" { set labelBg #e1ded9; set pressedBg #cac7c1 } "phase" { set labelBg #d5d1c9; set pressedBg #b0ada6 } "plastik" { set labelBg #d2cdc5; set pressedBg #b2afa7 } "qtcurve" { set labelBg #d2cdc6; set pressedBg #b4afa4 } "thinkeramik" { set labelBg #dad7d2; set pressedBg #c1beb8 } } } "#c3c3c3 #c3c3c3" { ;# color scheme "Redmond 95" switch -- $style { "light, 3rd revision" { set pressedBg #d6d6d6 } "platinum" { set pressedBg #a2a2a2 } "baghira" { set labelBg #eaeaea; set pressedBg #dfdfdf } "highcolor" { set labelBg #c5c5c5; set pressedBg #c3c3c3 } "keramik" { set labelBg #d5d5d5; set pressedBg #bdbdbd } "phase" { set labelBg #c4c4c4; set pressedBg #a2a2a2 } "plastik" { set labelBg #c1c1c1; set pressedBg #a3a3a3 } "qtcurve" { set labelBg #c1c1c1; set pressedBg #a3a3a3 } "thinkeramik" { set labelBg #cecece; set pressedBg #b5b5b5 } } } "#eeeee6 #eeeade" { ;# color scheme "Redmond XP" switch -- $style { "light, 3rd revision" { set pressedBg #fffffc } "platinum" { set pressedBg #c6c6bf } "baghira" { set labelBg #f6f6f6; set pressedBg #f3f2ee } "highcolor" { set labelBg #eeeae1; set pressedBg #eeeade } "keramik" { set labelBg #f3f1e8; set pressedBg #dddad1 } "phase" { set labelBg #efefe7; set pressedBg #c6c6bf } "plastik" { set labelBg #ebe7dc; set pressedBg #c9c6bc } "qtcurve" { set labelBg #ecece3; set pressedBg #cdcdbb } "thinkeramik" { set labelBg #ebebe5; set pressedBg #d5d5cf } } } "#aeb2c3 #aeb2c3" { ;# color scheme "Solaris" switch -- $style { "light, 3rd revision" { set pressedBg #bfc3d6 } "platinum" { set pressedBg #9194a2 } "baghira" { set labelBg #e4e7ef; set pressedBg #d9dbe4 } "highcolor" { set labelBg #b0b4c5; set pressedBg #aeb2c3 } "keramik" { set labelBg #c6c9d5; set pressedBg #adb0bd } "phase" { set labelBg #aeb2c3; set pressedBg #9194a2 } "plastik" { set labelBg #abafc0; set pressedBg #969aa9 } "qtcurve" { set labelBg #acb0c1; set pressedBg #8d91a5 } "thinkeramik" { set labelBg #c0c3ce; set pressedBg #a5a7b5 } } } "#eeeaee #e6f0f9" { ;# color scheme "SuSE" old switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #c6c3c6 } "baghira" { set labelBg #f5f5f5; set pressedBg #f1f3f5 } "highcolor" { set labelBg #eaeef2; set pressedBg #e6f0f9 } "keramik" { set labelBg #eef4f8; set pressedBg #d7dfe5 } "phase" { set labelBg #efecef; set pressedBg #c6c3c6 } "plastik" { set labelBg #e3ecf3; set pressedBg #c0c9d2 } "qtcurve" { set labelBg #ebe7eb; set pressedBg #cac1ca } "thinkeramik" { set labelBg #ebe8eb; set pressedBg #d5d2d5 } } } "#eeeeee #f4f4f4" { ;# color scheme "SuSE" new switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #c6c6c6 } "baghira" { set labelBg #f5f5f5; set pressedBg #f1f1f1 } "highcolor" { set labelBg #f0f0f0; set pressedBg #f4f4f4 } "keramik" { set labelBg #f6f6f6; set pressedBg #e1e1e1 } "phase" { set labelBg #efefef; set pressedBg #c6c6c6 } "plastik" { set labelBg #f0f0f0; set pressedBg #cdcdcd } "qtcurve" { set labelBg #ebebeb; set pressedBg #c7c7c7 } "thinkeramik" { set labelBg #ebebeb; set pressedBg #d5d5d5 } } } "#eaeaea #eaeaea" { ;# color scheme "SUSE-kdm" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #c3c3c3 } "baghira" { set labelBg #f4f4f4; set pressedBg #efefef } "highcolor" { set labelBg #ececec; set pressedBg #eaeaea } "keramik" { set labelBg #f1f1f1; set pressedBg #dadada } "phase" { set labelBg #ebebeb; set pressedBg #c3c3c3 } "plastik" { set labelBg #e7e7e7; set pressedBg #c6c6c6 } "qtcurve" { set labelBg #e7e7e7; set pressedBg #c4c4c4 } "thinkeramik" { set labelBg #e8e8e8; set pressedBg #d2d2d2 } } } "#d3d3d3 #d3d3d3" { ;# color scheme "System" switch -- $style { "light, 3rd revision" { set pressedBg #e8e8e8 } "platinum" { set pressedBg #afafaf } "baghira" { set labelBg #f0f0f0; set pressedBg #e6e6e6 } "highcolor" { set labelBg #d6d6d6; set pressedBg #d3d3d3 } "keramik" { set labelBg #e1e1e1; set pressedBg #c9c9c9 } "phase" { set labelBg #d2d2d2; set pressedBg #afafaf } "plastik" { set labelBg #d0d0d0; set pressedBg #b9b9b9 } "qtcurve" { set labelBg #d1d1d1; set pressedBg #aeaeae } "thinkeramik" { set labelBg #d9d9d9; set pressedBg #c0c0c0 } } } "#e6e6de #f0f0ef" { ;# color scheme "Thin Keramik" old switch -- $style { "light, 3rd revision" { set pressedBg #fdfdf4 } "platinum" { set pressedBg #bfbfb8 } "baghira" { set labelBg #f6f6f5; set pressedBg #f0f0f0 } "highcolor" { set labelBg #eeeeee; set pressedBg #f0f0ef } "keramik" { set labelBg #f4f4f4; set pressedBg #dfdfde } "phase" { set labelBg #e7e7df; set pressedBg #bfbfb8 } "plastik" { set labelBg #ededeb; set pressedBg #cbcbc9 } "qtcurve" { set labelBg #e3e3db; set pressedBg #c4c4b6 } "thinkeramik" { set labelBg #e6e6e1; set pressedBg #cfcfc9 } } } "#edede1 #f6f6e9" { ;# color scheme "Thin Keramik" new switch -- $style { "light, 3rd revision" { set pressedBg #fffff7 } "platinum" { set pressedBg #c5c5bb } "baghira" { set labelBg #f6f6f5; set pressedBg #f3f3f1 } "highcolor" { set labelBg #f1f1ec; set pressedBg #f6f6e9 } "keramik" { set labelBg #f7f7f0; set pressedBg #e3e3da } "phase" { set labelBg #edede1; set pressedBg #c5c5bb } "plastik" { set labelBg #f4f4e6; set pressedBg #ddddd0 } "qtcurve" { set labelBg #ebebde; set pressedBg #cbcbb3 } "thinkeramik" { set labelBg #eaeae3; set pressedBg #d4d4cb } } } "#f6f5e8 #eeeade" { ;# color scheme "Thin Keramik II" switch -- $style { "light, 3rd revision" { set pressedBg #ffffff } "platinum" { set pressedBg #cdccc1 } "baghira" { set labelBg #f7f7f7; set pressedBg #f3f2ee } "highcolor" { set labelBg #eeeae1; set pressedBg #eeeade } "keramik" { set labelBg #f3f1e8; set pressedBg #dddad1 } "phase" { set labelBg #f3f2e9; set pressedBg #cdccc1 } "plastik" { set labelBg #ebe7dc; set pressedBg #c9c6bc } "qtcurve" { set labelBg #f4f2e5; set pressedBg #dbd8b6 } "thinkeramik" { set labelBg #f1f1e8; set pressedBg #dbdad0 } } } } # # For some Qt styles the label colors are independent of the color scheme: # switch -- $style { "acqua" { set labelBg #e7e7e7; set labelFg #000000; set pressedBg #8fbeec } "kde_xp" { set labelBg #ebeadb; set labelFg #000000; set pressedBg #faf8f3 } "lipstik" { set labelBg $bg; set pressedBg $labelBg } "marble" { set labelBg #cccccc; set labelFg $fg; set pressedBg $labelBg } "riscos" { set labelBg #dddddd; set labelFg #000000; set pressedBg $labelBg } "system" - "systemalt" { set labelBg #cbcbcb; set labelFg #000000; set pressedBg $labelBg } } # # The stripe background color is specified # by a global KDE configuration option: # if {[set val [getKdeConfigVal "General" "alternateBackground"]] eq ""} { set stripeBg "" } elseif {[string range $val 0 0] eq "#"} { set stripeBg $val } elseif {[scan $val "%d,%d,%d" r g b] == 3} { set stripeBg [format "#%02x%02x%02x" $r $g $b] } else { set stripeBg "" } # # The arrow color and style depend mainly on the current Qt style: # switch -- $style { "highcontrast" - "light, 2nd revision" - "light, 3rd revision" - "lipstik" - "phase" - "plastik" { set arrowColor $labelFg; set arrowStyle flat7x4 } "baghira" { set arrowColor $labelFg; set arrowStyle flat7x7 } "qtcurve" { set arrowColor $labelFg; set arrowStyle flat7x5 } "keramik" - "thinkeramik" { set arrowColor $labelFg; set arrowStyle flat8x5 } default { set arrowColor ""; set arrowStyle sunken12x11 } } variable themeDefaults array set themeDefaults [list \ -background $tableBg \ -foreground $tableFg \ -disabledforeground $tableDisFg \ -stripebackground $stripeBg \ -selectbackground $selectBg \ -selectforeground $selectFg \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground $labelBg \ -labeldisabledBg $labelBg \ -labelactiveBg $labelBg \ -labelpressedBg $pressedBg \ -labelforeground $labelFg \ -labeldisabledFg $labelDisFg \ -labelactiveFg $labelFg \ -labelpressedFg $labelFg \ -labelfont TkDefaultFont \ -labelborderwidth 4 \ -labelpady 0 \ -arrowcolor $arrowColor \ -arrowstyle $arrowStyle \ ] } #------------------------------------------------------------------------------ # tablelist::winnativeTheme #------------------------------------------------------------------------------ proc tablelist::winnativeTheme {} { variable themeDefaults array set themeDefaults [list \ -background SystemWindow \ -foreground SystemWindowText \ -disabledforeground SystemDisabledText \ -stripebackground "" \ -selectbackground SystemHighlight \ -selectforeground SystemHighlightText \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground SystemButtonFace \ -labeldisabledBg SystemButtonFace \ -labelactiveBg SystemButtonFace \ -labelpressedBg SystemButtonFace \ -labelforeground SystemButtonText \ -labeldisabledFg SystemDisabledText \ -labelactiveFg SystemButtonText \ -labelpressedFg SystemButtonText \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 0 \ -arrowcolor "" \ -arrowstyle sunken8x7 \ ] } #------------------------------------------------------------------------------ # tablelist::winxpblueTheme #------------------------------------------------------------------------------ proc tablelist::winxpblueTheme {} { variable themeDefaults array set themeDefaults [list \ -background white \ -foreground black \ -disabledforeground #565248 \ -stripebackground "" \ -selectbackground #4a6984 \ -selectforeground #ffffff \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground #ece9d8 \ -labeldisabledBg #e3e1dd \ -labelactiveBg #c1d2ee \ -labelpressedBg #bab5ab \ -labelforeground black \ -labeldisabledFg #565248 \ -labelactiveFg black \ -labelpressedFg black \ -labelfont TkDefaultFont \ -labelborderwidth 2 \ -labelpady 1 \ -arrowcolor #aca899 \ -arrowstyle flat9x5 \ ] } #------------------------------------------------------------------------------ # tablelist::xpnativeTheme #------------------------------------------------------------------------------ proc tablelist::xpnativeTheme {} { variable xpStyle switch [winfo rgb . SystemButtonFace] { "60652 59881 55512" { set xpStyle 1 set labelBg #ebeadb set activeBg #faf8f3 set pressedBg #dedfd8 set labelBd 4 set labelPadY 4 set arrowColor #aca899 set arrowStyle flat9x5 if {[info exists tile::version] && [string compare $tile::version 0.7] < 0} { set labelBd 0 } } "57568 57311 58339" { set xpStyle 1 set labelBg #f9fafd set activeBg #fefefe set pressedBg #ececf3 set labelBd 4 set labelPadY 4 set arrowColor #aca899 set arrowStyle flat9x5 if {[info exists tile::version] && [string compare $tile::version 0.7] < 0} { set labelBd 0 } } default { set xpStyle 0 set labelBg SystemButtonFace set activeBg SystemButtonFace set pressedBg SystemButtonFace set labelBd 2 set labelPadY 0 set arrowColor SystemButtonShadow set arrowStyle flat7x4 } } variable themeDefaults array set themeDefaults [list \ -background SystemWindow \ -foreground SystemWindowText \ -disabledforeground SystemDisabledText \ -stripebackground "" \ -selectbackground SystemHighlight \ -selectforeground SystemHighlightText \ -selectborderwidth 0 \ -font TkTextFont \ -labelbackground $labelBg \ -labeldisabledBg $labelBg \ -labelactiveBg $activeBg \ -labelpressedBg $pressedBg \ -labelforeground SystemButtonText \ -labeldisabledFg SystemDisabledText \ -labelactiveFg SystemButtonText \ -labelpressedFg SystemButtonText \ -labelfont TkDefaultFont \ -labelborderwidth $labelBd \ -labelpady $labelPadY \ -arrowcolor $arrowColor \ -arrowstyle $arrowStyle \ ] } # # Private procedures performing RGB <-> HSV conversions # ===================================================== # #------------------------------------------------------------------------------ # tablelist::rgb2hsv # # Converts the specified RGB value to HSV. The arguments are assumed to be # integers in the interval [0, 65535]. The return value is a list of the form # {h s v}, where h in [0.0, 360.0) and s, v in [0.0, 1.0]. #------------------------------------------------------------------------------ proc tablelist::rgb2hsv {r g b} { set r [expr {$r/65535.0}] set g [expr {$g/65535.0}] set b [expr {$b/65535.0}] # # Compute the value component # set sortedLst [lsort -real [list $r $g $b]] set v [lindex $sortedLst end] set dist [expr {$v - [lindex $sortedLst 0]}] # # Compute the saturation component # if {$v == 0.0} { set s 0.0 } else { set s [expr {$dist/$v}] } # # Compute the hue component # if {$s == 0.0} { set h 0.0 } else { set rc [expr {($v - $r)/$dist}] set gc [expr {($v - $g)/$dist}] set bc [expr {($v - $b)/$dist}] if {$v == $r} { set h [expr {$bc - $gc}] } elseif {$v == $g} { set h [expr {2 + $rc - $bc}] } else { set h [expr {4 + $gc - $rc}] } set h [expr {$h*60}] if {$h < 0.0} { set h [expr {$h + 360.0}] } elseif {$h >= 360.0} { set h 0.0 } } return [list $h $s $v] } #------------------------------------------------------------------------------ # tablelist::hsv2rgb # # Converts the specified HSV value to RGB. The arguments are assumed to fulfil # the conditions: h in [0.0, 360.0) and s, v in [0.0, 1.0]. The return value # is a list of the form {r g b}, where r, g, and b are integers in the interval # [0, 65535]. #------------------------------------------------------------------------------ proc tablelist::hsv2rgb {h s v} { set h [expr {$h/60.0}] set f [expr {$h - floor($h)}] set p1 [expr {round(65535.0*$v*(1 - $s))}] set p2 [expr {round(65535.0*$v*(1 - $s*$f))}] set p3 [expr {round(65535.0*$v*(1 - $s*(1 - $f)))}] set v [expr {round(65535.0*$v)}] switch [expr {int($h)}] { 0 { return [list $v $p3 $p1] } 1 { return [list $p2 $v $p1] } 2 { return [list $p1 $v $p3] } 3 { return [list $p1 $p2 $v ] } 4 { return [list $p3 $p1 $v ] } 5 { return [list $v $p1 $p2] } } } # # Private procedures related to global KDE configuration options # ============================================================== # #------------------------------------------------------------------------------ # tablelist::getKdeConfigVal # # Returns the value of the global KDE configuration option identified by the # given group (section) and key. #------------------------------------------------------------------------------ proc tablelist::getKdeConfigVal {group key} { variable kdeDirList if {![info exists kdeDirList]} { makeKdeDirList } # # Search for the entry corresponding to the given group and key in # the file "share/config/kdeglobals" within the KDE directories # foreach dir $kdeDirList { set fileName [file join $dir "share/config/kdeglobals"] if {[set val [readKdeConfigVal $fileName $group $key]] ne ""} { return $val } } return "" } #------------------------------------------------------------------------------ # tablelist::makeKdeDirList # # Builds the list of the directories to be considered when searching for global # KDE configuration options. #------------------------------------------------------------------------------ proc tablelist::makeKdeDirList {} { variable kdeDirList {} if {[info exists ::env(USER)] && $::env(USER) eq "root"} { set name "KDEROOTHOME" } else { set name "KDEHOME" } if {[info exists ::env($name)] && $::env($name) ne ""} { set localKdeDir [file normalize $::env($name)] } elseif {[info exists ::env(HOME)] && $::env(HOME) ne ""} { set localKdeDir [file normalize [file join $::env(HOME) ".kde"]] } if {[info exists localKdeDir] && $localKdeDir ne "-"} { lappend kdeDirList $localKdeDir } if {[info exists ::env(KDEDIRS)] && $::env(KDEDIRS) ne ""} { foreach dir [split $::env(KDEDIRS) ":"] { if {$dir ne ""} { lappend kdeDirList $dir } } } elseif {[info exists ::env(KDEDIR)] && $::env(KDEDIR) ne ""} { lappend kdeDirList $::env(KDEDIR) } set prefix [exec kde-config --prefix] lappend kdeDirList $prefix set execPrefix [exec kde-config --expandvars --exec-prefix] if {$execPrefix ne $prefix} { lappend kdeDirList $execPrefix } } #------------------------------------------------------------------------------ # tablelist::readKdeConfigVal # # Reads the value of the global KDE configuration option identified by the # given group (section) and key from the specified file. Note that the # procedure performs a case-sensitive search and only works as expected for # "simple" group and key names. #------------------------------------------------------------------------------ proc tablelist::readKdeConfigVal {fileName group key} { if {[catch {open $fileName r} chan] != 0} { return "" } # # Search for the specified group # set groupFound 0 while {[gets $chan line] >= 0} { set line [string trim $line] if {$line eq "\[$group\]"} { set groupFound 1 break } } if {!$groupFound} { close $chan return "" } # # Search for the specified key within the group # set pattern "^$key\\s*=\\s*(.+)$" set keyFound 0 while {[gets $chan line] >= 0} { set line [string trim $line] if {[string range $line 0 0] eq "\["} { break } if {[regexp $pattern $line dummy val]} { set keyFound 1 break } } close $chan return [expr {$keyFound ? $val : ""}] } kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelist.tcl0000644000175000017500000000100211070725164023442 0ustar domibeldomibel#============================================================================== # Main Tablelist package module. # # Copyright (c) 2000-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== package require Tcl 8 package require Tk 8 package require -exact tablelist::common 4.10 package provide Tablelist $::tablelist::version package provide tablelist $::tablelist::version ::tablelist::useTile 0 # ::tablelist::createBindings kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/mwutil.tcl0000644000175000017500000003545611070725164023024 0ustar domibeldomibel#============================================================================== # Contains utility procedures for mega-widgets. # # Structure of the module: # - Namespace initialization # - Public utility procedures # # Copyright (c) 2000-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== package require Tcl 8 package require Tk 8 # # Namespace initialization # ======================== # namespace eval ::mwutil { # # Public variables: # variable version 2.5 variable library [file dirname [info script]] # # Public procedures: # namespace export wrongNumArgs getAncestorByClass convEventFields \ defineKeyNav processTraversal focusNext focusPrev \ configureWidget fullConfigOpt fullOpt enumOpts \ configureSubCmd attribSubCmd hasattribSubCmd \ unsetattribSubCmd getScrollInfo # # Make modified versions of the procedures tk_focusNext and # tk_focusPrev, to be invoked in the processTraversal command # proc makeFocusProcs {} { # # Enforce the evaluation of the Tk library file "focus.tcl" # tk_focusNext . # # Build the procedures focusNext and focusPrev # foreach direction {Next Prev} { set procBody [info body tk_focus$direction] regsub -all {winfo children} $procBody {getChildren $class} procBody proc focus$direction {w class} $procBody } } makeFocusProcs # # Invoked in the procedures focusNext and focusPrev defined above: # proc getChildren {class w} { if {[string compare [winfo class $w] $class] == 0} { return {} } else { return [winfo children $w] } } } # # Public utility procedures # ========================= # #------------------------------------------------------------------------------ # mwutil::wrongNumArgs # # Generates a "wrong # args" error message. #------------------------------------------------------------------------------ proc mwutil::wrongNumArgs args { set optList {} foreach arg $args { lappend optList \"$arg\" } return -code error "wrong # args: should be [enumOpts $optList]" } #------------------------------------------------------------------------------ # mwutil::getAncestorByClass # # Gets the path name of the widget of the specified class from the path name w # of one of its descendants. It is assumed that all of the ancestors of w # exist (but w itself needn't exist). #------------------------------------------------------------------------------ proc mwutil::getAncestorByClass {w class} { regexp {^(.+)\..+$} $w dummy win while {[string compare [winfo class $win] $class] != 0} { set win [winfo parent $win] } return $win } #------------------------------------------------------------------------------ # mwutil::convEventFields # # Gets the path name of the widget of the specified class and the x and y # coordinates relative to the latter from the path name w of one of its # descendants and from the x and y coordinates relative to the latter. #------------------------------------------------------------------------------ proc mwutil::convEventFields {w x y class} { set win [getAncestorByClass $w $class] set _x [expr {$x + [winfo rootx $w] - [winfo rootx $win]}] set _y [expr {$y + [winfo rooty $w] - [winfo rooty $win]}] return [list $win $_x $_y] } #------------------------------------------------------------------------------ # mwutil::defineKeyNav # # For a given mega-widget class, the procedure defines the binding tag # ${class}KeyNav as a partial replacement for "all", by substituting the # scripts bound to the events , , and <> with new # ones which propagate these events to the mega-widget of the given class # containing the widget to which the event was reported. (The event # was replaced with <> in Tk 8.3.0.) This tag is # designed to be inserted before "all" in the list of binding tags of a # descendant of a mega-widget of the specified class. #------------------------------------------------------------------------------ proc mwutil::defineKeyNav class { foreach event { <>} { bind ${class}KeyNav $event \ [list mwutil::processTraversal %W $class $event] } bind Entry <> { %W selection range 0 end; %W icursor end } bind Spinbox <> { %W selection range 0 end; %W icursor end } } #------------------------------------------------------------------------------ # mwutil::processTraversal # # Processes the given traversal event for the mega-widget of the specified # class containing the widget w if that mega-widget is not the only widget # receiving the focus during keyboard traversal within its top-level widget. #------------------------------------------------------------------------------ proc mwutil::processTraversal {w class event} { set win [getAncestorByClass $w $class] if {[string compare $event ""] == 0} { set target [focusNext $win $class] } else { set target [focusPrev $win $class] } if {[string compare $target $win] != 0} { set focus [focus] if {[string compare $focus ""] != 0} { event generate $focus <> } focus $target event generate $target <> } return -code break "" } #------------------------------------------------------------------------------ # mwutil::configureWidget # # Configures the widget win by processing the command-line arguments specified # in optValPairs and, if the value of initialize is true, also those database # options that don't match any command-line arguments. #------------------------------------------------------------------------------ proc mwutil::configureWidget {win configSpecsName configCmd cgetCmd \ optValPairs initialize} { upvar $configSpecsName configSpecs # # Process the command-line arguments # set cmdLineOpts {} set savedVals {} set failed 0 set count [llength $optValPairs] foreach {opt val} $optValPairs { if {[catch {fullConfigOpt $opt configSpecs} result] != 0} { set failed 1 break } if {$count == 1} { set result "value for \"$opt\" missing" set failed 1 break } set opt $result lappend cmdLineOpts $opt lappend savedVals [eval $cgetCmd [list $win $opt]] if {[catch {eval $configCmd [list $win $opt $val]} result] != 0} { set failed 1 break } incr count -2 } if {$failed} { # # Restore the saved values # foreach opt $cmdLineOpts val $savedVals { eval $configCmd [list $win $opt $val] } return -code error $result } if {$initialize} { # # Process those configuration options that were not # given as command-line arguments; use the corresponding # values from the option database if available # foreach opt [lsort [array names configSpecs]] { if {[llength $configSpecs($opt)] == 1 || [lsearch -exact $cmdLineOpts $opt] >= 0} { continue } set dbName [lindex $configSpecs($opt) 0] set dbClass [lindex $configSpecs($opt) 1] set dbValue [option get $win $dbName $dbClass] if {[string compare $dbValue ""] == 0} { set default [lindex $configSpecs($opt) 3] eval $configCmd [list $win $opt $default] } else { if {[catch { eval $configCmd [list $win $opt $dbValue] } result] != 0} { return -code error $result } } } } return "" } #------------------------------------------------------------------------------ # mwutil::fullConfigOpt # # Returns the full configuration option corresponding to the possibly # abbreviated option opt. #------------------------------------------------------------------------------ proc mwutil::fullConfigOpt {opt configSpecsName} { upvar $configSpecsName configSpecs if {[info exists configSpecs($opt)]} { if {[llength $configSpecs($opt)] == 1} { return $configSpecs($opt) } else { return $opt } } set optList [lsort [array names configSpecs]] set count 0 foreach elem $optList { if {[string first $opt $elem] == 0} { incr count if {$count == 1} { set option $elem } else { break } } } if {$count == 1} { if {[llength $configSpecs($option)] == 1} { return $configSpecs($option) } else { return $option } } elseif {$count == 0} { ### return -code error "unknown option \"$opt\"" return -code error \ "bad option \"$opt\": must be [enumOpts $optList]" } else { ### return -code error "unknown option \"$opt\"" return -code error \ "ambiguous option \"$opt\": must be [enumOpts $optList]" } } #------------------------------------------------------------------------------ # mwutil::fullOpt # # Returns the full option corresponding to the possibly abbreviated option opt. #------------------------------------------------------------------------------ proc mwutil::fullOpt {kind opt optList} { if {[lsearch -exact $optList $opt] >= 0} { return $opt } set count 0 foreach elem $optList { if {[string first $opt $elem] == 0} { incr count if {$count == 1} { set option $elem } else { break } } } if {$count == 1} { return $option } elseif {$count == 0} { return -code error \ "bad $kind \"$opt\": must be [enumOpts $optList]" } else { return -code error \ "ambiguous $kind \"$opt\": must be [enumOpts $optList]" } } #------------------------------------------------------------------------------ # mwutil::enumOpts # # Returns a string consisting of the elements of the given list, separated by # commas and spaces. #------------------------------------------------------------------------------ proc mwutil::enumOpts optList { set optCount [llength $optList] set n 1 foreach opt $optList { if {$n == 1} { set str $opt } elseif {$n < $optCount} { append str ", $opt" } else { if {$optCount > 2} { append str "," } append str " or $opt" } incr n } return $str } #------------------------------------------------------------------------------ # mwutil::configureSubCmd # # This procedure is invoked to process configuration subcommands. #------------------------------------------------------------------------------ proc mwutil::configureSubCmd {win configSpecsName configCmd cgetCmd argList} { upvar $configSpecsName configSpecs set argCount [llength $argList] if {$argCount > 1} { # # Set the specified configuration options to the given values # return [configureWidget $win configSpecs $configCmd $cgetCmd $argList 0] } elseif {$argCount == 1} { # # Return the description of the specified configuration option # set opt [fullConfigOpt [lindex $argList 0] configSpecs] set dbName [lindex $configSpecs($opt) 0] set dbClass [lindex $configSpecs($opt) 1] set default [lindex $configSpecs($opt) 3] return [list $opt $dbName $dbClass $default \ [eval $cgetCmd [list $win $opt]]] } else { # # Return a list describing all available configuration options # foreach opt [lsort [array names configSpecs]] { if {[llength $configSpecs($opt)] == 1} { set alias $configSpecs($opt) if {$::tk_version < 8.1} { set dbName [lindex $configSpecs($alias) 0] lappend result [list $opt $dbName] } else { lappend result [list $opt $alias] } } else { set dbName [lindex $configSpecs($opt) 0] set dbClass [lindex $configSpecs($opt) 1] set default [lindex $configSpecs($opt) 3] lappend result [list $opt $dbName $dbClass $default \ [eval $cgetCmd [list $win $opt]]] } } return $result } } #------------------------------------------------------------------------------ # mwutil::attribSubCmd # # This procedure is invoked to process *attrib subcommands. #------------------------------------------------------------------------------ proc mwutil::attribSubCmd {win prefix argList} { set classNs [string tolower [winfo class $win]] upvar ::${classNs}::ns${win}::attribs attribs set argCount [llength $argList] if {$argCount > 1} { # # Set the specified attributes to the given values # if {$argCount % 2 != 0} { return -code error "value for \"[lindex $argList end]\" missing" } foreach {attr val} $argList { set attribs($prefix-$attr) $val } return "" } elseif {$argCount == 1} { # # Return the value of the specified attribute # set attr [lindex $argList 0] set name $prefix-$attr if {[info exists attribs($name)]} { return $attribs($name) } else { return "" } } else { # # Return the current list of attribute names and values # set len [string length "$prefix-"] set result {} foreach name [lsort [array names attribs "$prefix-*"]] { set attr [string range $name $len end] lappend result [list $attr $attribs($name)] } return $result } } #------------------------------------------------------------------------------ # mwutil::hasattribSubCmd # # This procedure is invoked to process has*attrib subcommands. #------------------------------------------------------------------------------ proc mwutil::hasattribSubCmd {win prefix attr} { set classNs [string tolower [winfo class $win]] upvar ::${classNs}::ns${win}::attribs attribs return [info exists attribs($prefix-$attr)] } #------------------------------------------------------------------------------ # mwutil::unsetattribSubCmd # # This procedure is invoked to process unset*attrib subcommands. #------------------------------------------------------------------------------ proc mwutil::unsetattribSubCmd {win prefix attr} { set classNs [string tolower [winfo class $win]] upvar ::${classNs}::ns${win}::attribs attribs set name $prefix-$attr if {[info exists attribs($name)]} { unset attribs($name) } return "" } #------------------------------------------------------------------------------ # mwutil::getScrollInfo # # Parses a list of arguments of the form "moveto " or "scroll # units|pages" and returns the corresponding list consisting of two or # three properly formatted elements. #------------------------------------------------------------------------------ proc mwutil::getScrollInfo argList { set argCount [llength $argList] set opt [lindex $argList 0] if {[string first $opt "moveto"] == 0} { if {$argCount != 2} { wrongNumArgs "moveto fraction" } set fraction [format "%f" [lindex $argList 1]] return [list moveto $fraction] } elseif {[string first $opt "scroll"] == 0} { if {$argCount != 3} { wrongNumArgs "scroll number units|pages" } set number [format "%d" [lindex $argList 1]] set what [lindex $argList 2] if {[string first $what "units"] == 0} { return [list scroll $number units] } elseif {[string first $what "pages"] == 0} { return [list scroll $number pages] } else { return -code error "bad argument \"$what\": must be units or pages" } } else { return -code error "unknown option \"$opt\": must be moveto or scroll" } } kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/COPYRIGHT.txt0000644000175000017500000000075411070725164023101 0ustar domibeldomibelMulti-column listbox package Tablelist, version 4.10 Copyright (c) 2000-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) This library is free software; you can use, modify, and redistribute it for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/vtkKWTablelistInit.h0000644000175000017500000000265310562077266024707 0ustar domibeldomibel/*========================================================================= Module: $RCSfile: vtkKWTablelistInit.h,v $ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkKWTablelistInit - class used to initialize Tablelist // .SECTION Description // This class is used to initialize the Tablelist library. #ifndef __vtkKWTablelistInit_h #define __vtkKWTablelistInit_h #include "vtkObject.h" #include "vtkKWWidgets.h" // Needed for export symbols directives #include "vtkTcl.h" // Needed for Tcl interpreter class KWWidgets_EXPORT vtkKWTablelistInit : public vtkObject { public: static vtkKWTablelistInit* New(); vtkTypeRevisionMacro(vtkKWTablelistInit,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Load the Tablelist library. static void Initialize(Tcl_Interp*); protected: vtkKWTablelistInit() {}; ~vtkKWTablelistInit() {}; static int Initialized; private: vtkKWTablelistInit(const vtkKWTablelistInit&); // Not implemented. void operator=(const vtkKWTablelistInit&); // Not implemented. }; #endif kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/README.txt0000644000175000017500000001576711070725164022500 0ustar domibeldomibel The Multi-Column Listbox Package Tablelist by Csaba Nemethi csaba.nemethi@t-online.de What is Tablelist? ------------------ Tablelist is a library package for Tcl/Tk version 8.0 or higher, written in pure Tcl/Tk code. It contains: - the implementation of the "tablelist" mega-widget, including a general utility module for mega-widgets; - a demo script containing a useful procedure that displays the configuration options of an arbitrary widget in a tablelist and enables you to edit their values interactively; - a second demo script, implementing a simple widget browser based on a tablelist; - a third demo script, showing several ways to improve the appearance of a tablelist widget; - four further demo scripts, illustrating the interactive cell editing with the aid of various widgets from the Tk core and from the packages tile, BWidget, Iwidgets, combobox (by Bryan Oakley), and Mentry; - one further demo script, with a tablelist widget containing embedded windows; - tile-based counterparts of the above-mentioned demo scripts; - a tutorial in HTML format; - reference pages in HTML format. A tablelist widget is a multi-column listbox. The width of each column can be dynamic (i.e., just large enough to hold all its elements, including the header) or static (specified in characters or pixels). The columns are, per default, resizable. The alignment of each column can be specified as "left", "right", or "center". The columns, rows, and cells can be configured individually. Several of the global and column-specific options refer to the headers, implemented as label widgets. For instance, the "-labelcommand" option specifies a Tcl command to be invoked when mouse button 1 is released over a label. The most common value of this option is "tablelist::sortByColumn", which sorts the items based on the respective column. Interactive editing of the elements of a tablelist widget can be enabled for individual cells and for entire columns. A great variety of widgets from the Tk core and from the packages tile, BWidget, Iwidgets, combobox, and Mentry (or Mentry_tile) is supported for being used as embedded edit window. In addition, a rich set of keyboard bindings is provided for a comfortable navigation between the editable cells. The Tcl command corresponding to a tablelist widget is very similar to the one associated with a normal listbox. There are column-, row-, and cell-specific counterparts of the "configure" and "cget" subcommands ("columnconfigure", "rowconfigure", "cellconfigure", ...). They can be used, among others, to insert images into the cells and the header labels, or to insert embedded windows into the cells. The "index", "nearest", and "see" command options refer to the rows, but similar subcommands are provided for the columns and cells ("columnindex", "cellindex", ...). The items can be sorted with the "sort", "sortbycolumn", and "sortbycolumnlist" command options. The bindings defined for the body of a tablelist widget make it behave just like a normal listbox. This includes the support for the virtual event <> (which is equivalent to <>). In addition, version 2.3 or higher of the widget callback package Wcb (written in pure Tcl/Tk code as well) can be used to define callbacks for the "activate", "selection set", and "selection clear" commands, and Wcb version 3.0 or higher also supports callbacks for the "activatecell", "cellselection set", and "cellselection clear" commands. The download location of Wcb is http://www.nemethi.de How to get it? -------------- Tablelist is available for free download from the same URL as Wcb. The distribution file is "tablelist4.10.tar.gz" for UNIX and "tablelist4_10.zip" for Windows. These files contain the same information, except for the additional carriage return character preceding the linefeed at the end of each line in the text files for Windows. Tablelist is also hosted on SourceForge, as part of tklib, which in turn is contained in the tcllib project, having the address http://sourceforge.net/projects/tcllib How to install it? ------------------ Install the package as a subdirectory of one of the directories given by the "auto_path" variable. For example, you can install it as a directory at the same level as the Tcl and Tk script libraries. The locations of these library directories are given by the "tcl_library" and "tk_library" variables, respectively. To install Tablelist on UNIX, "cd" to the desired directory and unpack the distribution file "tablelist4.10.tar.gz": gunzip -c tablelist4.10.tar.gz | tar -xf - This command will create a directory named "tablelist4.10", with the subdirectories "demos", "doc", and "scripts". On Windows, use WinZip or some other program capable of unpacking the distribution file "tablelist4_10.zip" into the directory "tablelist4.10", with the subdirectories "demos", "doc", and "scripts". Note that the file "tablelistEdit.tcl" in the "scripts" directory is only needed for applications making use of interactive cell editing. Similarly, the file "tablelistMove.tcl" in the same directory is only required for scripts invoking the "move" or "movecolumn" tablelist command. Finally, the file "tablelistThemes.tcl" is only needed for applications using the package Tablelist_tile (see next section). Next, you should check the exact version number of your Tcl/Tk distribution, given by the "tcl_patchLevel" and "tk_patchLevel" variables. If you are using Tcl/Tk version 8.2.X, 8.3.0 - 8.3.2, or 8.4a1, then you should proceed as described in the "How to install it?" section of the file "tablelist.html", located in the "doc" directory. How to use it? -------------- The Tablelist distribution provides two packages, called Tablelist and Tablelist_tile. The main difference between the two is that Tablelist_tile enables the tile-based, theme-specific appearance of tablelist widgets; this package requires Tcl/Tk 8.4 or higher and tile 0.6 or higher. It is not possible to use both packages in one and the same application, because both are implemented in the same "tablelist" namespace and provide identical commands. To be able to use the commands and variables implemented in the package Tablelist, your scripts must contain one of the lines package require Tablelist package require tablelist Likewise, to be able to use the commands and variables implemented in the package Tablelist_tile, your scripts must contain one of the lines package require Tablelist_tile package require tablelist_tile Since the packagse Tablelist and Tablelist_tile are implemented in the namespace "tablelist", you must either import the procedures you need, or use qualified names like "tablelist::tablelist". For a detailed description of the commands and variables provided by Tablelist and of the examples contained in the "demos" directory, see the tutorial "tablelist.html" and the reference pages, all located in the "doc" directory. kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/README.kww.txt0000644000175000017500000000350711070725164023274 0ustar domibeldomibelThis is the Tablelist 4.9 widget. See info and license below. The changes are: - added a tablelistUtil2.tcl to provide a tablelist::emptyStr proc, useful for -formatcommand - the default mouse binding triggers "editing" on a single-click, which is downright annoying since it does prevents proper navigation or selection. The tablelistBind.tcl file has been edited to edit on double-click only. In tablelist::defineTablelistBody: a) copy the contents of: bind TablelistBody {...} to the empty script: bind TablelistBody { ... } then in bind TablelistBody { remove everything *below*: tablelist::condEditContainingCell ... \ $tablelist::x $tablelist::y b) in: bind TablelistBody {...} remove the line: tablelist::condEditContainingCell ... \ + next line - If an uneditable cell in a tablelist is double-clicked, let's generate a virtual event <>. In tablelistBind.tcl, locate tablelist::condEditContainingCell and find the lines above; Add the part after else. # # Finish a possibly active cell editing # if {$data(editRow) >= 0} { doFinishEditing $win } else { event generate $win <> } - in tablelistPublic.tcl replace: variable library [DIR] by: variable library [file dirname [info script]] - in mwutil.tcl replace: namespace eval mwutil { by: namespace eval ::mwutil { Otherwise the key won't work (namespace problem?) - in tablelist.tcl Comment: # ::tablelist::createBindings This line has been moved to tablelistUtil2.tcl so that it is evaluated last. We had a chicken-egg situation here that was relying on Tcl's auto-load feature, which is not available to us. kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistBitmaps.tcl0000644000175000017500000002642111043435206024771 0ustar domibeldomibel#============================================================================== # Contains procedures that create various bitmap images. The argument w # specifies a canvas displaying a sort arrow, while the argument win stands for # a tablelist widget. # # Copyright (c) 2006-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== #------------------------------------------------------------------------------ # tablelist::flat7x4Arrows #------------------------------------------------------------------------------ proc tablelist::flat7x4Arrows w { image create bitmap triangleUp$w -data " #define triangleUp7x4_width 7 #define triangleUp7x4_height 4 static unsigned char triangleUp7x4_bits[] = { 0x08, 0x1c, 0x3e, 0x7f}; " image create bitmap triangleDn$w -data " #define triangleDn7x4_width 7 #define triangleDn7x4_height 4 static unsigned char triangleDn7x4_bits[] = { 0x7f, 0x3e, 0x1c, 0x08}; " } #------------------------------------------------------------------------------ # tablelist::flat7x5Arrows #------------------------------------------------------------------------------ proc tablelist::flat7x5Arrows w { image create bitmap triangleUp$w -data " #define triangleUp7x5_width 7 #define triangleUp7x5_height 5 static unsigned char triangleUp7x5_bits[] = { 0x08, 0x1c, 0x3e, 0x7f, 0x22}; " image create bitmap triangleDn$w -data " #define triangleDn7x5_width 7 #define triangleDn7x5_height 5 static unsigned char triangleDn7x5_bits[] = { 0x22, 0x7f, 0x3e, 0x1c, 0x08}; " } #------------------------------------------------------------------------------ # tablelist::flat7x7Arrows #------------------------------------------------------------------------------ proc tablelist::flat7x7Arrows w { image create bitmap triangleUp$w -data " #define triangleUp7x7_width 7 #define triangleUp7x7_height 7 static unsigned char triangleUp7x7_bits[] = { 0x08, 0x1c, 0x1c, 0x3e, 0x3e, 0x7f, 0x7f}; " image create bitmap triangleDn$w -data " #define triangleDn7x7_width 7 #define triangleDn7x7_height 7 static unsigned char triangleDn7x7_bits[] = { 0x7f, 0x7f, 0x3e, 0x3e, 0x1c, 0x1c, 0x08}; " } #------------------------------------------------------------------------------ # tablelist::flat8x5Arrows #------------------------------------------------------------------------------ proc tablelist::flat8x5Arrows w { image create bitmap triangleUp$w -data " #define triangleUp8x5_width 8 #define triangleUp8x5_height 5 static unsigned char triangleUp8x5_bits[] = { 0x18, 0x3c, 0x7e, 0xff, 0xff}; " image create bitmap triangleDn$w -data " #define triangleDn8x5_width 8 #define triangleDn8x5_height 5 static unsigned char triangleDn8x5_bits[] = { 0xff, 0xff, 0x7e, 0x3c, 0x18}; " } #------------------------------------------------------------------------------ # tablelist::flat9x5Arrows #------------------------------------------------------------------------------ proc tablelist::flat9x5Arrows w { image create bitmap triangleUp$w -data " #define triangleUp9x5_width 9 #define triangleUp9x5_height 5 static unsigned char triangleUp9x5_bits[] = { 0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xff, 0x01}; " image create bitmap triangleDn$w -data " #define triangleDn9x5_width 9 #define triangleDn9x5_height 5 static unsigned char triangleDn9x5_bits[] = { 0xff, 0x01, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00}; " } #------------------------------------------------------------------------------ # tablelist::sunken8x7Arrows #------------------------------------------------------------------------------ proc tablelist::sunken8x7Arrows w { image create bitmap triangleUp$w -data " #define triangleUp8x7_width 8 #define triangleUp8x7_height 7 static unsigned char triangleUp8x7_bits[] = { 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff}; " image create bitmap darkLineUp$w -data " #define darkLineUp8x7_width 8 #define darkLineUp8x7_height 7 static unsigned char darkLineUp8x7_bits[] = { 0x08, 0x0c, 0x04, 0x06, 0x02, 0x03, 0x00}; " image create bitmap lightLineUp$w -data " #define lightLineUp8x7_width 8 #define lightLineUp8x7_height 7 static unsigned char lightLineUp8x7_bits[] = { 0x10, 0x30, 0x20, 0x60, 0x40, 0xc0, 0xff}; " image create bitmap triangleDn$w -data " #define triangleDn8x7_width 8 #define triangleDn8x7_height 7 static unsigned char triangleDn8x7_bits[] = { 0xff, 0xff, 0x7e, 0x7e, 0x3c, 0x3c, 0x18}; " image create bitmap darkLineDn$w -data " #define darkLineDn8x7_width 8 #define darkLineDn8x7_height 7 static unsigned char darkLineDn8x7_bits[] = { 0xff, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08}; " image create bitmap lightLineDn$w -data " #define lightLineDn8x7_width 8 #define lightLineDn8x7_height 7 static unsigned char lightLineDn8x7_bits[] = { 0x00, 0xc0, 0x40, 0x60, 0x20, 0x30, 0x10}; " } #------------------------------------------------------------------------------ # tablelist::sunken10x9Arrows #------------------------------------------------------------------------------ proc tablelist::sunken10x9Arrows w { image create bitmap triangleUp$w -data " #define triangleUp10x9_width 10 #define triangleUp10x9_height 9 static unsigned char triangleUp10x9_bits[] = { 0x30, 0x00, 0x78, 0x00, 0x78, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xff, 0x03, 0xff, 0x03}; " image create bitmap darkLineUp$w -data " #define darkLineUp10x9_width 10 #define darkLineUp10x9_height 9 static unsigned char darkLineUp10x9_bits[] = { 0x10, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00}; " image create bitmap lightLineUp$w -data " #define lightLineUp10x9_width 10 #define lightLineUp10x9_height 9 static unsigned char lightLineUp10x9_bits[] = { 0x20, 0x00, 0x60, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x03, 0xff, 0x03}; " image create bitmap triangleDn$w -data " #define triangleDn10x9_width 10 #define triangleDn10x9_height 9 static unsigned char triangleDn10x9_bits[] = { 0xff, 0x03, 0xff, 0x03, 0xfe, 0x01, 0xfe, 0x01, 0xfc, 0x00, 0xfc, 0x00, 0x78, 0x00, 0x78, 0x00, 0x30, 0x00}; " image create bitmap darkLineDn$w -data " #define darkLineDn10x9_width 10 #define darkLineDn10x9_height 9 static unsigned char darkLineDn10x9_bits[] = { 0xff, 0x03, 0x03, 0x00, 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x18, 0x00, 0x10, 0x00}; " image create bitmap lightLineDn$w -data " #define lightLineDn10x9_width 10 #define lightLineDn10x9_height 9 static unsigned char lightLineDn10x9_bits[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x60, 0x00, 0x20, 0x00}; " } #------------------------------------------------------------------------------ # tablelist::sunken12x11Arrows #------------------------------------------------------------------------------ proc tablelist::sunken12x11Arrows w { image create bitmap triangleUp$w -data " #define triangleUp12x11_width 12 #define triangleUp12x11_height 11 static unsigned char triangleUp12x11_bits[] = { 0x60, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf8, 0x01, 0xf8, 0x01, 0xfc, 0x03, 0xfc, 0x03, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0x0f, 0xff, 0x0f}; " image create bitmap darkLineUp$w -data " #define darkLineUp12x11_width 12 #define darkLineUp12x11_height 11 static unsigned char darkLineUp12x11_bits[] = { 0x20, 0x00, 0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00}; " image create bitmap lightLineUp$w -data " #define lightLineUp12x11_width 12 #define lightLineUp12x11_height 11 static unsigned char lightLineUp12x11_bits[] = { 0x40, 0x00, 0xc0, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0c, 0xff, 0x0f}; " image create bitmap triangleDn$w -data " #define triangleDn12x11_width 12 #define triangleDn12x11_height 11 static unsigned char triangleDn12x11_bits[] = { 0xff, 0x0f, 0xff, 0x0f, 0xfe, 0x07, 0xfe, 0x07, 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x01, 0xf8, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0x60, 0x00}; " image create bitmap darkLineDn$w -data " #define darkLineDn12x11_width 12 #define darkLineDn12x11_height 11 static unsigned char darkLineDn12x11_bits[] = { 0xff, 0x0f, 0x03, 0x00, 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x18, 0x00, 0x10, 0x00, 0x30, 0x00, 0x20, 0x00}; " image create bitmap lightLineDn$w -data " #define lightLineDn12x11_width 12 #define lightLineDn12x11_height 11 static unsigned char lightLineDn12x11_bits[] = { 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0xc0, 0x00, 0x40, 0x00}; " } #------------------------------------------------------------------------------ # tablelist::createSortRankImgs #------------------------------------------------------------------------------ proc tablelist::createSortRankImgs win { image create bitmap sortRank1$win -data " #define sortRank1_width 4 #define sortRank1_height 6 static unsigned char sortRank1_bits[] = { 0x04, 0x06, 0x04, 0x04, 0x04, 0x04}; " image create bitmap sortRank2$win -data " #define sortRank2_width 4 #define sortRank2_height 6 static unsigned char sortRank2_bits[] = { 0x06, 0x09, 0x08, 0x04, 0x02, 0x0f}; " image create bitmap sortRank3$win -data " #define sortRank3_width 4 #define sortRank3_height 6 static unsigned char sortRank3_bits[] = { 0x0f, 0x08, 0x06, 0x08, 0x09, 0x06}; " image create bitmap sortRank4$win -data " #define sortRank4_width 4 #define sortRank4_height 6 static unsigned char sortRank4_bits[] = { 0x04, 0x06, 0x05, 0x0f, 0x04, 0x04}; " image create bitmap sortRank5$win -data " #define sortRank5_width 4 #define sortRank5_height 6 static unsigned char sortRank5_bits[] = { 0x0f, 0x01, 0x07, 0x08, 0x09, 0x06}; " image create bitmap sortRank6$win -data " #define sortRank6_width 4 #define sortRank6_height 6 static unsigned char sortRank6_bits[] = { 0x06, 0x01, 0x07, 0x09, 0x09, 0x06}; " image create bitmap sortRank7$win -data " #define sortRank7_width 4 #define sortRank7_height 6 static unsigned char sortRank7_bits[] = { 0x0f, 0x08, 0x04, 0x04, 0x02, 0x02}; " image create bitmap sortRank8$win -data " #define sortRank8_width 4 #define sortRank8_height 6 static unsigned char sortRank8_bits[] = { 0x06, 0x09, 0x06, 0x09, 0x09, 0x06}; " image create bitmap sortRank9$win -data " #define sortRank9_width 4 #define sortRank9_height 6 static unsigned char sortRank9_bits[] = { 0x06, 0x09, 0x09, 0x0e, 0x08, 0x06}; " } #------------------------------------------------------------------------------ # tablelist::createCheckbuttonImgs #------------------------------------------------------------------------------ proc tablelist::createCheckbuttonImgs {} { variable checkedImg variable uncheckedImg set checkedImg [image create bitmap -data " #define checked_width 9 #define checked_height 9 static unsigned char checked_bits[] = { 0x00, 0x00, 0x80, 0x00, 0xc0, 0x00, 0xe2, 0x00, 0x76, 0x00, 0x3e, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x00, 0x00}; "] set uncheckedImg [image create bitmap -data " #define unchecked_width 9 #define unchecked_height 9 static unsigned char unchecked_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; "] } kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/vtkKWTablelistTclLibrary.h0000644000175000017500000047055511073220147026047 0ustar domibeldomibel/* * Resource generated for file: * mwutil.tcl (zlib, base64) (text file) */ static const unsigned long file_mwutil_tcl_length = 4728; static const unsigned long file_mwutil_tcl_decoded_length = 15150; static const unsigned char file_mwutil_tcl[] = "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" "GICtsI89mC8K5bloaqAQeMNUdehyT/Azoq/kc="; /* * Resource generated for file: * tablelist.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelist_tcl_length = 280; static const unsigned long file_tablelist_tcl_decoded_length = 514; static const unsigned char file_tablelist_tcl[] = "eNqtkM1qAkEQhO/zFAWbgx52mYQcZEAQJcfktC/QzjZr4/ysM7MS394NQaIY8GIf+vB1dV" "Nd1fKppSp8kgS0tHXsJBcMZPfUM3zsRseNqibJJg6nJP2uYGbneNNa11NbAJtMW8IXey47" "weyj9iTOwP7gJvziValjcBK46Xiuqif7Vxe/iQ+jJEZrHRb3dI9/aM3fZAvK5XljbPQ+Br" "w3r/rv9JDiUTq+CunFmKulI6csMdzpywO9uqFj5lYcQ0+B3wxsYiq8ltBJ6LM6AyOGng0="; /* * Resource generated for file: * tablelistBind.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistBind_tcl_length = 18076; static const unsigned long file_tablelistBind_tcl_decoded_length = 78007; static const unsigned char file_tablelistBind_tcl[] = "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" "e2YMBkDy/gcAoooa"; /* * Resource generated for file: * tablelistBitmaps.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistBitmaps_tcl_length = 1940; static const unsigned long file_tablelistBitmaps_tcl_decoded_length = 11537; static const unsigned char file_tablelistBitmaps_tcl[] = "eNrFWkuP2zYQvvtXEHEOCbC70JvSFgFaJD0UKHro4xQEBVembGFt2ZDo7AbB/vdIlGSN+B" "KdKqoPBOEZi9/MfDMf7d31u1lfqzV6fywYyYsKncpjSjfnklaI7QhDaUkJo+gzKfPjuUIP" "OTuQE8oPZEurO4T+3lFEyu35QAuGnuoHVSea5llef5yglBSfSYU2eXXaky95sa3fq44lqz" "9RHp9u0NMu39P6GPiIvEAVI8WmQtmxrJ9HECMPe7rPq8a42VJ2t1pzwKcvZb7dMfQmfYs8" "x4lu6yVG6H1FHgj6gx4o2+Xoza+3B5Lv71HavH1XtG//zG6PxT4v6N2Gvl2tZ87man0766" "uO9pKD+/tsTxh+Dn5pUljNflRTfu1p6Al9XaH6xcvfU6OjBCtzUmz39J/T6yd0uyGMoFer" "9YZmdZqBsX7Yv3Ud2Q5hjXVHeVmDVc0DlqfoXFT5tqAblO5IKfjWZ1cfP6F3LS7n2Ylv6t" "VNm9WnzYqzl59WryZRfygMqD8UJtSt1Q516yuixtmAt8XuxBz1yyJcChflUjgnl0Ijl8K+" "KuE0l0IrLjWr583DqNDIKFvsra+I3fNu/n9e4UV5hefkFTbyCve1wdO8wkZeQXZBjs01tb" "CRY7ZxtL7qqQU5Bpm2ON/iRedYPOcciy+zINZYbedYrJgFLuebz+uBeYWyrF3n4JgJe2u1" "nWMq7D3SAXsbh7scr5JFeZXMyavkUptEY7XlVaLilcM7nK9+POxxOuwzCva8io47B+tMkb" "VWW9YlWtY5rhgBjAxG3GdiEU5W5+KR1s2ylLoK580z77Bx3tnra6zQJTjv4NS7YvZtSPn4" "e41KGcdgVMUxtprjGPuq7wlOy7mArxFf+d3O8QHndHHsm9O1gQCrKhLBbA5FcFbPCp+vHl" "8jvgZ8TZ059Qgb9cj+zqOKQ9YjqEojbZriljKOwWjilk0cY1/NhPMBnyLAM3h3m+SWMhBg" "NXLLJhTBWeoTwKEAcMsDnHOXnM2u85wsOpyHA+eYzs3TuoK5js7eVSyZGtDcWayYD24OOF" "bvs1Szp502d0SmQKoBqfv9HGNenRDBbk6I4Gy6SrkgCQ7cgyR0beqAxnW6hHTd7ECNgOs8" "eqFOiehgzonoLf2GAXBHYB+AfQr2sbzvWeI4A0tgaqxYYik85rbp7HZt0zmbhvZoT6Xrqq" "ttoe67u6brfBuWWCqYuW2sEiI4G1UMct1TtIfYNuOEwE5zdVf7/yyFE21jlRPRWy2HoxWm" "xh21h9A2l3ZqHxVoOtBb/vuO6z277rKiOpw4i6o2j+tr72kdutq77qSwcnex+LBKmW4fgx" "ERS+PC75U1lSYMlvZtA2ZwP4viqpMlOkwkS3Q3CQy8klylxl3TBZqJs4waq9MleUzkS/IX" "E3aV8upkdzSlrAe1Fbtsldrcir2DZSv27hpxyqQ+0fUS7DehFXUdq+nwaE4VN7eiZbJEd1" "OyfrCSi93uzavwE61omS/J30Llp74fyONIvhxPXgzAFFhE/dsy/HUs2Z+kePztsP3x8i8f" "yf8rRX8DqDpX93XjJ5LjYu1YESgsHRsiNRkGP4kFgfTTzWg1crp/rGeE7Wlhe5awPRl2Cz" "gBohoAemZWsH0jbF8L27eE7cuwMwA4Avs2kMgKdmCEHWhhB5awAzNJQjBnryFJaIQdamGH" "lrBDXbbdQSG/I9uREXakhR1Zwo503Iawk6thYyNsrIWNLWFjM7cDqSU9K9ixEXashR1bwo" "7NkyT6zmwnRtiJFnZiCTsxw25XCmfLgtL6fkfTx4czY8diQXUVTkVfXzp9bf7PtHGuM1h7" "0E1tHb9/LoCFmyrKgDf6qCq1WNzOX/obcv+++SeY3st0KdPdnii4gmFwNfPp6Bbrpprvne" "Dy9ekSPkyKXQIun5BSMFjMSRj8LO6m1692j2rT8LL6Bg5PFXc="; /* * Resource generated for file: * tablelistConfig.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistConfig_tcl_length = 17740; static const unsigned long file_tablelistConfig_tcl_decoded_length = 93118; static const unsigned char file_tablelistConfig_tcl[] = "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" "JRj4HDYxpth6DrljdDhZb/AyKf/mg="; /* * Resource generated for file: * tablelistEdit.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistEdit_tcl_length = 17824; static const unsigned long file_tablelistEdit_tcl_decoded_length = 75325; static const unsigned char file_tablelistEdit_tcl[] = "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"; /* * Resource generated for file: * tablelistMove.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistMove_tcl_length = 3720; static const unsigned long file_tablelistMove_tcl_decoded_length = 9942; static const unsigned char file_tablelistMove_tcl[] = "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" "8HcT4tOg=="; /* * Resource generated for file: * tablelistPublic.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistPublic_tcl_length = 1292; static const unsigned long file_tablelistPublic_tcl_decoded_length = 2378; static const unsigned char file_tablelistPublic_tcl[] = "eNqtVU1v4zYQPVu/YmDvIQESIy16KAwUaONm0Rx2G3Td9pAaC0oa22woUiApfzTIf+8bSv" "7cxO1hfRDM4fDNzOOb4eCHr/rLBvRBaUsTlRs2OkRSttyvPkdtmGpVPKk5U+XKxvAwG+DU" "2NUbr+eLSBfFJX17c3Nzjc/3ROOgckUfueK40HRxd10pbUZUiHloW/OP8dpZoy0PS77MBl" "+5pMyqigOSZuKlMjQaxV11zxnhN2i/9NDkRhe0VF6LRxgd7G6NtGQftLO974bf3BzvGJ17" "5Te9x5mwVGovgelR25mjUHhdx+k0Owo49qwiB1JkeUX7tFa6nHM8DH9Qw7p2PvZ2zseIn7" "BHccGkI1eB3AzYp7iUb8hZJudxhZ7FScdAhTNNZcPZqAGf2804eZIqy4mTgO06HGfyC5ua" "PdXeFVw2HlU2gUuCuHJtS23nHSfnAyLdnfoeVFwgS7u8W7KN7zWb8iTmbzyHH6LKnbgmdA" "UHmqFWbbGjiqiXTAUbQ1zqiDzOxkeNt38mkDsb/Yb260+1trdufWAZuyp3ML2KJDa43tvC" "J6SZpL+1/AwVTHTFLQ79lfV6vW5LwlhUdLBEIdtlCpm/EVIgflVPhjf/6SYJfOBthZLKfr" "VNrrNsk3uv11w+OCSzd71/+KksfbvOXrJsOykggqUuea/E0ahwVeUsvTvoxtGo660sjZQJ" "VDxzxriViGWnoytc5NI9tVLq7w4PY2H6aVrtbWlcpY0r4AURgrTGrmGPYjcBYSbSudEltz" "mEYuFsGk646Ty6CRpiwCF5jK6wQ5M5KEmeonLCfM6dMy/dvNklsI/5TvbTZsJ/zWXV0GPq" "4qMAaKyIJv79GGkq7H9JYou9o5KQPq+5aCLYXC3YMi7giCIgvEESjq68jhEUobcaC3aGRP" "eRuoROqAanmDFCG14JbTGGE7FXHcuYSOI+016eHD9vKmjodUa/KPhZIP9IiP6jTFyMF16T" "q8/R3Z1J+2GlY7GArcaB3ko+YvYcG2/punBQLnuPMvs6SuHWIUnhFLShMNwx5Q6z6ejVTH" "3SO3k6tU11BklT1TVeGxUh+H7We8l6zTbyOQkILP0/IXQ1TgVcYF9EFGkK1khfq0DPL4Lx" "NBrNvGSUlunvG25G5WzaZfrbagzj2G/QCxAYG3BhmUtpz0BG/aPNhoxTYkDHlFyBmitaap" "WIKDUmEchn3zYoNfWOoybHE8oFitpQv3sr+nQRmDutoMY+mvterrt/KWox4JTRqqqJ7nMt" "z0X7Fv+NMXUyarrHevsITbN/AYjLEpY="; /* * Resource generated for file: * tablelistSort.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistSort_tcl_length = 5228; static const unsigned long file_tablelistSort_tcl_decoded_length = 15396; static const unsigned char file_tablelistSort_tcl[] = "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"; /* * Resource generated for file: * tablelistThemes.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistThemes_tcl_length = 11336; static const unsigned long file_tablelistThemes_tcl_decoded_length = 52595; static const unsigned char file_tablelistThemes_tcl[] = "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"; /* * Resource generated for file: * tablelistUtil.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistUtil_tcl_length = 31352; static const unsigned long file_tablelistUtil_tcl_decoded_length = 130210; static const unsigned char file_tablelistUtil_tcl[] = "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"; /* * Resource generated for file: * tablelistUtil2.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistUtil2_tcl_length = 372; static const unsigned long file_tablelistUtil2_tcl_decoded_length = 593; static const unsigned char file_tablelistUtil2_tcl[] = "eNqtkM1uwyAQhO88xSg+tJUSP4CPvVW9NalyxrCOUTBYsORHUd69a1dt2qrHcECw7Mx8bL" "W661IVWLeevMvcNDSMfF5zUpXU34hLCtABcxmZkwu7Gu+ZuuLRxYSVbINmE4dBB6uqO7ON" "KZr/8HDRaXfFRQHpE3KxUFclzJveZZRMFhzREly46Ws2fom2MI4Eo8MDY080wjG4p0RL6D" "xdknRTFrMYpgfownHlo7boSEsa4dEkOdGzC1YmknGMk5nEdbEEi2NPf2LFTLhGnYRMYqae" "WLxFrw+EjfGY7b8lW2d3NAvncJmwM9r78xJilONA3Evu7Rs2oktxwIH3r9vNl8tLcFyb0+" "lJqab5McXf8OoDw6mzjw=="; /* * Resource generated for file: * tablelistWidget.tcl (zlib, base64) (text file) */ static const unsigned long file_tablelistWidget_tcl_length = 31924; static const unsigned long file_tablelistWidget_tcl_decoded_length = 145665; static const unsigned char file_tablelistWidget_tcl[] = "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" "rFY="; kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistUtil2.tcl0000644000175000017500000000112111070725164024364 0ustar domibeldomibel#------------------------------------------------------------------------------ # tablelist::emptyStr # # Return an empty string. Useful for -formatcommand #------------------------------------------------------------------------------ proc tablelist::emptyStr {arg} { return "" } # This used to be in tablelist.tcl, but we can't keep it there, as it relies # on the auto-load feature (createBindings won't be found when tablelist.tcl # is parsed, and would have Tcl load tablelistWidget.tcl automatically, # something we can't do from vtkKWTablelistInit.cxx) ::tablelist::createBindings kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistConfig.tcl0000644000175000017500000026567611073220147024617 0ustar domibeldomibel#============================================================================== # Contains private configuration procedures for tablelist widgets. # # Copyright (c) 2000-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== #------------------------------------------------------------------------------ # tablelist::extendConfigSpecs # # Extends the elements of the array configSpecs. #------------------------------------------------------------------------------ proc tablelist::extendConfigSpecs {} { variable usingTile variable helpLabel variable configSpecs variable winSys # # Extend some elements of the array configSpecs # lappend configSpecs(-activestyle) frame lappend configSpecs(-columns) {} lappend configSpecs(-editendcommand) {} lappend configSpecs(-editstartcommand) {} lappend configSpecs(-forceeditendcommand) 0 lappend configSpecs(-incrarrowtype) up lappend configSpecs(-labelcommand) {} lappend configSpecs(-labelcommand2) {} lappend configSpecs(-labelrelief) raised lappend configSpecs(-listvariable) {} lappend configSpecs(-movablecolumns) 0 lappend configSpecs(-movablerows) 0 lappend configSpecs(-movecolumncursor) icon lappend configSpecs(-movecursor) hand2 lappend configSpecs(-protecttitlecolumns) 0 lappend configSpecs(-resizablecolumns) 1 lappend configSpecs(-resizecursor) sb_h_double_arrow lappend configSpecs(-selecttype) row lappend configSpecs(-setfocus) 1 lappend configSpecs(-showarrow) 1 lappend configSpecs(-showlabels) 1 lappend configSpecs(-showseparators) 0 lappend configSpecs(-snipstring) ... lappend configSpecs(-sortcommand) {} lappend configSpecs(-spacing) 0 lappend configSpecs(-stretch) {} lappend configSpecs(-stripebackground) {} lappend configSpecs(-stripeforeground) {} lappend configSpecs(-stripeheight) 1 lappend configSpecs(-targetcolor) black lappend configSpecs(-titlecolumns) 0 lappend configSpecs(-tooltipaddcommand) {} lappend configSpecs(-tooltipdelcommand) {} # # Append the default values of the configuration options # of a temporary, invisible listbox widget to the values # of the corresponding elements of the array configSpecs # set helpListbox .__helpListbox for {set n 0} {[winfo exists $helpListbox]} {incr n} { set helpListbox .__helpListbox$n } listbox $helpListbox foreach configSet [$helpListbox configure] { if {[llength $configSet] != 2} { set opt [lindex $configSet 0] if {[info exists configSpecs($opt)]} { lappend configSpecs($opt) [lindex $configSet 3] } } } destroy $helpListbox set helpLabel .__helpLabel for {set n 0} {[winfo exists $helpLabel]} {incr n} { set helpLabel .__helpLabel$n } if {$usingTile} { foreach opt {-highlightbackground -highlightcolor -highlightthickness -labelactivebackground -labelactiveforeground -labeldisabledforeground -labelheight} { unset configSpecs($opt) } # # Append theme-specific values to some elements of the array configSpecs # setThemeDefaults ttk::label $helpLabel -takefocus 0 # # Define the header label layout # style theme settings "default" { style layout TablelistHeader.TLabel { Treeheading.cell Treeheading.border -children { Label.padding -children { Label.label } } } } if {[string compare [package provide ttk::theme::aqua] ""] != 0 || [string compare [package provide tile::theme::aqua] ""] != 0} { style theme settings "aqua" { if {[info exists tile::patchlevel] && [string compare $tile::patchlevel "0.6.4"] < 0} { style layout TablelistHeader.TLabel { Treeheading.cell Label.padding -children { Label.label -side top Separator.hseparator -side bottom } } } else { style layout TablelistHeader.TLabel { Treeheading.cell Label.padding -children { Label.label -side top } } } style map TablelistHeader.TLabel -foreground [list \ {disabled background} #a3a3a3 disabled #a3a3a3 \ background black] } } } else { if {$::tk_version < 8.3} { unset configSpecs(-titlecolumns) } # # Append the default values of some configuration options # of an invisible label widget to the values of the # corresponding -label* elements of the array configSpecs # tk::label $helpLabel -takefocus 0 foreach optTail {font height} { set configSet [$helpLabel configure -$optTail] lappend configSpecs(-label$optTail) [lindex $configSet 3] } if {[catch {$helpLabel configure -activebackground} configSet1] == 0 && [catch {$helpLabel configure -activeforeground} configSet2] == 0} { lappend configSpecs(-labelactivebackground) [lindex $configSet1 3] lappend configSpecs(-labelactiveforeground) [lindex $configSet2 3] } else { unset configSpecs(-labelactivebackground) unset configSpecs(-labelactiveforeground) } if {[catch {$helpLabel configure -disabledforeground} configSet] == 0} { lappend configSpecs(-labeldisabledforeground) [lindex $configSet 3] } else { unset configSpecs(-labeldisabledforeground) } if {[string compare $winSys "win32"] == 0 && $::tcl_platform(osVersion) < 5.1} { lappend configSpecs(-labelpady) 0 } else { set configSet [$helpLabel configure -pady] lappend configSpecs(-labelpady) [lindex $configSet 3] } # # Steal the default values of some configuration # options from a temporary, invisible button widget # set helpButton .__helpButton for {set n 0} {[winfo exists $helpButton]} {incr n} { set helpButton .__helpButton$n } button $helpButton foreach opt {-disabledforeground -state} { if {[llength $configSpecs($opt)] == 3} { set configSet [$helpButton configure $opt] lappend configSpecs($opt) [lindex $configSet 3] } } foreach optTail {background foreground} { set configSet [$helpButton configure -$optTail] lappend configSpecs(-label$optTail) [lindex $configSet 3] } if {[string compare $winSys "classic"] == 0 || [string compare $winSys "aqua"] == 0} { lappend configSpecs(-labelborderwidth) 1 } else { set configSet [$helpButton configure -borderwidth] lappend configSpecs(-labelborderwidth) [lindex $configSet 3] } destroy $helpButton # # Set the default values of the -arrowcolor, # -arrowdisabledcolor, and -arrowstyle options # switch $winSys { x11 { lappend configSpecs(-arrowcolor) {} lappend configSpecs(-arrowdisabledcolor) {} lappend configSpecs(-arrowstyle) sunken10x9 } win32 { if {$::tcl_platform(osVersion) < 5.1} { lappend configSpecs(-arrowcolor) {} lappend configSpecs(-arrowdisabledcolor) {} lappend configSpecs(-arrowstyle) sunken8x7 } else { lappend configSpecs(-arrowcolor) #aca899 lappend configSpecs(-arrowdisabledcolor) SystemDisabledText lappend configSpecs(-arrowstyle) flat9x5 } } classic - aqua { lappend configSpecs(-arrowcolor) #777777 lappend configSpecs(-arrowdisabledcolor) #a3a3a3 lappend configSpecs(-arrowstyle) flat7x7 } } lappend configSpecs(-arrowdisabledcolor) \ [lindex $configSpecs(-arrowcolor) 3] } } #------------------------------------------------------------------------------ # tablelist::doConfig # # Applies the value val of the configuration option opt to the tablelist widget # win. #------------------------------------------------------------------------------ proc tablelist::doConfig {win opt val} { variable usingTile variable helpLabel variable configSpecs upvar ::tablelist::ns${win}::data data # # Apply the value to the widget(s) corresponding to the given option # switch [lindex $configSpecs($opt) 2] { c { # # Apply the value to all children and save the # properly formatted value of val in data($opt) # foreach w [winfo children $win] { if {[regexp {^(body|hdr|sep([0-9]+)?)$} [winfo name $w]]} { $w configure $opt $val } } $data(hdrTxt) configure $opt $val $data(hdrLbl) configure $opt $val foreach w [winfo children $data(hdrTxtFr)] { $w configure $opt $val } set data($opt) [$data(hdrLbl) cget $opt] } b { # # Apply the value to the body text widget and save # the properly formatted value of val in data($opt) # set w $data(body) $w configure $opt $val set data($opt) [$w cget $opt] switch -- $opt { -background { # # Apply the value to the frame (because of # the shadow colors of its 3-D border), to # the separators, and to the "disabled" tag # if {$usingTile} { styleConfig Frame$win.TFrame $opt $val styleConfig Seps$win.TSeparator $opt $val } else { $win configure $opt $val foreach c [winfo children $win] { if {[regexp {^sep[0-9]+$} [winfo name $c]]} { $c configure $opt $val } } } $w tag configure disabled $opt $val updateColorsWhenIdle $win } -font { # # Apply the value to the header text widget and to # the listbox child, rebuild the lists of the column # fonts and tag names, configure the edit window if # present, set up and adjust the columns, and make # sure the items will be redisplayed at idle time # $data(hdrTxt) configure $opt $val $data(lb) configure $opt $val set data(charWidth) [font measure $val -displayof $win 0] makeColFontAndTagLists $win if {$data(editRow) >= 0} { setEditWinFont $win } for {set col 0} {$col < $data(colCount)} {incr col} { if {$data($col-maxwidth) > 0} { set data($col-maxPixels) \ [charsToPixels $win $val $data($col-maxwidth)] } } setupColumns $win $data(-columns) 0 adjustColumns $win allCols 1 redisplayWhenIdle $win } -foreground { # # Set the background color of the main separator # frame (if any) to the specified value, and apply # this value to the "disabled" tag if needed # if {$usingTile} { styleConfig Sep$win.TSeparator -background $val } else { if {[winfo exists $data(sep)]} { $data(sep) configure -background $val } } if {[string compare $data(-disabledforeground) ""] == 0} { $w tag configure disabled $opt $val } updateColorsWhenIdle $win } } } l { # # Apply the value to all not individually configured labels # and save the properly formatted value of val in data($opt) # set optTail [string range $opt 6 end] ;# remove the -label configLabel $data(hdrLbl) -$optTail $val for {set col 0} {$col < $data(colCount)} {incr col} { set w $data(hdrTxtFrLbl)$col if {![info exists data($col$opt)]} { configLabel $w -$optTail $val } } if {$usingTile && [string compare $opt "-labelpady"] == 0} { set data($opt) $val } else { set data($opt) [$data(hdrLbl) cget -$optTail] } switch -- $opt { -labelbackground - -labelforeground { # # Apply the value to $data(hdrTxt) and conditionally # to the canvases displaying up- or down-arrows # $data(hdrTxt) configure -$optTail $data($opt) foreach col $data(arrowColList) { if {![info exists data($col$opt)]} { configCanvas $win $col } } } -labelborderwidth { # # Adjust the columns (including # the height of the header frame) # adjustColumns $win allLabels 1 } -labeldisabledforeground { # # Conditionally apply the value to the # canvases displaying up- or down-arrows # foreach col $data(arrowColList) { if {![info exists data($col$opt)]} { configCanvas $win $col } } } -labelfont { # # Adjust the columns (including # the height of the header frame) # adjustColumns $win allLabels 1 } -labelheight - -labelpady { # # Adjust the height of the header frame # adjustHeaderHeight $win } } } f { # # Apply the value to the frame and save the # properly formatted value of val in data($opt) # $win configure $opt $val set data($opt) [$win cget $opt] } w { switch -- $opt { -activestyle { # # Configure the "active" tag and save the # properly formatted value of val in data($opt) # variable activeStyles set val [mwutil::fullOpt "active style" $val $activeStyles] set w $data(body) switch $val { frame { $w tag configure active \ -borderwidth 1 -relief solid -underline "" } none { $w tag configure active \ -borderwidth "" -relief "" -underline "" } underline { $w tag configure active \ -borderwidth "" -relief "" -underline 1 } } set data($opt) $val } -arrowcolor - -arrowdisabledcolor { # # Save the properly formatted value of val in data($opt) # and set the color of the normal or disabled arrows # if {[string compare $val ""] == 0} { set data($opt) "" } else { $helpLabel configure -foreground $val set data($opt) [$helpLabel cget -foreground] } if {([string compare $opt "-arrowcolor"] == 0 && !$data(isDisabled)) || ([string compare $opt "-arrowdisabledcolor"] == 0 && $data(isDisabled))} { foreach w [info commands $data(hdrTxtFrCanv)*] { fillArrows $w $val $data(-arrowstyle) } } } -arrowstyle { # # Save the properly formatted value of val in data($opt) # and draw the corresponding arrows in the canvas widgets # variable arrowStyles set data($opt) \ [mwutil::fullOpt "arrow style" $val $arrowStyles] regexp {^(flat|sunken)([0-9]+)x([0-9]+)$} $data($opt) \ dummy relief width height set data(arrowWidth) $width foreach w [info commands $data(hdrTxtFrCanv)*] { createArrows $w $width $height $relief if {$data(isDisabled)} { fillArrows $w $data(-arrowdisabledcolor) $data($opt) } else { fillArrows $w $data(-arrowcolor) $data($opt) } } if {[llength $data(arrowColList)] > 0} { foreach col $data(arrowColList) { raiseArrow $win $col lappend whichWidths l$col } adjustColumns $win $whichWidths 1 } } -columns { # # Set up and adjust the columns, rebuild # the lists of the column fonts and tag # names, and redisplay the items # set selCells [curCellSelection $win] setupColumns $win $val 1 adjustColumns $win allCols 1 adjustColIndex $win data(anchorCol) 1 adjustColIndex $win data(activeCol) 1 makeColFontAndTagLists $win redisplay $win 0 $selCells } -disabledforeground { # # Configure the "disabled" tag in the body text widget and # save the properly formatted value of val in data($opt) # set w $data(body) if {[string compare $val ""] == 0} { $w tag configure disabled -fgstipple gray50 \ -foreground $data(-foreground) set data($opt) "" } else { $w tag configure disabled -fgstipple "" \ -foreground $val set data($opt) [$w tag cget disabled -foreground] } if {$data(isDisabled)} { updateColorsWhenIdle $win } } -editendcommand - -editstartcommand - -labelcommand - -labelcommand2 - -selectmode - -sortcommand - -tooltipaddcommand - -tooltipdelcommand - -yscrollcommand { set data($opt) $val } -exportselection { # # Save the boolean value specified by val in # data($opt). In addition, if the selection is # exported and there are any selected rows in the # widget then make win the new owner of the PRIMARY # selection and register a callback to be invoked # when it loses ownership of the PRIMARY selection # set data($opt) [expr {$val ? 1 : 0}] if {$val && [llength [$data(body) tag nextrange select 1.0]] != 0} { selection own -command \ [list ::tablelist::lostSelection $win] $win } } -forceeditendcommand - -movablecolumns - -movablerows - -protecttitlecolumns - -resizablecolumns - -setfocus { # # Save the boolean value specified by val in data($opt) # set data($opt) [expr {$val ? 1 : 0}] } -height { # # Adjust the heights of the body text widget # and of the listbox child, and save the # properly formatted value of val in data($opt) # set val [format "%d" $val] ;# integer check with error msg if {$val <= 0} { set nonHiddenRowCount \ [expr {$data(itemCount) - $data(hiddenRowCount)}] $data(body) configure $opt $nonHiddenRowCount $data(lb) configure $opt $nonHiddenRowCount } else { $data(body) configure $opt $val $data(lb) configure $opt $val } set data($opt) $val } -incrarrowtype { # # Save the properly formatted value of val in # data($opt) and raise the corresponding arrows # if the currently mapped canvas widgets # variable arrowTypes set data($opt) \ [mwutil::fullOpt "arrow type" $val $arrowTypes] foreach col $data(arrowColList) { raiseArrow $win $col } } -listvariable { # # Associate val as list variable with the # given widget and save it in data($opt) # makeListVar $win $val set data($opt) $val if {[string compare $val ""] == 0} { set data(hasListVar) 0 } else { set data(hasListVar) 1 } } -movecolumncursor - -movecursor - -resizecursor { # # Save the properly formatted value of val in data($opt) # $helpLabel configure -cursor $val set data($opt) [$helpLabel cget -cursor] } -selectbackground - -selectforeground { # # Configure the "select" tag in the body text widget # and save the properly formatted value of val in # data($opt). Don't use the built-in "sel" tag # because on Windows the selection in a text widget only # becomes visible when the window gets the input focus. # set w $data(body) set optTail [string range $opt 7 end] ;# remove the -select $w tag configure select -$optTail $val set data($opt) [$w tag cget select -$optTail] if {!$data(isDisabled)} { updateColorsWhenIdle $win } } -selecttype { # # Save the properly formatted value of val in data($opt) # variable selectTypes set val [mwutil::fullOpt "selection type" $val $selectTypes] set data($opt) $val } -selectborderwidth { # # Configure the "select" tag in the body text widget # and save the properly formatted value of val in # data($opt). Don't use the built-in "sel" tag # because on Windows the selection in a text widget only # becomes visible when the window gets the input focus. # In addition, adjust the line spacing accordingly and # apply the value to the listbox child, too. # set w $data(body) set optTail [string range $opt 7 end] ;# remove the -select $w tag configure select -$optTail $val set data($opt) [$w tag cget select -$optTail] set pixVal [winfo pixels $w $val] if {$pixVal < 0} { set pixVal 0 } set spacing [winfo pixels $w $data(-spacing)] if {$spacing < 0} { set spacing 0 } $w configure -spacing1 [expr {$spacing + $pixVal}] \ -spacing3 [expr {$spacing + $pixVal + 1}] $data(lb) configure $opt $val redisplayWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win } -setgrid { # # Apply the value to the listbox child and save # the properly formatted value of val in data($opt) # $data(lb) configure $opt $val set data($opt) [$data(lb) cget $opt] } -showarrow { # # Save the boolean value specified by val in # data($opt) and manage or unmanage the # canvases displaying up- or down-arrows # set data($opt) [expr {$val ? 1 : 0}] makeSortAndArrowColLists $win adjustColumns $win allLabels 1 } -showlabels { # # Save the boolean value specified by val in data($opt) # and adjust the height of the header frame # set data($opt) [expr {$val ? 1 : 0}] adjustHeaderHeight $win } -showseparators { # # Save the boolean value specified by val in data($opt), # and create or destroy the separators if needed # set oldVal $data($opt) set data($opt) [expr {$val ? 1 : 0}] if {!$oldVal && $data($opt)} { createSeps $win } elseif {$oldVal && !$data($opt)} { foreach w [winfo children $win] { if {[regexp {^sep[0-9]+$} [winfo name $w]]} { destroy $w } } } } -snipstring { # # Save val in data($opt), adjust the columns, and make # sure the items will be redisplayed at idle time # set data($opt) $val adjustColumns $win {} 0 redisplayWhenIdle $win } -spacing { # # Adjust the line spacing and save val in data($opt) # set w $data(body) set pixVal [winfo pixels $w $val] if {$pixVal < 0} { set pixVal 0 } set selectBd [winfo pixels $w $data(-selectborderwidth)] if {$selectBd < 0} { set selectBd 0 } $w configure -spacing1 [expr {$pixVal + $selectBd}] \ -spacing3 [expr {$pixVal + $selectBd + 1}] set data($opt) $val redisplayWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win } -state { # # Apply the value to all labels and their sublabels # (if any), as well as to the edit window (if present), # add/remove the "disabled" tag to/from the contents # of the body text widget, configure the borderwidth # of the "active" and "select" tags, save the # properly formatted value of val in data($opt), # and raise the corresponding arrow in the canvas # variable states set val [mwutil::fullOpt "state" $val $states] catch { configLabel $data(hdrLbl) $opt $val for {set col 0} {$col < $data(colCount)} {incr col} { configLabel $data(hdrTxtFrLbl)$col $opt $val } } if {$data(editRow) >= 0} { catch {$data(bodyFrEd) configure $opt $val} } set w $data(body) switch $val { disabled { $w tag add disabled 1.0 end $w tag configure select -relief flat set data(isDisabled) 1 } normal { $w tag remove disabled 1.0 end $w tag configure select -relief raised set data(isDisabled) 0 } } set data($opt) $val foreach col $data(arrowColList) { configCanvas $win $col raiseArrow $win $col } updateColorsWhenIdle $win } -stretch { # # Save the properly formatted value of val in # data($opt) and stretch the stretchable columns # if {[string first $val "all"] == 0} { set data($opt) all } else { set data($opt) $val sortStretchableColList $win } set data(forceAdjust) 1 stretchColumnsWhenIdle $win } -stripebackground - -stripeforeground { # # Configure the "stripe" tag in the body text # widget, save the properly formatted value of val # in data($opt), and draw the stripes if necessary # set w $data(body) set optTail [string range $opt 7 end] ;# remove the -stripe $w tag configure stripe -$optTail $val set data($opt) [$w tag cget stripe -$optTail] makeStripesWhenIdle $win } -stripeheight { # # Save the properly formatted value of val in # data($opt) and draw the stripes if necessary # set val [format "%d" $val] ;# integer check with error msg set data($opt) $val makeStripesWhenIdle $win } -targetcolor { # # Set the color of the row and column gaps, and save # the properly formatted value of val in data($opt) # $data(rowGap) configure -background $val $data(colGap) configure -background $val set data($opt) [$data(rowGap) cget -background] } -titlecolumns { # # Update the value of the -xscrollcommand option, save # the properly formatted value of val in data($opt), # and create or destroy the main separator if needed # set oldVal $data($opt) set val [format "%d" $val] ;# integer check with error msg if {$val < 0} { set val 0 } xviewSubCmd $win 0 set w $data(sep) if {$val == 0} { $data(hdrTxt) configure -xscrollcommand \ $data(-xscrollcommand) if {$oldVal > 0} { destroy $w } } else { $data(hdrTxt) configure -xscrollcommand "" if {$oldVal == 0} { if {$usingTile} { ttk::separator $w -style Sep$win.TSeparator \ -cursor $data(-cursor) \ -orient vertical -takefocus 0 } else { tk::frame $w -background $data(-foreground) \ -borderwidth 1 -container 0 \ -cursor $data(-cursor) \ -highlightthickness 0 \ -relief sunken -takefocus 0 \ -width 2 } bindtags $w [lreplace [bindtags $w] 1 1 \ $data(bodyTag) TablelistBody] } adjustSepsWhenIdle $win } set data($opt) $val xviewSubCmd $win 0 updateHScrlbarWhenIdle $win } -width { # # Adjust the widths of the body text widget, # header frame, and listbox child, and save the # properly formatted value of val in data($opt) # set val [format "%d" $val] ;# integer check with error msg $data(body) configure $opt $val if {$val <= 0} { $data(hdr) configure $opt $data(hdrPixels) $data(lb) configure $opt \ [expr {$data(hdrPixels) / $data(charWidth)}] } else { $data(hdr) configure $opt 0 $data(lb) configure $opt $val } set data($opt) $val } -xscrollcommand { # # Save val in data($opt), and apply it to the header text # widget if (and only if) no title columns are being used # set data($opt) $val if {$data(-titlecolumns) == 0} { $data(hdrTxt) configure $opt $val } else { $data(hdrTxt) configure $opt "" } } } } } } #------------------------------------------------------------------------------ # tablelist::doCget # # Returns the value of the configuration option opt for the tablelist widget # win. #------------------------------------------------------------------------------ proc tablelist::doCget {win opt} { upvar ::tablelist::ns${win}::data data return $data($opt) } #------------------------------------------------------------------------------ # tablelist::doColConfig # # Applies the value val of the column configuration option opt to the col'th # column of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::doColConfig {col win opt val} { variable canElide upvar ::tablelist::ns${win}::data data switch -- $opt { -align { # # Set up and adjust the columns, and make sure the # given column will be redisplayed at idle time # set idx [expr {3*$col + 2}] setupColumns $win [lreplace $data(-columns) $idx $idx $val] 0 adjustColumns $win {} 0 redisplayColWhenIdle $win $col } -background - -foreground { set w $data(body) set name $col$opt if {[info exists data($name)] && (!$data($col-hide) || $canElide)} { # # Remove the tag col$opt-$data($name) # from the elements of the given column # set tag col$opt-$data($name) for {set line 1} {$line <= $data(itemCount)} {incr line} { findTabs $win $line $col $col tabIdx1 tabIdx2 $w tag remove $tag $tabIdx1 $tabIdx2+1c } } if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) } } else { # # Configure the tag col$opt-$val in the body text widget # set tag col$opt-$val $w tag configure $tag $opt $val $w tag lower $tag if {!$data($col-hide) || $canElide} { # # Apply the tag to the elements of the given column # for {set line 1} {$line <= $data(itemCount)} {incr line} { findTabs $win $line $col $col tabIdx1 tabIdx2 if {[lsearch -exact [$w tag names $tabIdx1] select] < 0} { $w tag add $tag $tabIdx1 $tabIdx2+1c } } } # # Save val in data($name) # set data($name) $val } if {!$data(isDisabled)} { updateColorsWhenIdle $win } # # Rebuild the lists of the column fonts and tag names # makeColFontAndTagLists $win } -changesnipside - -wrap { # # Save the boolean value specified by val in data($col$opt) and # make sure the given column will be redisplayed at idle time # set data($col$opt) [expr {$val ? 1 : 0}] if {[lindex $data(-columns) [expr {3*$col}]] != 0} { redisplayColWhenIdle $win $col } } -editable - -resizable { # # Save the boolean value specified by val in data($col$opt) # set data($col$opt) [expr {$val ? 1 : 0}] } -editwindow { variable editWin if {[info exists editWin($val-creationCmd)]} { set data($col$opt) $val } else { return -code error "name \"$val\" is not registered\ for interactive cell editing" } } -font { set w $data(body) set name $col$opt if {[info exists data($name)] && (!$data($col-hide) || $canElide)} { # # Remove the tag col$opt-$data($name) # from the elements of the given column # set tag col$opt-$data($name) for {set line 1} {$line <= $data(itemCount)} {incr line} { findTabs $win $line $col $col tabIdx1 tabIdx2 $w tag remove $tag $tabIdx1 $tabIdx2+1c } } if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) } } else { # # Configure the tag col$opt-$val in the body text widget # set tag col$opt-$val $w tag configure $tag $opt $val $w tag lower $tag if {!$data($col-hide) || $canElide} { # # Apply the tag to the elements of the given column # for {set line 1} {$line <= $data(itemCount)} {incr line} { findTabs $win $line $col $col tabIdx1 tabIdx2 $w tag add $tag $tabIdx1 $tabIdx2+1c } } # # Save val in data($name) # set data($name) $val } # # Rebuild the lists of the column fonts and tag names # makeColFontAndTagLists $win # # Adjust the columns, and make sure the specified # column will be redisplayed at idle time # adjustColumns $win $col 1 redisplayColWhenIdle $win $col adjustElidedTextWhenIdle $win if {$col == $data(editCol)} { # # Configure the edit window # setEditWinFont $win } } -formatcommand { if {[string compare $val ""] == 0} { if {[info exists data($col$opt)]} { unset data($col$opt) } set fmtCmdFlag 0 } else { set data($col$opt) $val set fmtCmdFlag 1 } # # Update the corresponding element of the list data(fmtCmdFlagList) # set data(fmtCmdFlagList) \ [lreplace $data(fmtCmdFlagList) $col $col $fmtCmdFlag] set data(hasFmtCmds) \ [expr {[lsearch -exact $data(fmtCmdFlagList) 1] >= 0}] # # Adjust the columns and make sure the specified # column will be redisplayed at idle time # adjustColumns $win $col 1 redisplayColWhenIdle $win $col } -hide { # # Save the boolean value specified by val in data($col$opt), # adjust the columns, and redisplay the items # set oldVal $data($col$opt) set newVal [expr {$val ? 1 : 0}] if {$newVal != $oldVal} { if {!$canElide} { set selCells [curCellSelection $win] } elseif {$newVal} { cellSelection $win clear 0 $col $data(lastRow) $col } set data($col$opt) $newVal if {$newVal} { ;# hiding the column incr data(hiddenColCount) adjustColIndex $win data(anchorCol) 1 adjustColIndex $win data(activeCol) 1 if {$col == $data(editCol)} { doCancelEditing $win } } else { incr data(hiddenColCount) -1 } makeColFontAndTagLists $win adjustColumns $win $col 1 if {$canElide} { adjustElidedTextWhenIdle $win } else { redisplay $win 0 $selCells } if {!$newVal && [string compare $data(-selecttype) "row"] == 0} { foreach row [curSelection $win] { rowSelection $win set $row $row } } } } -labelalign { if {[string compare $val ""] == 0} { # # Unset data($col$opt) # set alignment [lindex $data(colList) [expr {2*$col + 1}]] if {[info exists data($col$opt)]} { unset data($col$opt) } } else { # # Save the properly formatted value of val in data($col$opt) # variable alignments set val [mwutil::fullOpt "label alignment" $val $alignments] set alignment $val set data($col$opt) $val } # # Adjust the col'th label # set pixels [lindex $data(colList) [expr {2*$col}]] if {$pixels == 0} { ;# convention: dynamic width if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } } if {$pixels != 0} { incr pixels $data($col-delta) } adjustLabel $win $col $pixels $alignment } -labelbackground - -labelforeground { set w $data(hdrTxtFrLbl)$col set optTail [string range $opt 6 end] ;# remove the -label if {[string compare $val ""] == 0} { # # Apply the value of the corresponding widget # configuration option to the col'th label and # its sublabels (if any), and unset data($col$opt) # configLabel $w -$optTail $data($opt) if {[info exists data($col$opt)]} { unset data($col$opt) } } else { # # Apply the given value to the col'th label and # its sublabels (if any), and save the properly # formatted value of val in data($col$opt) # configLabel $w -$optTail $val set data($col$opt) [$w cget -$optTail] } if {[lsearch -exact $data(arrowColList) $col] >= 0} { configCanvas $win $col } } -labelborderwidth { set w $data(hdrTxtFrLbl)$col set optTail [string range $opt 6 end] ;# remove the -label if {[string compare $val ""] == 0} { # # Apply the value of the corresponding widget configuration # option to the col'th label and unset data($col$opt) # configLabel $w -$optTail $data($opt) if {[info exists data($col$opt)]} { unset data($col$opt) } } else { # # Apply the given value to the col'th label and save the # properly formatted value of val in data($col$opt) # configLabel $w -$optTail $val set data($col$opt) [$w cget -$optTail] } # # Adjust the columns (including the height of the header frame) # adjustColumns $win l$col 1 } -labelcommand - -labelcommand2 - -name - -sortcommand { if {[string compare $val ""] == 0} { if {[info exists data($col$opt)]} { unset data($col$opt) } } else { set data($col$opt) $val } } -labelfont { set w $data(hdrTxtFrLbl)$col set optTail [string range $opt 6 end] ;# remove the -label if {[string compare $val ""] == 0} { # # Apply the value of the corresponding widget # configuration option to the col'th label and # its sublabels (if any), and unset data($col$opt) # configLabel $w -$optTail $data($opt) if {[info exists data($col$opt)]} { unset data($col$opt) } } else { # # Apply the given value to the col'th label and # its sublabels (if any), and save the properly # formatted value of val in data($col$opt) # configLabel $w -$optTail $val set data($col$opt) [$w cget -$optTail] } # # Adjust the columns (including the height of the header frame) # adjustColumns $win l$col 1 } -labelheight - -labelpady { set w $data(hdrTxtFrLbl)$col set optTail [string range $opt 6 end] ;# remove the -label if {[string compare $val ""] == 0} { # # Apply the value of the corresponding widget configuration # option to the col'th label and unset data($col$opt) # configLabel $w -$optTail $data($opt) if {[info exists data($col$opt)]} { unset data($col$opt) } } else { # # Apply the given value to the col'th label and save the # properly formatted value of val in data($col$opt) # configLabel $w -$optTail $val variable usingTile if {$usingTile} { set data($col$opt) $val } else { set data($col$opt) [$w cget -$optTail] } } # # Adjust the height of the header frame # adjustHeaderHeight $win } -labelimage { set w $data(hdrTxtFrLbl)$col if {[string compare $val ""] == 0} { foreach l [getSublabels $w] { destroy $l } if {[info exists data($col$opt)]} { unset data($col$opt) } } else { if {![winfo exists $w-il]} { variable configSpecs variable configOpts foreach l [list $w-il $w-tl] { ;# image and text labels # # Create the label $l # tk::label $l -borderwidth 0 -height 0 \ -highlightthickness 0 -padx 0 \ -pady 0 -takefocus 0 -width 0 # # Apply to it the current configuration options # foreach opt2 $configOpts { if {[string compare \ [lindex $configSpecs($opt2) 2] "c"] == 0} { $l configure $opt2 $data($opt2) } } foreach opt2 {-background -foreground -font} { $l configure $opt2 [$w cget $opt2] } foreach opt2 {-activebackground -activeforeground -disabledforeground -state} { catch {$l configure $opt2 [$w cget $opt2]} } # # Replace the binding tag Label with # $w and TablelistSubLabel in the # list of binding tags of the label $l # bindtags $l [lreplace [bindtags $l] 1 1 \ $w TablelistSubLabel] } } # # Display the specified image in the label # $w-il and save val in data($col$opt) # $w-il configure -image $val set data($col$opt) $val } # # Adjust the columns (including the height of the header frame) # adjustColumns $win l$col 1 } -labelrelief { set w $data(hdrTxtFrLbl)$col set optTail [string range $opt 6 end] ;# remove the -label if {[string compare $val ""] == 0} { # # Apply the value of the corresponding widget configuration # option to the col'th label and unset data($col$opt) # configLabel $w -$optTail $data($opt) if {[info exists data($col$opt)]} { unset data($col$opt) } } else { # # Apply the given value to the col'th label and save the # properly formatted value of val in data($col$opt) # configLabel $w -$optTail $val set data($col$opt) [$w cget -$optTail] } } -maxwidth { # # Save the properly formatted value of val in # data($col$opt), adjust the columns, and make sure # the specified column will be redisplayed at idle time # set val [format "%d" $val] ;# integer check with error message set data($col$opt) $val if {$val > 0} { ;# convention: max. width in characters set pixels [charsToPixels $win $data(-font) $val] } elseif {$val < 0} { ;# convention: max. width in pixels set pixels [expr {(-1)*$val}] } else { ;# convention: no max. width set pixels 0 } set data($col-maxPixels) $pixels adjustColumns $win $col 1 redisplayColWhenIdle $win $col } -selectbackground - -selectforeground { set w $data(body) set name $col$opt if {[info exists data($name)] && (!$data($col-hide) || $canElide)} { # # Remove the tag col$opt-$data($name) # from the elements of the given column # set tag col$opt-$data($name) for {set line 1} {$line <= $data(itemCount)} {incr line} { findTabs $win $line $col $col tabIdx1 tabIdx2 $w tag remove $tag $tabIdx1 $tabIdx2+1c } } if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) } } else { # # Configure the tag col$opt-$val in the body text widget # set tag col$opt-$val set optTail [string range $opt 7 end] ;# remove the -select $w tag configure $tag -$optTail $val $w tag raise $tag select if {!$data($col-hide) || $canElide} { # # Apply the tag to the selected elements of the given column # set selRange [$w tag nextrange select 1.0] while {[llength $selRange] != 0} { set selStart [lindex $selRange 0] set line [expr {int($selStart)}] findTabs $win $line $col $col tabIdx1 tabIdx2 if {[lsearch -exact [$w tag names $tabIdx1] select] >= 0} { $w tag add $tag $tabIdx1 $tabIdx2+1c } set selRange \ [$w tag nextrange select "$selStart lineend"] } } # # Save val in data($name) # set data($name) $val } if {!$data(isDisabled)} { updateColorsWhenIdle $win } } -showarrow { # # Save the boolean value specified by val in data($col$opt) and # manage or unmanage the canvas displaying an up- or down-arrow # set data($col$opt) [expr {$val ? 1 : 0}] makeSortAndArrowColLists $win adjustColumns $win l$col 1 } -showlinenumbers { # # Save the boolean value specified by val in # data($col$opt), and make sure the line numbers # will be redisplayed at idle time if needed # set val [expr {$val ? 1 : 0}] if {!$data($col$opt) && $val} { showLineNumbersWhenIdle $win } set data($col$opt) $val } -sortmode { # # Save the properly formatted value of val in data($col$opt) # variable sortModes set data($col$opt) [mwutil::fullOpt "sort mode" $val $sortModes] } -stretchable { set flag [expr {$val ? 1 : 0}] if {$flag} { if {[string compare $data(-stretch) "all"] != 0 && [lsearch -exact $data(-stretch) $col] < 0} { # # col was not found in data(-stretch): add it to the list # lappend data(-stretch) $col sortStretchableColList $win set data(forceAdjust) 1 stretchColumnsWhenIdle $win } } elseif {[string compare $data(-stretch) "all"] == 0} { # # Replace the value "all" of data(-stretch) with # the list of all column indices different from col # set data(-stretch) {} for {set n 0} {$n < $data(colCount)} {incr n} { if {$n != $col} { lappend data(-stretch) $n } } set data(forceAdjust) 1 stretchColumnsWhenIdle $win } else { # # If col is contained in data(-stretch) # then remove it from the list # if {[set n [lsearch -exact $data(-stretch) $col]] >= 0} { set data(-stretch) [lreplace $data(-stretch) $n $n] set data(forceAdjust) 1 stretchColumnsWhenIdle $win } # # If col indicates the last column and data(-stretch) # contains "end" then remove "end" from the list # if {$col == $data(lastCol) && [string compare [lindex $data(-stretch) end] "end"] == 0} { set data(-stretch) [lreplace $data(-stretch) end end] set data(forceAdjust) 1 stretchColumnsWhenIdle $win } } } -text { if {$data(isDisabled)} { return "" } # # Replace the column's contents in the internal list # set newItemList {} set row 0 foreach item $data(itemList) text [lrange $val 0 $data(itemCount)] { set item [lreplace $item $col $col $text] lappend newItemList $item } set data(itemList) $newItemList # # Update the list variable if present # condUpdateListVar $win # # Adjust the columns and make sure the specified # column will be redisplayed at idle time # adjustColumns $win $col 1 redisplayColWhenIdle $win $col } -title { # # Save the given value in the corresponding # element of data(-columns) and adjust the columns # set idx [expr {3*$col + 1}] set data(-columns) [lreplace $data(-columns) $idx $idx $val] adjustColumns $win l$col 1 } -width { # # Set up and adjust the columns, and make sure the # given column will be redisplayed at idle time # set idx [expr {3*$col}] if {$val != [lindex $data(-columns) $idx]} { setupColumns $win [lreplace $data(-columns) $idx $idx $val] 0 redisplayColWhenIdle $win $col ;# here before adjustColumns! adjustColumns $win $col 1 } } } } #------------------------------------------------------------------------------ # tablelist::doColCget # # Returns the value of the column configuration option opt for the col'th # column of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::doColCget {col win opt} { upvar ::tablelist::ns${win}::data data switch -- $opt { -align { return [lindex $data(-columns) [expr {3*$col + 2}]] } -stretchable { return [expr { [string compare $data(-stretch) "all"] == 0 || [lsearch -exact $data(-stretch) $col] >= 0 || ($col == $data(lastCol) && \ [string compare [lindex $data(-stretch) end] "end"] == 0) }] } -text { set result {} foreach item $data(itemList) { lappend result [lindex $item $col] } return $result } -title { return [lindex $data(-columns) [expr {3*$col + 1}]] } -width { return [lindex $data(-columns) [expr {3*$col}]] } default { if {[info exists data($col$opt)]} { return $data($col$opt) } else { return "" } } } } #------------------------------------------------------------------------------ # tablelist::doRowConfig # # Applies the value val of the row configuration option opt to the row'th row # of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::doRowConfig {row win opt val} { variable canElide variable elide variable snipSides upvar ::tablelist::ns${win}::data data set w $data(body) switch -- $opt { -background - -foreground { set key [lindex [lindex $data(itemList) $row] end] set name $key$opt if {[info exists data($name)]} { # # Remove the tag row$opt-$data($name) from the given row # set line [expr {$row + 1}] $w tag remove row$opt-$data($name) $line.0 $line.end } if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) incr data(rowTagRefCount) -1 } } else { # # Configure the tag row$opt-$val in the body text widget and # apply it to the non-selected elements of the given row # set tag row$opt-$val $w tag configure $tag $opt $val $w tag lower $tag active set line [expr {$row + 1}] if {[llength [$w tag nextrange select $line.0 $line.end]] == 0} { $w tag add $tag $line.0 $line.end } else { set textIdx1 [expr {double($line)}] for {set col 0} {$col < $data(colCount)} {incr col} { if {$data($col-hide) && !$canElide} { continue } set textIdx2 \ [$w search $elide "\t" $textIdx1+1c $line.end]+1c if {[lsearch -exact [$w tag names $textIdx1] select] < 0} { $w tag add $tag $textIdx1 $textIdx2 } set textIdx1 $textIdx2 } } # # Save val in data($name) # if {![info exists data($name)]} { incr data(rowTagRefCount) } set data($name) $val } if {!$data(isDisabled)} { updateColorsWhenIdle $win } } -font { # # Save the current cell fonts in a temporary array # set item [lindex $data(itemList) $row] set key [lindex $item end] for {set col 0} {$col < $data(colCount)} {incr col} { set oldCellFonts($col) [getCellFont $win $key $col] } set name $key$opt if {[info exists data($name)]} { # # Remove the tag row$opt-$data($name) from the given row # set line [expr {$row + 1}] $w tag remove row$opt-$data($name) $line.0 $line.end } if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) incr data(rowTagRefCount) -1 } } else { # # Configure the tag row$opt-$val in the body # text widget and apply it to the given row # set tag row$opt-$val $w tag configure $tag $opt $val $w tag lower $tag active set line [expr {$row + 1}] $w tag add $tag $line.0 $line.end # # Save val in data($name) # if {![info exists data($name)]} { incr data(rowTagRefCount) } set data($name) $val } set displayedItem [lrange $item 0 $data(lastCol)] if {$data(hasFmtCmds)} { set displayedItem [formatItem $win $key $row $displayedItem] } set colWidthsChanged 0 set colIdxList {} set line [expr {$row + 1}] set textIdx1 $line.1 set col 0 foreach text [strToDispStr $displayedItem] \ {pixels alignment} $data(colList) { if {$data($col-hide) && !$canElide} { incr col continue } # # Adjust the cell text and the image or window width # set multiline [string match "*\n*" $text] set cellFont [getCellFont $win $key $col] set workPixels $pixels if {$pixels == 0} { ;# convention: dynamic width set textSav $text getAuxData $win $key $col auxType auxWidthSav if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set workPixels $data($col-maxPixels) } } } set aux [getAuxData $win $key $col auxType auxWidth $workPixels] set maxTextWidth $workPixels if {$workPixels != 0} { incr workPixels $data($col-delta) set maxTextWidth [getMaxTextWidth $workPixels $auxWidth] if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $maxTextWidth} { set multiline 1 } } } set snipSide $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } adjustMlElem $win list auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) set msgScript [list ::tablelist::displayText $win $key \ $col [join $list "\n"] $cellFont \ $maxTextWidth $alignment] } else { adjustElem $win text auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) } if {$row == $data(editRow) && $col == $data(editCol)} { # # Configure the edit window # setEditWinFont $win } else { # # Update the text widget's contents between the two tabs # set textIdx2 [$w search $elide "\t" $textIdx1 $line.end] if {$multiline} { updateMlCell $w $textIdx1 $textIdx2 $msgScript \ $aux $auxType $auxWidth $alignment } else { updateCell $w $textIdx1 $textIdx2 $text \ $aux $auxType $auxWidth $alignment } } if {$pixels == 0} { ;# convention: dynamic width # # Check whether the width of the current column has changed # set text $textSav set auxWidth $auxWidthSav set newElemWidth \ [getElemWidth $win $text $auxWidth $cellFont] if {$newElemWidth > $data($col-elemWidth)} { set data($col-elemWidth) $newElemWidth set data($col-widestCount) 1 if {$newElemWidth > $data($col-reqPixels)} { set data($col-reqPixels) $newElemWidth set colWidthsChanged 1 } } else { set oldElemWidth [getElemWidth $win $text \ $auxWidth $oldCellFonts($col)] if {$oldElemWidth < $data($col-elemWidth) && $newElemWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$oldElemWidth == $data($col-elemWidth) && $newElemWidth < $oldElemWidth && [incr data($col-widestCount) -1] == 0} { set colWidthsChanged 1 lappend colIdxList $col } } } set textIdx1 [$w search $elide "\t" $textIdx1 $line.end]+2c incr col } # # Adjust the columns if necessary and schedule # some operations for execution at idle time # if {$colWidthsChanged} { adjustColumns $win $colIdxList 1 } adjustElidedTextWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win } -hide { set val [expr {$val ? 1 : 0}] set item [lindex $data(itemList) $row] set key [lindex $item end] set name $key$opt set line [expr {$row + 1}] set viewChanged 0 if {$val} { ;# hiding the row if {![info exists data($name)]} { rowSelection $win clear $row $row set data($name) 1 incr data(hiddenRowCount) $w tag add hiddenRow $line.0 $line.end+1c set viewChanged 1 adjustRowIndex $win data(anchorRow) 1 adjustRowIndex $win data(activeRow) 1 if {$row == $data(editRow)} { doCancelEditing $win } } } else { ;# unhiding the row if {[info exists data($name)]} { unset data($name) incr data(hiddenRowCount) -1 $w tag remove hiddenRow $line.0 $line.end+1c set viewChanged 1 } } if {$viewChanged} { # # Adjust the heights of the body text widget # and of the listbox child, if necessary # if {$data(-height) <= 0} { set nonHiddenRowCount \ [expr {$data(itemCount) - $data(hiddenRowCount)}] $w configure -height $nonHiddenRowCount $data(lb) configure -height $nonHiddenRowCount } # # Build the list of those dynamic-width columns # whose widths are affected by (un)hiding the row # set colWidthsChanged 0 set colIdxList {} set displayedItem [lrange $item 0 $data(lastCol)] if {$data(hasFmtCmds)} { set displayedItem [formatItem $win $key $row $displayedItem] } set col 0 foreach text [strToDispStr $displayedItem] \ {pixels alignment} $data(colList) { if {($data($col-hide) && !$canElide) || $pixels != 0} { incr col continue } getAuxData $win $key $col auxType auxWidth set cellFont [getCellFont $win $key $col] set elemWidth [getElemWidth $win $text $auxWidth $cellFont] if {$val} { ;# hiding the row if {$elemWidth == $data($col-elemWidth) && [incr data($col-widestCount) -1] == 0} { set colWidthsChanged 1 lappend colIdxList $col } } else { ;# unhiding the row if {$elemWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$elemWidth > $data($col-elemWidth)} { set data($col-elemWidth) $elemWidth set data($col-widestCount) 1 if {$elemWidth > $data($col-reqPixels)} { set data($col-reqPixels) $elemWidth set colWidthsChanged 1 } } } incr col } # # Invalidate the list of the row indices indicating the # non-hidden rows, adjust the columns if necessary, and # schedule some operations for execution at idle time # set data(nonHiddenRowList) {-1} if {$colWidthsChanged} { adjustColumns $win $colIdxList 1 } adjustElidedTextWhenIdle $win makeStripesWhenIdle $win adjustSepsWhenIdle $win updateVScrlbarWhenIdle $win showLineNumbersWhenIdle $win } } -name { set key [lindex [lindex $data(itemList) $row] end] if {[string compare $val ""] == 0} { if {[info exists data($key$opt)]} { unset data($key$opt) } } else { set data($key$opt) $val } } -selectable { set val [expr {$val ? 1 : 0}] set key [lindex [lindex $data(itemList) $row] end] if {$val} { if {[info exists data($key$opt)]} { unset data($key$opt) } } else { # # Set data($key$opt) to 0 and deselect the row # set data($key$opt) 0 rowSelection $win clear $row $row } } -selectbackground - -selectforeground { set key [lindex [lindex $data(itemList) $row] end] set name $key$opt if {[info exists data($name)]} { # # Remove the tag row$opt-$data($name) from the given row # set line [expr {$row + 1}] $w tag remove row$opt-$data($name) $line.0 $line.end } if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) } } else { # # Configure the tag row$opt-$val in the body text widget # and apply it to the selected elements of the given row # set tag row$opt-$val set optTail [string range $opt 7 end] ;# remove the -select $w tag configure $tag -$optTail $val $w tag lower $tag active set line [expr {$row + 1}] set selRange [$w tag nextrange select $line.0 $line.end] while {[llength $selRange] != 0} { foreach {selStart selEnd} $selRange {} $w tag add $tag $selStart $selEnd set selRange [$w tag nextrange select $selEnd $line.end] } # # Save val in data($name) # set data($name) [$w tag cget $tag -$optTail] } if {!$data(isDisabled)} { updateColorsWhenIdle $win } } -text { if {$data(isDisabled)} { return "" } set colWidthsChanged 0 set colIdxList {} set oldItem [lindex $data(itemList) $row] set key [lindex $oldItem end] set newItem [adjustItem $val $data(colCount)] if {$data(hasFmtCmds)} { set displayedItem [formatItem $win $key $row $newItem] } else { set displayedItem $newItem } set line [expr {$row + 1}] set textIdx1 $line.1 set col 0 foreach text [strToDispStr $displayedItem] \ {pixels alignment} $data(colList) { if {$data($col-hide) && !$canElide} { incr col continue } # # Adjust the cell text and the image or window width # set multiline [string match "*\n*" $text] set cellFont [getCellFont $win $key $col] set workPixels $pixels if {$pixels == 0} { ;# convention: dynamic width set textSav $text getAuxData $win $key $col auxType auxWidthSav if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set workPixels $data($col-maxPixels) } } } set aux [getAuxData $win $key $col auxType auxWidth $workPixels] set maxTextWidth $workPixels if {$workPixels != 0} { incr workPixels $data($col-delta) set maxTextWidth [getMaxTextWidth $workPixels $auxWidth] if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $maxTextWidth} { set multiline 1 } } } set snipSide $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } adjustMlElem $win list auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) set msgScript [list ::tablelist::displayText $win $key \ $col [join $list "\n"] $cellFont \ $maxTextWidth $alignment] } else { adjustElem $win text auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) } if {$row != $data(editRow) || $col != $data(editCol)} { # # Update the text widget's contents between the two tabs # set textIdx2 [$w search $elide "\t" $textIdx1 $line.end] if {$multiline} { updateMlCell $w $textIdx1 $textIdx2 $msgScript \ $aux $auxType $auxWidth $alignment } else { updateCell $w $textIdx1 $textIdx2 $text \ $aux $auxType $auxWidth $alignment } } if {$pixels == 0} { ;# convention: dynamic width # # Check whether the width of the current column has changed # set text $textSav set auxWidth $auxWidthSav set newElemWidth \ [getElemWidth $win $text $auxWidth $cellFont] if {$newElemWidth > $data($col-elemWidth)} { set data($col-elemWidth) $newElemWidth set data($col-widestCount) 1 if {$newElemWidth > $data($col-reqPixels)} { set data($col-reqPixels) $newElemWidth set colWidthsChanged 1 } } else { set oldText [lindex $oldItem $col] if {[lindex $data(fmtCmdFlagList) $col]} { set oldText \ [formatElem $win $key $row $col $oldText] } set oldText [strToDispStr $oldText] set oldElemWidth \ [getElemWidth $win $oldText $auxWidth $cellFont] if {$oldElemWidth < $data($col-elemWidth) && $newElemWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$oldElemWidth == $data($col-elemWidth) && $newElemWidth < $oldElemWidth && [incr data($col-widestCount) -1] == 0} { set colWidthsChanged 1 lappend colIdxList $col } } } set textIdx1 [$w search $elide "\t" $textIdx1 $line.end]+2c incr col } # # Replace the row contents in the list variable if present # if {$data(hasListVar)} { upvar #0 $data(-listvariable) var trace vdelete var wu $data(listVarTraceCmd) set var [lreplace $var $row $row $newItem] trace variable var wu $data(listVarTraceCmd) } # # Replace the row contents in the internal list # lappend newItem [lindex $oldItem end] set data(itemList) [lreplace $data(itemList) $row $row $newItem] # # Adjust the columns if necessary and schedule # some operations for execution at idle time # if {$colWidthsChanged} { adjustColumns $win $colIdxList 1 } adjustElidedTextWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win showLineNumbersWhenIdle $win } } } #------------------------------------------------------------------------------ # tablelist::doRowCget # # Returns the value of the row configuration option opt for the row'th row of # the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::doRowCget {row win opt} { upvar ::tablelist::ns${win}::data data # # Return the value of the specified row configuration option # set item [lindex $data(itemList) $row] switch -- $opt { -text { return [lrange $item 0 $data(lastCol)] } -hide { set key [lindex $item end] if {[info exists data($key$opt)]} { return $data($key$opt) } else { return 0 } } -selectable { set key [lindex $item end] if {[info exists data($key$opt)]} { return $data($key$opt) } else { return 1 } } default { set key [lindex $item end] if {[info exists data($key$opt)]} { return $data($key$opt) } else { return "" } } } } #------------------------------------------------------------------------------ # tablelist::doCellConfig # # Applies the value val of the cell configuration option opt to the cell # row,col of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::doCellConfig {row col win opt val} { variable canElide variable snipSides upvar ::tablelist::ns${win}::data data set w $data(body) switch -- $opt { -background - -foreground { set key [lindex [lindex $data(itemList) $row] end] set name $key,$col$opt if {[info exists data($name)] && (!$data($col-hide) || $canElide)} { # # Remove the tag cell$opt-$data($name) from the given cell # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 $w tag remove cell$opt-$data($name) $tabIdx1 $tabIdx2+1c } if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) incr data(cellTagRefCount) -1 } } else { # # Configure the tag cell$opt-$val in the body text widget # set tag cell$opt-$val $w tag configure $tag $opt $val $w tag lower $tag disabled if {!$data($col-hide) || $canElide} { # # Apply the tag to the given cell if it is not selected # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 if {[lsearch -exact [$w tag names $tabIdx1] select] < 0} { $w tag add $tag $tabIdx1 $tabIdx2+1c } } # # Save val in data($name) # if {![info exists data($name)]} { incr data(cellTagRefCount) } set data($name) $val } if {!$data(isDisabled)} { updateColorsWhenIdle $win } } -editable { # # Save the boolean value specified by val in data($key,$col$opt) # set key [lindex [lindex $data(itemList) $row] end] set data($key,$col$opt) [expr {$val ? 1 : 0}] } -editwindow { variable editWin if {[info exists editWin($val-creationCmd)]} { set key [lindex [lindex $data(itemList) $row] end] set data($key,$col$opt) $val } else { return -code error "name \"$val\" is not registered\ for interactive cell editing" } } -font { # # Save the current cell font # set item [lindex $data(itemList) $row] set key [lindex $item end] set name $key,$col$opt set oldCellFont [getCellFont $win $key $col] if {[info exists data($name)] && (!$data($col-hide) || $canElide)} { # # Remove the tag cell$opt-$data($name) from the given cell # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 $w tag remove cell$opt-$data($name) $tabIdx1 $tabIdx2+1c } if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) incr data(cellTagRefCount) -1 } } else { # # Configure the tag cell$opt-$val in the body text widget # set tag cell$opt-$val $w tag configure $tag $opt $val $w tag lower $tag disabled if {!$data($col-hide) || $canElide} { # # Apply the tag to the given cell # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 $w tag add $tag $tabIdx1 $tabIdx2+1c } # # Save val in data($name) # if {![info exists data($name)]} { incr data(cellTagRefCount) } set data($name) $val } # # Adjust the cell text and the image or window width # set text [lindex $item $col] if {[lindex $data(fmtCmdFlagList) $col]} { set text [formatElem $win $key $row $col $text] } set text [strToDispStr $text] set multiline [string match "*\n*" $text] set cellFont [getCellFont $win $key $col] set pixels [lindex $data(colList) [expr {2*$col}]] set workPixels $pixels if {$pixels == 0} { ;# convention: dynamic width set textSav $text getAuxData $win $key $col auxType auxWidthSav if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set workPixels $data($col-maxPixels) } } } set aux [getAuxData $win $key $col auxType auxWidth $workPixels] set maxTextWidth $workPixels if {$workPixels != 0} { incr workPixels $data($col-delta) set maxTextWidth [getMaxTextWidth $workPixels $auxWidth] if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $maxTextWidth} { set multiline 1 } } } set alignment [lindex $data(colList) [expr {2*$col + 1}]] set snipSide $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } adjustMlElem $win list auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) set msgScript [list ::tablelist::displayText $win $key \ $col [join $list "\n"] $cellFont \ $maxTextWidth $alignment] } else { adjustElem $win text auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) } if {!$data($col-hide)} { if {$row == $data(editRow) && $col == $data(editCol)} { # # Configure the edit window # setEditWinFont $win } else { # # Update the text widget's contents between the two tabs # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 if {$multiline} { updateMlCell $w $tabIdx1+1c $tabIdx2 $msgScript \ $aux $auxType $auxWidth $alignment } else { updateCell $w $tabIdx1+1c $tabIdx2 $text \ $aux $auxType $auxWidth $alignment } } } # # Adjust the columns if necessary # if {$pixels == 0} { ;# convention: dynamic width set text $textSav set auxWidth $auxWidthSav set newElemWidth [getElemWidth $win $text $auxWidth $cellFont] if {$newElemWidth > $data($col-elemWidth)} { set data($col-elemWidth) $newElemWidth set data($col-widestCount) 1 if {$newElemWidth > $data($col-reqPixels)} { set data($col-reqPixels) $newElemWidth adjustColumns $win {} 1 } } else { set oldElemWidth \ [getElemWidth $win $text $auxWidth $oldCellFont] if {$oldElemWidth < $data($col-elemWidth) && $newElemWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$oldElemWidth == $data($col-elemWidth) && $newElemWidth < $oldElemWidth && [incr data($col-widestCount) -1] == 0} { adjustColumns $win $col 1 } } } adjustElidedTextWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win } -image { if {$data(isDisabled)} { return "" } # # Save the old image or window width # set item [lindex $data(itemList) $row] set key [lindex $item end] set name $key,$col$opt getAuxData $win $key $col oldAuxType oldAuxWidth # # Delete data($name) or save the specified value in it # if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) incr data(imgCount) -1 } } else { if {![info exists data($name)]} { incr data(imgCount) } set imgLabel $w.l$key,$col set existsImgLabel [winfo exists $imgLabel] if {$existsImgLabel && [info exists data($name)] && [string compare $val $data($name)] == 0} { set keepAux 1 } else { set keepAux 0 if {$existsImgLabel} { destroy $imgLabel } } set data($name) $val } # # Adjust the cell text and the image or window width # set pixels [lindex $data(colList) [expr {2*$col}]] set workPixels $pixels set text [lindex $item $col] if {[lindex $data(fmtCmdFlagList) $col]} { set text [formatElem $win $key $row $col $text] } set text [strToDispStr $text] set oldText $text set multiline [string match "*\n*" $text] set cellFont [getCellFont $win $key $col] if {$pixels == 0} { ;# convention: dynamic width set textSav $text getAuxData $win $key $col auxType auxWidthSav if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set workPixels $data($col-maxPixels) } } } set aux [getAuxData $win $key $col auxType auxWidth $workPixels] set maxTextWidth $workPixels if {$workPixels != 0} { incr workPixels $data($col-delta) set maxTextWidth [getMaxTextWidth $workPixels $auxWidth] if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $maxTextWidth} { set multiline 1 } } } set alignment [lindex $data(colList) [expr {2*$col + 1}]] set snipSide $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } adjustMlElem $win list auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) set msgScript [list ::tablelist::displayText $win $key \ $col [join $list "\n"] $cellFont \ $maxTextWidth $alignment] } else { adjustElem $win text auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) } if {(!$data($col-hide) || $canElide) && !($row == $data(editRow) && $col == $data(editCol))} { # # Delete the old cell contents between the two tabs, # and insert the text and the auxiliary object # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 if {$auxType != 1 || $keepAux} { if {$multiline} { updateMlCell $w $tabIdx1+1c $tabIdx2 $msgScript \ $aux $auxType $auxWidth $alignment } else { updateCell $w $tabIdx1+1c $tabIdx2 $text \ $aux $auxType $auxWidth $alignment } } else { set aux [lreplace $aux end end $auxWidth] $w delete $tabIdx1+1c $tabIdx2 if {$multiline} { insertMlElem $w $tabIdx1+1c $msgScript \ $aux $auxType $alignment } else { insertElem $w $tabIdx1+1c $text $aux $auxType $alignment } } } # # Adjust the columns if necessary # if {$pixels == 0} { ;# convention: dynamic width set text $textSav set auxWidth $auxWidthSav set newElemWidth [getElemWidth $win $text $auxWidth $cellFont] if {$newElemWidth > $data($col-elemWidth)} { set data($col-elemWidth) $newElemWidth set data($col-widestCount) 1 if {$newElemWidth > $data($col-reqPixels)} { set data($col-reqPixels) $newElemWidth adjustColumns $win {} 1 } } else { set oldElemWidth \ [getElemWidth $win $oldText $oldAuxWidth $cellFont] if {$oldElemWidth < $data($col-elemWidth) && $newElemWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$oldElemWidth == $data($col-elemWidth) && $newElemWidth < $oldElemWidth && [incr data($col-widestCount) -1] == 0} { adjustColumns $win $col 1 } } } adjustElidedTextWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win } -selectbackground - -selectforeground { set key [lindex [lindex $data(itemList) $row] end] set name $key,$col$opt if {[info exists data($name)] && (!$data($col-hide) || $canElide)} { # # Remove the tag cell$opt-$data($name) from the given cell # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 $w tag remove cell$opt-$data($name) $tabIdx1 $tabIdx2+1c } if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) } } else { # # Configure the tag cell$opt-$val in the body text widget # set tag cell$opt-$val set optTail [string range $opt 7 end] ;# remove the -select $w tag configure $tag -$optTail $val $w tag lower $tag disabled if {!$data($col-hide) || $canElide} { # # Apply the tag to the given cell if it is selected # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 if {[lsearch -exact [$w tag names $tabIdx1] select] >= 0} { $w tag add $tag $tabIdx1 $tabIdx2+1c } } # # Save val in data($name) # set data($name) $val } if {!$data(isDisabled)} { updateColorsWhenIdle $win } } -stretchwindow { # # Save the boolean value specified by val in data($key,$col$opt) # set item [lindex $data(itemList) $row] set key [lindex $item end] set name $key,$col$opt if {$val} { set data($name) 1 } elseif {[info exists data($name)]} { unset data($name) } if {($data($col-hide) && !$canElide) || ($row == $data(editRow) && $col == $data(editCol))} { return "" } set pixels [lindex $data(colList) [expr {2*$col}]] set text [lindex $item $col] if {[lindex $data(fmtCmdFlagList) $col]} { set text [formatElem $win $key $row $col $text] } set text [strToDispStr $text] set multiline [string match "*\n*" $text] set cellFont [getCellFont $win $key $col] if {$pixels == 0} { ;# convention: dynamic width if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } } set aux [getAuxData $win $key $col auxType auxWidth $pixels] set maxTextWidth $pixels if {$pixels != 0} { incr pixels $data($col-delta) set maxTextWidth [getMaxTextWidth $pixels $auxWidth] if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $maxTextWidth} { set multiline 1 } } } if {$auxType < 2} { ;# no window return "" } # # Adjust the cell text and the window width # set alignment [lindex $data(colList) [expr {2*$col + 1}]] set snipSide $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } adjustMlElem $win list auxWidth $cellFont $pixels \ $snipSide $data(-snipstring) set msgScript [list ::tablelist::displayText $win $key $col \ [join $list "\n"] $cellFont \ $maxTextWidth $alignment] } else { adjustElem $win text auxWidth $cellFont $pixels \ $snipSide $data(-snipstring) } # # Update the text widget's contents between the two tabs # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 if {$multiline} { updateMlCell $w $tabIdx1+1c $tabIdx2 $msgScript \ $aux $auxType $auxWidth $alignment } else { updateCell $w $tabIdx1+1c $tabIdx2 $text \ $aux $auxType $auxWidth $alignment } } -text { if {$data(isDisabled)} { return "" } set pixels [lindex $data(colList) [expr {2*$col}]] set workPixels $pixels set text $val set oldItem [lindex $data(itemList) $row] set key [lindex $oldItem end] set fmtCmdFlag [lindex $data(fmtCmdFlagList) $col] if {$fmtCmdFlag} { set text [formatElem $win $key $row $col $text] } set text [strToDispStr $text] set textSav $text set multiline [string match "*\n*" $text] set cellFont [getCellFont $win $key $col] if {$pixels == 0} { ;# convention: dynamic width getAuxData $win $key $col auxType auxWidthSav if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set workPixels $data($col-maxPixels) } } } set aux [getAuxData $win $key $col auxType auxWidth $workPixels] set maxTextWidth $workPixels if {$workPixels != 0} { incr workPixels $data($col-delta) set maxTextWidth [getMaxTextWidth $workPixels $auxWidth] if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $maxTextWidth} { set multiline 1 } } } set alignment [lindex $data(colList) [expr {2*$col + 1}]] # # Adjust the cell text and the image or window width # set snipSide $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } adjustMlElem $win list auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) set msgScript [list ::tablelist::displayText $win $key \ $col [join $list "\n"] $cellFont \ $maxTextWidth $alignment] } else { adjustElem $win text auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) } if {(!$data($col-hide) || $canElide) && !($row == $data(editRow) && $col == $data(editCol))} { # # Update the text widget's contents between the two tabs # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 if {$multiline} { updateMlCell $w $tabIdx1+1c $tabIdx2 $msgScript \ $aux $auxType $auxWidth $alignment } else { updateCell $w $tabIdx1+1c $tabIdx2 $text \ $aux $auxType $auxWidth $alignment } } # # Replace the cell contents in the internal list # set newItem [lreplace $oldItem $col $col $val] set data(itemList) [lreplace $data(itemList) $row $row $newItem] # # Replace the cell contents in the list variable if present # if {$data(hasListVar)} { upvar #0 $data(-listvariable) var trace vdelete var wu $data(listVarTraceCmd) set var [lreplace $var $row $row \ [lrange $newItem 0 $data(lastCol)]] trace variable var wu $data(listVarTraceCmd) } # # Adjust the columns if necessary # if {$pixels == 0} { ;# convention: dynamic width set text $textSav set auxWidth $auxWidthSav set newElemWidth [getElemWidth $win $text $auxWidth $cellFont] if {$newElemWidth > $data($col-elemWidth)} { set data($col-elemWidth) $newElemWidth set data($col-widestCount) 1 if {$newElemWidth > $data($col-reqPixels)} { set data($col-reqPixels) $newElemWidth adjustColumns $win {} 1 } } else { set oldText [lindex $oldItem $col] if {$fmtCmdFlag} { set oldText [formatElem $win $key $row $col $oldText] } set oldText [strToDispStr $oldText] set oldElemWidth \ [getElemWidth $win $oldText $auxWidth $cellFont] if {$oldElemWidth < $data($col-elemWidth) && $newElemWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$oldElemWidth == $data($col-elemWidth) && $newElemWidth < $oldElemWidth && [incr data($col-widestCount) -1] == 0} { adjustColumns $win $col 1 } } } adjustElidedTextWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win } -window { if {$data(isDisabled)} { return "" } # # Save the old image or window width # set item [lindex $data(itemList) $row] set key [lindex $item end] set name $key,$col$opt getAuxData $win $key $col oldAuxType oldAuxWidth # # Delete data($name) or save the specified value in it # if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) unset data($key,$col-reqWidth) unset data($key,$col-reqHeight) # # If the cell index is contained in the list # data(cellsToReconfig) then remove it from the list # set n [lsearch -exact $data(cellsToReconfig) $row,$col] if {$n >= 0} { set data(cellsToReconfig) \ [lreplace $data(cellsToReconfig) $n $n] } incr data(winCount) -1 } } else { if {![info exists data($name)]} { incr data(winCount) } set aux $w.f$key,$col set existsAux [winfo exists $aux] if {$existsAux && [info exists data($name)] && [string compare $val $data($name)] == 0} { set keepAux 1 } else { set keepAux 0 if {$existsAux} { destroy $aux } # # Create the frame and evaluate the specified script # that creates a child widget within the frame # tk::frame $aux -borderwidth 0 -class TablelistWindow \ -container 0 -highlightthickness 0 \ -relief flat -takefocus 0 catch {$aux configure -padx 0 -pady 0} bindtags $aux [linsert [bindtags $aux] 1 \ $data(bodyTag) TablelistBody] uplevel #0 $val [list $win $row $col $aux.w] } set data($name) $val set data($key,$col-reqWidth) [winfo reqwidth $aux.w] set data($key,$col-reqHeight) [winfo reqheight $aux.w] $aux configure -height $data($key,$col-reqHeight) # # Add the cell index to the list data(cellsToReconfig) if # the window's requested width or height is not yet known # if {($data($key,$col-reqWidth) == 1 || $data($key,$col-reqHeight) == 1) && [lsearch -exact $data(cellsToReconfig) $row,$col] < 0} { lappend data(cellsToReconfig) $row,$col if {![info exists data(reconfigId)]} { set data(reconfigId) \ [after idle [list tablelist::reconfigWindows $win]] } } } # # Adjust the cell text and the image or window width # set pixels [lindex $data(colList) [expr {2*$col}]] set workPixels $pixels set text [lindex $item $col] if {[lindex $data(fmtCmdFlagList) $col]} { set text [formatElem $win $key $row $col $text] } set text [strToDispStr $text] set oldText $text set multiline [string match "*\n*" $text] set cellFont [getCellFont $win $key $col] if {$pixels == 0} { ;# convention: dynamic width set textSav $text getAuxData $win $key $col auxType auxWidthSav if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set workPixels $data($col-maxPixels) } } } set aux [getAuxData $win $key $col auxType auxWidth $workPixels] set maxTextWidth $workPixels if {$workPixels != 0} { incr workPixels $data($col-delta) set maxTextWidth [getMaxTextWidth $workPixels $auxWidth] if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $maxTextWidth} { set multiline 1 } } } set alignment [lindex $data(colList) [expr {2*$col + 1}]] set snipSide $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } adjustMlElem $win list auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) set msgScript [list ::tablelist::displayText $win $key \ $col [join $list "\n"] $cellFont \ $maxTextWidth $alignment] } else { adjustElem $win text auxWidth $cellFont $workPixels \ $snipSide $data(-snipstring) } if {(!$data($col-hide) || $canElide) && !($row == $data(editRow) && $col == $data(editCol))} { # # Delete the old cell contents between the two tabs, # and insert the text and the auxiliary object # findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 if {$auxType < 2 || $keepAux} { if {$multiline} { updateMlCell $w $tabIdx1+1c $tabIdx2 $msgScript \ $aux $auxType $auxWidth $alignment } else { updateCell $w $tabIdx1+1c $tabIdx2 $text \ $aux $auxType $auxWidth $alignment } } else { $aux configure -width $auxWidth $w delete $tabIdx1+1c $tabIdx2 if {$multiline} { insertMlElem $w $tabIdx1+1c $msgScript \ $aux $auxType $alignment } else { insertElem $w $tabIdx1+1c $text $aux $auxType $alignment } } } # # Adjust the columns if necessary # if {$pixels == 0} { ;# convention: dynamic width set text $textSav set auxWidth $auxWidthSav set newElemWidth [getElemWidth $win $text $auxWidth $cellFont] if {$newElemWidth > $data($col-elemWidth)} { set data($col-elemWidth) $newElemWidth set data($col-widestCount) 1 if {$newElemWidth > $data($col-reqPixels)} { set data($col-reqPixels) $newElemWidth adjustColumns $win {} 1 } } else { set oldElemWidth \ [getElemWidth $win $oldText $oldAuxWidth $cellFont] if {$oldElemWidth < $data($col-elemWidth) && $newElemWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$oldElemWidth == $data($col-elemWidth) && $newElemWidth < $oldElemWidth && [incr data($col-widestCount) -1] == 0} { adjustColumns $win $col 1 } } } adjustElidedTextWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win } -windowdestroy { set key [lindex [lindex $data(itemList) $row] end] set name $key,$col$opt # # Delete data($name) or save the specified value in it # if {[string compare $val ""] == 0} { if {[info exists data($name)]} { unset data($name) } } else { set data($name) $val } } } } #------------------------------------------------------------------------------ # tablelist::doCellCget # # Returns the value of the cell configuration option opt for the cell row,col # of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::doCellCget {row col win opt} { upvar ::tablelist::ns${win}::data data # # Return the value of the specified cell configuration option # switch -- $opt { -editable { return [isCellEditable $win $row $col] } -editwindow { return [getEditWindow $win $row $col] } -stretchwindow { set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key,$col$opt)]} { return $data($key,$col$opt) } else { return 0 } } -text { return [lindex [lindex $data(itemList) $row] $col] } default { set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key,$col$opt)]} { return $data($key,$col$opt) } else { return "" } } } } #------------------------------------------------------------------------------ # tablelist::makeListVar # # Arranges for the global variable specified by varName to become the list # variable associated with the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::makeListVar {win varName} { upvar ::tablelist::ns${win}::data data if {[string compare $varName ""] == 0} { # # If there is an old list variable associated with the # widget then remove the trace set on this variable # if {$data(hasListVar)} { synchronize $win upvar #0 $data(-listvariable) var trace vdelete var wu $data(listVarTraceCmd) } return "" } # # The list variable may be an array element but must not be an array # if {![regexp {^(.*)\((.*)\)$} $varName dummy name1 name2]} { if {[array exists $varName]} { return -code error "variable \"$varName\" is array" } set name1 $varName set name2 "" } # # If there is an old list variable associated with the # widget then remove the trace set on this variable # if {$data(hasListVar)} { synchronize $win upvar #0 $data(-listvariable) var trace vdelete var wu $data(listVarTraceCmd) } upvar #0 $varName var if {[info exists var]} { # # Invoke the trace procedure associated with the new list variable # listVarTrace $win $name1 $name2 w } else { # # Set $varName according to the value of data(itemList) # set var {} foreach item $data(itemList) { lappend var [lrange $item 0 $data(lastCol)] } } # # Set a trace on the new list variable # trace variable var wu $data(listVarTraceCmd) } #------------------------------------------------------------------------------ # tablelist::getCellFont # # Returns the font to be used in the tablelist cell specified by win, key, and # col. #------------------------------------------------------------------------------ proc tablelist::getCellFont {win key col} { upvar ::tablelist::ns${win}::data data if {[info exists data($key,$col-font)]} { return $data($key,$col-font) } elseif {[info exists data($key-font)]} { return $data($key-font) } else { return [lindex $data(colFontList) $col] } } #------------------------------------------------------------------------------ # tablelist::reconfigWindows # # Invoked as an after idle callback, this procedure forces any geometry manager # calculations to be completed and then applies the -window option a second # time to those cells whose embedded windows' requested widths or heights were # still unknown. #------------------------------------------------------------------------------ proc tablelist::reconfigWindows win { # # Force any geometry manager calculations to be completed first # update idletasks if {![winfo exists $win]} { ;# because of update idletasks return "" } # # Reconfigure the cells specified in the list data(cellsToReconfig) # upvar ::tablelist::ns${win}::data data foreach cellIdx $data(cellsToReconfig) { foreach {row col} [split $cellIdx ","] {} set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key,$col-window)]} { doCellConfig $row $col $win -window $data($key,$col-window) } } unset data(reconfigId) set data(cellsToReconfig) {} } #------------------------------------------------------------------------------ # tablelist::isCellEditable # # Checks whether the given cell of the tablelist widget win is editable. #------------------------------------------------------------------------------ proc tablelist::isCellEditable {win row col} { upvar ::tablelist::ns${win}::data data set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key,$col-editable)]} { return $data($key,$col-editable) } else { return $data($col-editable) } } #------------------------------------------------------------------------------ # tablelist::getEditWindow # # Returns the value of the -editwindow option at cell or column level for the # given cell of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::getEditWindow {win row col} { upvar ::tablelist::ns${win}::data data set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key,$col-editwindow)]} { return $data($key,$col-editwindow) } elseif {[info exists data($col-editwindow)]} { return $data($col-editwindow) } else { return "entry" } } kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistWidget.tcl0000644000175000017500000043440111070725164024623 0ustar domibeldomibel#============================================================================== # Contains the implementation of the tablelist widget. # # Structure of the module: # - Namespace initialization # - Private procedure creating the default bindings # - Public procedure creating a new tablelist widget # - Private procedures implementing the tablelist widget command # - Private callback procedures # # Copyright (c) 2000-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== # # Namespace initialization # ======================== # namespace eval tablelist { # # Get the current windowing system ("x11", "win32", "classic", or "aqua") # variable winSys if {[catch {tk windowingsystem} winSys] != 0} { switch $::tcl_platform(platform) { unix { set winSys x11 } windows { set winSys win32 } macintosh { set winSys classic } } } # # Create aliases for a few tile commands if not yet present # proc createTileAliases {} { if {[string compare [interp alias {} ::tablelist::style] ""] != 0} { return "" } if {[string compare [info commands ::ttk::style] ""] == 0} { interp alias {} ::tablelist::style {} ::style if {[string compare $::tile::version "0.7"] >= 0} { interp alias {} ::tablelist::styleConfig {} ::style configure } else { interp alias {} ::tablelist::styleConfig {} ::style default } interp alias {} ::tablelist::getThemes {} ::tile::availableThemes interp alias {} ::tablelist::setTheme {} ::tile::setTheme interp alias {} ::tablelist::tileqt_currentThemeName \ {} ::tile::theme::tileqt::currentThemeName interp alias {} ::tablelist::tileqt_currentThemeColour \ {} ::tile::theme::tileqt::currentThemeColour } else { interp alias {} ::tablelist::style {} ::ttk::style interp alias {} ::tablelist::styleConfig {} ::ttk::style configure interp alias {} ::tablelist::getThemes {} ::ttk::themes interp alias {} ::tablelist::setTheme {} ::ttk::setTheme interp alias {} ::tablelist::tileqt_currentThemeName \ {} ::ttk::theme::tileqt::currentThemeName interp alias {} ::tablelist::tileqt_currentThemeColour \ {} ::ttk::theme::tileqt::currentThemeColour } } if {$usingTile} { createTileAliases } # # The array configSpecs is used to handle configuration options. The # names of its elements are the configuration options for the Tablelist # class. The value of an array element is either an alias name or a list # containing the database name and class as well as an indicator specifying # the widget(s) to which the option applies: c stands for all children # (text widgets and labels), b for the body text widget, l for the labels, # f for the frame, and w for the widget itself. # # Command-Line Name {Database Name Database Class W} # ------------------------------------------------------------------------ # variable configSpecs array set configSpecs { -activestyle {activeStyle ActiveStyle w} -arrowcolor {arrowColor ArrowColor w} -arrowstyle {arrowStyle ArrowStyle w} -arrowdisabledcolor {arrowDisabledColor ArrowDisabledColor w} -background {background Background b} -bg -background -borderwidth {borderWidth BorderWidth f} -bd -borderwidth -columns {columns Columns w} -cursor {cursor Cursor c} -disabledforeground {disabledForeground DisabledForeground w} -editendcommand {editEndCommand EditEndCommand w} -editstartcommand {editStartCommand EditStartCommand w} -exportselection {exportSelection ExportSelection w} -font {font Font b} -forceeditendcommand {forceEditEndCommand ForceEditEndCommand w} -foreground {foreground Foreground b} -fg -foreground -height {height Height w} -highlightbackground {highlightBackground HighlightBackground f} -highlightcolor {highlightColor HighlightColor f} -highlightthickness {highlightThickness HighlightThickness f} -incrarrowtype {incrArrowType IncrArrowType w} -labelactivebackground {labelActiveBackground Foreground l} -labelactiveforeground {labelActiveForeground Background l} -labelbackground {labelBackground Background l} -labelbg -labelbackground -labelborderwidth {labelBorderWidth BorderWidth l} -labelbd -labelborderwidth -labelcommand {labelCommand LabelCommand w} -labelcommand2 {labelCommand2 LabelCommand2 w} -labeldisabledforeground {labelDisabledForeground DisabledForeground l} -labelfont {labelFont Font l} -labelforeground {labelForeground Foreground l} -labelfg -labelforeground -labelheight {labelHeight Height l} -labelpady {labelPadY Pad l} -labelrelief {labelRelief Relief l} -listvariable {listVariable Variable w} -movablecolumns {movableColumns MovableColumns w} -movablerows {movableRows MovableRows w} -movecolumncursor {moveColumnCursor MoveColumnCursor w} -movecursor {moveCursor MoveCursor w} -protecttitlecolumns {protectTitleColumns ProtectTitleColumns w} -relief {relief Relief f} -resizablecolumns {resizableColumns ResizableColumns w} -resizecursor {resizeCursor ResizeCursor w} -selectbackground {selectBackground Foreground w} -selectborderwidth {selectBorderWidth BorderWidth w} -selectforeground {selectForeground Background w} -selectmode {selectMode SelectMode w} -selecttype {selectType SelectType w} -setfocus {setFocus SetFocus w} -setgrid {setGrid SetGrid w} -showarrow {showArrow ShowArrow w} -showlabels {showLabels ShowLabels w} -showseparators {showSeparators ShowSeparators w} -snipstring {snipString SnipString w} -sortcommand {sortCommand SortCommand w} -spacing {spacing Spacing w} -state {state State w} -stretch {stretch Stretch w} -stripebackground {stripeBackground Background w} -stripebg -stripebackground -stripeforeground {stripeForeground Foreground w} -stripefg -stripeforeground -stripeheight {stripeHeight StripeHeight w} -takefocus {takeFocus TakeFocus f} -targetcolor {targetColor TargetColor w} -titlecolumns {titleColumns TitleColumns w} -tooltipaddcommand {tooltipAddCommand TooltipAddCommand w} -tooltipdelcommand {tooltipDelCommand TooltipDelCommand w} -width {width Width w} -xscrollcommand {xScrollCommand ScrollCommand w} -yscrollcommand {yScrollCommand ScrollCommand w} } # # Extend the elements of the array configSpecs # extendConfigSpecs variable configOpts [lsort [array names configSpecs]] # # The array colConfigSpecs is used to handle column configuration options. # The names of its elements are the column configuration options for the # Tablelist widget class. The value of an array element is either an alias # name or a list containing the database name and class. # # Command-Line Name {Database Name Database Class } # ----------------------------------------------------------------- # variable colConfigSpecs array set colConfigSpecs { -align {align Align } -background {background Background } -bg -background -changesnipside {changeSnipSide ChangeSnipSide } -editable {editable Editable } -editwindow {editWindow EditWindow } -font {font Font } -foreground {foreground Foreground } -fg -foreground -formatcommand {formatCommand FormatCommand } -hide {hide Hide } -labelalign {labelAlign Align } -labelbackground {labelBackground Background } -labelbg -labelbackground -labelborderwidth {labelBorderWidth BorderWidth } -labelbd -labelborderwidth -labelcommand {labelCommand LabelCommand } -labelcommand2 {labelCommand2 LabelCommand2 } -labelfont {labelFont Font } -labelforeground {labelForeground Foreground } -labelfg -labelforeground -labelheight {labelHeight Height } -labelimage {labelImage Image } -labelpady {labelPadY Pad } -labelrelief {labelRelief Relief } -maxwidth {maxWidth MaxWidth } -name {name Name } -resizable {resizable Resizable } -selectbackground {selectBackground Foreground } -selectforeground {selectForeground Background } -showarrow {showArrow ShowArrow } -showlinenumbers {showLineNumbers ShowLineNumbers } -sortcommand {sortCommand SortCommand } -sortmode {sortMode SortMode } -stretchable {stretchable Stretchable } -text {text Text } -title {title Title } -width {width Width } -wrap {wrap Wrap } } # # Extend some elements of the array colConfigSpecs # lappend colConfigSpecs(-align) - left lappend colConfigSpecs(-changesnipside) - 0 lappend colConfigSpecs(-editable) - 0 lappend colConfigSpecs(-editwindow) - entry lappend colConfigSpecs(-hide) - 0 lappend colConfigSpecs(-maxwidth) - 0 lappend colConfigSpecs(-resizable) - 1 lappend colConfigSpecs(-showarrow) - 1 lappend colConfigSpecs(-showlinenumbers) - 0 lappend colConfigSpecs(-sortmode) - ascii lappend colConfigSpecs(-stretchable) - 0 lappend colConfigSpecs(-width) - 0 lappend colConfigSpecs(-wrap) - 0 if {$usingTile} { unset colConfigSpecs(-labelheight) } # # The array rowConfigSpecs is used to handle row configuration options. # The names of its elements are the row configuration options for the # Tablelist widget class. The value of an array element is either an alias # name or a list containing the database name and class. # # Command-Line Name {Database Name Database Class } # ----------------------------------------------------------------- # variable rowConfigSpecs array set rowConfigSpecs { -background {background Background } -bg -background -font {font Font } -foreground {foreground Foreground } -fg -foreground -hide {hide Hide } -name {name Name } -selectable {selectable Selectable } -selectbackground {selectBackground Foreground } -selectforeground {selectForeground Background } -text {text Text } } # # Check whether the -elide text widget tag option is available # variable canElide variable elide if {$::tk_version >= 8.3} { set canElide 1 set elide -elide } else { set canElide 0 set elide -- } # # Extend some elements of the array rowConfigSpecs # if {$canElide} { lappend rowConfigSpecs(-hide) - 0 } else { unset rowConfigSpecs(-hide) } lappend rowConfigSpecs(-selectable) - 1 # # The array cellConfigSpecs is used to handle cell configuration options. # The names of its elements are the cell configuration options for the # Tablelist widget class. The value of an array element is either an alias # name or a list containing the database name and class. # # Command-Line Name {Database Name Database Class } # ----------------------------------------------------------------- # variable cellConfigSpecs array set cellConfigSpecs { -background {background Background } -bg -background -editable {editable Editable } -editwindow {editWindow EditWindow } -font {font Font } -foreground {foreground Foreground } -fg -foreground -image {image Image } -selectbackground {selectBackground Foreground } -selectforeground {selectForeground Background } -stretchwindow {stretchWindow StretchWindow } -text {text Text } -window {window Window } -windowdestroy {windowDestroy WindowDestroy } } # # Extend some elements of the array cellConfigSpecs # lappend cellConfigSpecs(-editable) - 0 lappend cellConfigSpecs(-editwindow) - entry lappend cellConfigSpecs(-stretchwindow) - 0 # # Use a list to facilitate the handling of the command options # variable cmdOpts [list \ activate activatecell attrib bbox bodypath bodytag cancelediting \ cellattrib cellcget cellconfigure cellindex cellselection cget \ columnattrib columncget columnconfigure columncount columnindex \ columnwidth config configcelllist configcells configcolumnlist \ configcolumns configrowlist configrows configure containing \ containingcell containingcolumn curcellselection curselection delete \ deletecolumns editcell editwintag editwinpath entrypath fillcolumn \ finishediting formatinfo get getcells getcolumns getkeys hasattrib \ hascellattrib hascolumnattrib hasrowattrib imagelabelpath index \ insert insertcolumnlist insertcolumns insertlist iselemsnipped \ istitlesnipped itemlistvar labelpath labels move movecolumn nearest \ nearestcell nearestcolumn rejectinput resetsortinfo rowattrib rowcget \ rowconfigure scan see seecell seecolumn selection separatorpath \ separators size sort sortbycolumn sortbycolumnlist sortcolumn \ sortcolumnlist sortorder sortorderlist togglecolumnhide togglerowhide \ unsetattrib unsetcellattrib unsetcolumnattrib unsetrowattrib \ windowpath xview yview] if {!$canElide} { set idx [lsearch -exact $cmdOpts togglerowhide] set cmdOpts [lreplace $cmdOpts $idx $idx] } # # Use lists to facilitate the handling of miscellaneous options # variable activeStyles [list frame none underline] variable alignments [list left right center] variable arrowStyles [list flat7x4 flat7x5 flat7x7 flat8x5 flat9x5 \ sunken8x7 sunken10x9 sunken12x11] variable arrowTypes [list up down] variable colWidthOpts [list -requested -stretched -total] variable states [list disabled normal] variable selectTypes [list row cell] variable sortModes [list ascii command dictionary integer real] variable sortOrders [list increasing decreasing] variable _sortOrders [list -increasing -decreasing] variable scanCmdOpts [list mark dragto] variable selCmdOpts [list anchor clear includes set] # # Define the procedure strToDispStr, which returns the string # obtained by replacing all \t characters in its argument with # \\t, as well as the procedure strMap, needed because the # "string map" command is not available in Tcl 8.0 and 8.1.0. # if {[catch {string map {} ""}] == 0} { proc strToDispStr str { if {[string match "*\t*" $str]} { return [string map {"\t" "\\t"} $str] } else { return $str } } interp alias {} ::tablelist::strMap {} string map } else { proc strToDispStr str { if {[string match "*\t*" $str]} { regsub -all "\t" $str "\\t" str } return $str } proc strMap {charMap str} { foreach {key val} $charMap { # # We will only need this for noncritical key and str values # regsub -all $key $str $val str } return $str } } } # # Private procedure creating the default bindings # =============================================== # #------------------------------------------------------------------------------ # tablelist::createBindings # # Creates the default bindings for the binding tags Tablelist, TablelistWindow, # TablelistKeyNav, TablelistBody, TablelistLabel, TablelistSubLabel, # TablelistArrow, and TablelistEdit. #------------------------------------------------------------------------------ proc tablelist::createBindings {} { # # Define some Tablelist class bindings # bind Tablelist continue bind Tablelist { if {![info exists tablelist::ns%W::data(dispId)]} { tablelist::addActiveTag %W } if {[string compare [focus -lastfor %W] %W] == 0} { if {[winfo exists [%W editwinpath]]} { focus [set tablelist::ns%W::data(editFocus)] } else { focus [%W bodypath] } } } bind Tablelist { tablelist::removeActiveTag %W } bind Tablelist <> { event generate %W <> } bind Tablelist { tablelist::cleanup %W } variable usingTile if {$usingTile} { bind Tablelist <> { after idle [list tablelist::updateConfigSpecs %W] } } # # Define some TablelistWindow class bindings # bind TablelistWindow { tablelist::cleanupWindow %W } # # Define the binding tags TablelistKeyNav and TablelistBody # mwutil::defineKeyNav Tablelist defineTablelistBody # # Define the virtual events <> and <> # event add <> event add <> variable winSys if {[string compare $winSys "classic"] == 0 || [string compare $winSys "aqua"] == 0} { event add <> event add <> } # # Define some mouse bindings for the binding tag TablelistLabel # bind TablelistLabel { tablelist::labelEnter %W %X %Y %x } bind TablelistLabel { tablelist::labelEnter %W %X %Y %x } bind TablelistLabel { tablelist::labelLeave %W %X %x %y } bind TablelistLabel { tablelist::labelB1Down %W %x 0 } bind TablelistLabel { tablelist::labelB1Down %W %x 1 } bind TablelistLabel { tablelist::labelB1Motion %W %X %x %y } bind TablelistLabel { tablelist::labelB1Enter %W } bind TablelistLabel { tablelist::labelB1Leave %W %x %y } bind TablelistLabel { tablelist::labelB1Up %W %X} bind TablelistLabel <> { tablelist::labelB3Down %W 0 } bind TablelistLabel <> { tablelist::labelB3Down %W 1 } # # Define the binding tags TablelistSubLabel and TablelistArrow # defineTablelistSubLabel defineTablelistArrow # # Define the binding tag TablelistEdit if the file tablelistEdit.tcl exists # catch {defineTablelistEdit} } # # Public procedure creating a new tablelist widget # ================================================ # #------------------------------------------------------------------------------ # tablelist::tablelist # # Creates a new tablelist widget whose name is specified as the first command- # line argument, and configures it according to the options and their values # given on the command line. Returns the name of the newly created widget. #------------------------------------------------------------------------------ proc tablelist::tablelist args { variable usingTile variable configSpecs variable configOpts variable canElide if {[llength $args] == 0} { mwutil::wrongNumArgs "tablelist pathName ?options?" } # # Create a frame of the class Tablelist # set win [lindex $args 0] if {[catch { if {$usingTile} { ttk::frame $win -style Frame$win.TFrame -class Tablelist \ -height 0 -width 0 -padding 0 } else { tk::frame $win -class Tablelist -container 0 -height 0 -width 0 catch {$win configure -padx 0 -pady 0} } } result] != 0} { return -code error $result } # # Create a namespace within the current one to hold the data of the widget # namespace eval ns$win { # # The folowing array holds various data for this widget # variable data array set data { arrowWidth 9 hasListVar 0 isDisabled 0 ownsFocus 0 charWidth 1 hdrPixels 0 activeRow 0 activeCol 0 anchorRow 0 anchorCol 0 seqNum -1 freeKeyList {} itemList {} itemCount 0 lastRow -1 colList {} colCount 0 lastCol -1 rowTagRefCount 0 cellTagRefCount 0 imgCount 0 winCount 0 afterId "" labelClicked 0 arrowColList {} sortColList {} sortOrder "" editRow -1 editCol -1 fmtKey "" fmtRow -1 fmtCol -1 prevCell "" prevCol -1 forceAdjust 0 fmtCmdFlagList {} hasFmtCmds 0 scrlColOffset 0 cellsToReconfig {} hiddenRowCount 0 nonHiddenRowList {-1} hiddenColCount 0 } # # The following array is used to hold arbitrary # attributes and their values for this widget # variable attribs } # # Initialize some further components of data # upvar ::tablelist::ns${win}::data data foreach opt $configOpts { set data($opt) [lindex $configSpecs($opt) 3] } if {$usingTile} { setThemeDefaults variable themeDefaults set data(currentTheme) [getCurrentTheme] set data(themeDefaults) [array get themeDefaults] if {[string compare $data(currentTheme) "tileqt"] == 0} { set data(widgetStyle) [tileqt_currentThemeName] set data(colorScheme) [getKdeConfigVal "KDE" "colorScheme"] } else { set data(widgetStyle) "" set data(colorScheme) "" } } set data(-titlecolumns) 0 ;# for Tk versions < 8.3 set data(colFontList) [list $data(-font)] set data(listVarTraceCmd) [list tablelist::listVarTrace $win] set data(bodyTag) body$win set data(editwinTag) editwin$win set data(body) $win.body set data(bodyFr) $data(body).f set data(bodyFrEd) $data(bodyFr).e set data(rowGap) $data(body).g set data(hdr) $win.hdr set data(hdrTxt) $data(hdr).t set data(hdrTxtFr) $data(hdrTxt).f set data(hdrTxtFrCanv) $data(hdrTxtFr).c set data(hdrTxtFrLbl) $data(hdrTxtFr).l set data(hdrLbl) $data(hdr).l set data(colGap) $data(hdr).g set data(lb) $win.lb set data(sep) $win.sep # # Create a child hierarchy used to hold the column labels. The # labels will be created as children of the frame data(hdrTxtFr), # which is embedded into the text widget data(hdrTxt) (in order # to make it scrollable), which in turn fills the frame data(hdr) # (whose width and height can be set arbitrarily in pixels). # set w $data(hdr) ;# header frame tk::frame $w -borderwidth 0 -container 0 -height 0 -highlightthickness 0 \ -relief flat -takefocus 0 -width 0 catch {$w configure -padx 0 -pady 0} bind $w { set tablelist::W [winfo parent %W] tablelist::stretchColumnsWhenIdle $tablelist::W tablelist::updateScrlColOffsetWhenIdle $tablelist::W tablelist::updateHScrlbarWhenIdle $tablelist::W } pack $w -fill x set w $data(hdrTxt) ;# text widget within the header frame text $w -borderwidth 0 -highlightthickness 0 -insertwidth 0 \ -padx 0 -pady 0 -state normal -takefocus 0 -wrap none place $w -relheight 1.0 -relwidth 1.0 bindtags $w [lreplace [bindtags $w] 1 1] tk::frame $data(hdrTxtFr) -borderwidth 0 -container 0 -height 0 \ -highlightthickness 0 -relief flat \ -takefocus 0 -width 0 catch {$data(hdrTxtFr) configure -padx 0 -pady 0} $w window create 1.0 -window $data(hdrTxtFr) set w $data(hdrLbl) ;# filler label within the header frame if {$usingTile} { ttk::label $data(hdrTxtFrLbl)0 -style TablelistHeader.TLabel ttk::label $w -style TablelistHeader.TLabel -image "" \ -padding {1 1 1 1} -takefocus 0 -text "" \ -textvariable "" -underline -1 -wraplength 0 } else { tk::label $data(hdrTxtFrLbl)0 tk::label $w -bitmap "" -highlightthickness 0 -image "" \ -takefocus 0 -text "" -textvariable "" -underline -1 \ -wraplength 0 } place $w -relheight 1.0 -relwidth 1.0 # # Create the body text widget within the main frame # set w $data(body) text $w -borderwidth 0 -exportselection 0 -highlightthickness 0 \ -insertwidth 0 -padx 0 -pady 0 -state normal -takefocus 0 -wrap none bind $w { set tablelist::W [winfo parent %W] tablelist::makeColFontAndTagLists $tablelist::W tablelist::adjustElidedTextWhenIdle $tablelist::W tablelist::updateColorsWhenIdle $tablelist::W tablelist::adjustSepsWhenIdle $tablelist::W tablelist::updateVScrlbarWhenIdle $tablelist::W } pack $w -expand 1 -fill both # # Modify the list of binding tags of the body text widget # bindtags $w [list $w $data(bodyTag) TablelistBody [winfo toplevel $w] \ TablelistKeyNav all] # # Create the "stripe", "select", "active", "disabled", "hiddenRow", # "hiddenCol", and "elidedCol" tags in the body text widget. Don't # use the built-in "sel" tag because on Windows the selection in a # text widget only becomes visible when the window gets the input # focus. DO NOT CHANGE the order of creation of these tags! # $w tag configure stripe -background "" -foreground "" ;# will be changed $w tag configure select -relief raised $w tag configure active -borderwidth "" ;# will be changed $w tag configure disabled -foreground "" ;# will be changed if {$canElide} { $w tag configure hiddenRow -elide 1 $w tag configure hiddenCol -elide 1 $w tag configure elidedCol -elide 1 } # # Create two frames used to display a gap between two consecutive # rows/columns when moving a row/column interactively # tk::frame $data(rowGap) -borderwidth 1 -container 0 -highlightthickness 0 \ -relief sunken -takefocus 0 -height 4 tk::frame $data(colGap) -borderwidth 1 -container 0 -highlightthickness 0 \ -relief sunken -takefocus 0 -width 4 # # Create an unmanaged listbox child, used to handle the -setgrid option # listbox $data(lb) # # Create the bitmaps needed to display the sort ranks # createSortRankImgs $win # # Configure the widget according to the command-line # arguments and to the available database options # if {[catch { mwutil::configureWidget $win configSpecs tablelist::doConfig \ tablelist::doCget [lrange $args 1 end] 1 } result] != 0} { destroy $win return -code error $result } # # Move the original widget command into the current namespace and # create an alias of the original name for a new widget procedure # rename ::$win $win interp alias {} ::$win {} tablelist::tablelistWidgetCmd $win # # Register a callback to be invoked whenever the PRIMARY # selection is owned by the window win and someone # attempts to retrieve it as a UTF8_STRING or STRING # selection handle -type UTF8_STRING $win \ [list ::tablelist::fetchSelection $win] selection handle -type STRING $win \ [list ::tablelist::fetchSelection $win] # # Set a trace on the array elements data(activeRow), # data(avtiveCol), and data(-selecttype) # foreach name {activeRow activeCol -selecttype} { trace variable data($name) w [list tablelist::activeTrace $win] } return $win } # # Private procedures implementing the tablelist widget command # ============================================================ # #------------------------------------------------------------------------------ # tablelist::tablelistWidgetCmd # # Processes the Tcl command corresponding to a tablelist widget. #------------------------------------------------------------------------------ proc tablelist::tablelistWidgetCmd {win args} { if {[llength $args] == 0} { mwutil::wrongNumArgs "$win option ?arg arg ...?" } variable cmdOpts set cmd [mwutil::fullOpt "option" [lindex $args 0] $cmdOpts] return [${cmd}SubCmd $win [lrange $args 1 end]] } #------------------------------------------------------------------------------ # tablelist::activateSubCmd #------------------------------------------------------------------------------ proc tablelist::activateSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win activate index" } upvar ::tablelist::ns${win}::data data if {$data(isDisabled)} { return "" } synchronize $win displayItems $win set index [rowIndex $win [lindex $argList 0] 0] # # Adjust the index to fit within the existing non-hidden items # adjustRowIndex $win index 1 set data(activeRow) $index return "" } #------------------------------------------------------------------------------ # tablelist::activatecellSubCmd #------------------------------------------------------------------------------ proc tablelist::activatecellSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win activatecell cellIndex" } upvar ::tablelist::ns${win}::data data if {$data(isDisabled)} { return "" } synchronize $win displayItems $win foreach {row col} [cellIndex $win [lindex $argList 0] 0] {} # # Adjust the row and column indices to fit # within the existing non-hidden elements # adjustRowIndex $win row 1 adjustColIndex $win col 1 set data(activeRow) $row set data(activeCol) $col return "" } #------------------------------------------------------------------------------ # tablelist::attribSubCmd #------------------------------------------------------------------------------ proc tablelist::attribSubCmd {win argList} { return [mwutil::attribSubCmd $win "widget" $argList] } #------------------------------------------------------------------------------ # tablelist::bboxSubCmd #------------------------------------------------------------------------------ proc tablelist::bboxSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win bbox index" } synchronize $win displayItems $win set index [rowIndex $win [lindex $argList 0] 0] upvar ::tablelist::ns${win}::data data set w $data(body) set dlineinfo [$w dlineinfo [expr {double($index + 1)}]] if {$data(itemCount) == 0 || [string compare $dlineinfo ""] == 0} { return {} } set spacing1 [$w cget -spacing1] set spacing3 [$w cget -spacing3] foreach {x y width height baselinePos} $dlineinfo {} lappend bbox [expr {$x + [winfo x $w]}] \ [expr {$y + [winfo y $w] + $spacing1}] \ $width [expr {$height - $spacing1 - $spacing3}] return $bbox } #------------------------------------------------------------------------------ # tablelist::bodypathSubCmd #------------------------------------------------------------------------------ proc tablelist::bodypathSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win bodypath" } upvar ::tablelist::ns${win}::data data return $data(body) } #------------------------------------------------------------------------------ # tablelist::bodytagSubCmd #------------------------------------------------------------------------------ proc tablelist::bodytagSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win bodytag" } upvar ::tablelist::ns${win}::data data return $data(bodyTag) } #------------------------------------------------------------------------------ # tablelist::canceleditingSubCmd #------------------------------------------------------------------------------ proc tablelist::canceleditingSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win cancelediting" } synchronize $win displayItems $win return [doCancelEditing $win] } #------------------------------------------------------------------------------ # tablelist::cellattribSubCmd #------------------------------------------------------------------------------ proc tablelist::cellattribSubCmd {win argList} { if {[llength $argList] < 1} { mwutil::wrongNumArgs "$win cellattrib cellIndex ?name? ?value\ name value ...?" } synchronize $win foreach {row col} [cellIndex $win [lindex $argList 0] 1] {} upvar ::tablelist::ns${win}::data data set key [lindex [lindex $data(itemList) $row] end] return [mwutil::attribSubCmd $win $key,$col [lrange $argList 1 end]] } #------------------------------------------------------------------------------ # tablelist::cellcgetSubCmd #------------------------------------------------------------------------------ proc tablelist::cellcgetSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win cellcget cellIndex option" } synchronize $win foreach {row col} [cellIndex $win [lindex $argList 0] 1] {} variable cellConfigSpecs set opt [mwutil::fullConfigOpt [lindex $argList 1] cellConfigSpecs] return [doCellCget $row $col $win $opt] } #------------------------------------------------------------------------------ # tablelist::cellconfigureSubCmd #------------------------------------------------------------------------------ proc tablelist::cellconfigureSubCmd {win argList} { if {[llength $argList] < 1} { mwutil::wrongNumArgs "$win cellconfigure cellIndex ?option? ?value\ option value ...?" } synchronize $win displayItems $win variable cellConfigSpecs foreach {row col} [cellIndex $win [lindex $argList 0] 1] {} return [mwutil::configureSubCmd $win cellConfigSpecs \ "tablelist::doCellConfig $row $col" \ "tablelist::doCellCget $row $col" [lrange $argList 1 end]] } #------------------------------------------------------------------------------ # tablelist::cellindexSubCmd #------------------------------------------------------------------------------ proc tablelist::cellindexSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win cellindex cellIndex" } synchronize $win return [join [cellIndex $win [lindex $argList 0] 0] ","] } #------------------------------------------------------------------------------ # tablelist::cellselectionSubCmd #------------------------------------------------------------------------------ proc tablelist::cellselectionSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 2 || $argCount > 3} { mwutil::wrongNumArgs \ "$win cellselection option firstCellIndex lastCellIndex" \ "$win cellselection option cellIndexList" } synchronize $win displayItems $win variable selCmdOpts set opt [mwutil::fullOpt "option" [lindex $argList 0] $selCmdOpts] set first [lindex $argList 1] switch $opt { anchor - includes { if {$argCount != 2} { mwutil::wrongNumArgs "$win cellselection $opt cellIndex" } foreach {row col} [cellIndex $win $first 0] {} return [cellSelection $win $opt $row $col $row $col] } clear - set { if {$argCount == 2} { foreach elem $first { foreach {row col} [cellIndex $win $elem 0] {} cellSelection $win $opt $row $col $row $col } return "" } else { foreach {firstRow firstCol} [cellIndex $win $first 0] {} foreach {lastRow lastCol} \ [cellIndex $win [lindex $argList 2] 0] {} return [cellSelection $win $opt \ $firstRow $firstCol $lastRow $lastCol] } } } } #------------------------------------------------------------------------------ # tablelist::cgetSubCmd #------------------------------------------------------------------------------ proc tablelist::cgetSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win cget option" } # # Return the value of the specified configuration option # variable configSpecs set opt [mwutil::fullConfigOpt [lindex $argList 0] configSpecs] upvar ::tablelist::ns${win}::data data return $data($opt) } #------------------------------------------------------------------------------ # tablelist::columnattribSubCmd #------------------------------------------------------------------------------ proc tablelist::columnattribSubCmd {win argList} { if {[llength $argList] < 1} { mwutil::wrongNumArgs "$win columnattrib columnIndex ?name? ?value\ name value ...?" } synchronize $win set col [colIndex $win [lindex $argList 0] 1] return [mwutil::attribSubCmd $win $col [lrange $argList 1 end]] } #------------------------------------------------------------------------------ # tablelist::columncgetSubCmd #------------------------------------------------------------------------------ proc tablelist::columncgetSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win columncget columnIndex option" } synchronize $win set col [colIndex $win [lindex $argList 0] 1] variable colConfigSpecs set opt [mwutil::fullConfigOpt [lindex $argList 1] colConfigSpecs] return [doColCget $col $win $opt] } #------------------------------------------------------------------------------ # tablelist::columnconfigureSubCmd #------------------------------------------------------------------------------ proc tablelist::columnconfigureSubCmd {win argList} { if {[llength $argList] < 1} { mwutil::wrongNumArgs "$win columnconfigure columnIndex ?option? ?value\ option value ...?" } synchronize $win displayItems $win variable colConfigSpecs set col [colIndex $win [lindex $argList 0] 1] return [mwutil::configureSubCmd $win colConfigSpecs \ "tablelist::doColConfig $col" "tablelist::doColCget $col" \ [lrange $argList 1 end]] } #------------------------------------------------------------------------------ # tablelist::columncountSubCmd #------------------------------------------------------------------------------ proc tablelist::columncountSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win columncount" } upvar ::tablelist::ns${win}::data data return $data(colCount) } #------------------------------------------------------------------------------ # tablelist::columnindexSubCmd #------------------------------------------------------------------------------ proc tablelist::columnindexSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win columnindex columnIndex" } return [colIndex $win [lindex $argList 0] 0] } #------------------------------------------------------------------------------ # tablelist::columnwidthSubCmd #------------------------------------------------------------------------------ proc tablelist::columnwidthSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs "$win columnwidth columnIndex\ ?-requested|-stretched|-total?" } synchronize $win displayItems $win set col [colIndex $win [lindex $argList 0] 1] if {$argCount == 1} { set opt -requested } else { variable colWidthOpts set opt [mwutil::fullOpt "option" [lindex $argList 1] $colWidthOpts] } return [colWidth $win $col $opt] } #------------------------------------------------------------------------------ # tablelist::configSubCmd #------------------------------------------------------------------------------ proc tablelist::configSubCmd {win argList} { return [configureSubCmd $win $argList] } #------------------------------------------------------------------------------ # tablelist::configcelllistSubCmd #------------------------------------------------------------------------------ proc tablelist::configcelllistSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win configcelllist cellConfigSpecList" } return [configcellsSubCmd $win [lindex $argList 0]] } #------------------------------------------------------------------------------ # tablelist::configcellsSubCmd #------------------------------------------------------------------------------ proc tablelist::configcellsSubCmd {win argList} { synchronize $win displayItems $win variable cellConfigSpecs set argCount [llength $argList] foreach {cell opt val} $argList { if {$argCount == 1} { return -code error "option and value for \"$cell\" missing" } elseif {$argCount == 2} { return -code error "value for \"$opt\" missing" } foreach {row col} [cellIndex $win $cell 1] {} mwutil::configureWidget $win cellConfigSpecs \ "tablelist::doCellConfig $row $col" \ "tablelist::doCellCget $row $col" [list $opt $val] 0 incr argCount -3 } return "" } #------------------------------------------------------------------------------ # tablelist::configcolumnlistSubCmd #------------------------------------------------------------------------------ proc tablelist::configcolumnlistSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win configcolumnlist columnConfigSpecList" } return [configcolumnsSubCmd $win [lindex $argList 0]] } #------------------------------------------------------------------------------ # tablelist::configcolumnsSubCmd #------------------------------------------------------------------------------ proc tablelist::configcolumnsSubCmd {win argList} { synchronize $win displayItems $win variable colConfigSpecs set argCount [llength $argList] foreach {col opt val} $argList { if {$argCount == 1} { return -code error "option and value for \"$col\" missing" } elseif {$argCount == 2} { return -code error "value for \"$opt\" missing" } set col [colIndex $win $col 1] mwutil::configureWidget $win colConfigSpecs \ "tablelist::doColConfig $col" "tablelist::doColCget $col" \ [list $opt $val] 0 incr argCount -3 } return "" } #------------------------------------------------------------------------------ # tablelist::configrowlistSubCmd #------------------------------------------------------------------------------ proc tablelist::configrowlistSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win configrowlist rowConfigSpecList" } return [configrowsSubCmd $win [lindex $argList 0]] } #------------------------------------------------------------------------------ # tablelist::configrowsSubCmd #------------------------------------------------------------------------------ proc tablelist::configrowsSubCmd {win argList} { synchronize $win displayItems $win variable rowConfigSpecs upvar ::tablelist::ns${win}::data data set argCount [llength $argList] foreach {rowSpec opt val} $argList { if {$argCount == 1} { return -code error "option and value for \"$rowSpec\" missing" } elseif {$argCount == 2} { return -code error "value for \"$opt\" missing" } set row [rowIndex $win $rowSpec 0] if {$row < 0 || $row > $data(lastRow)} { return -code error "row index \"$rowSpec\" out of range" } mwutil::configureWidget $win rowConfigSpecs \ "tablelist::doRowConfig $row" "tablelist::doRowCget $row" \ [list $opt $val] 0 incr argCount -3 } return "" } #------------------------------------------------------------------------------ # tablelist::configureSubCmd #------------------------------------------------------------------------------ proc tablelist::configureSubCmd {win argList} { synchronize $win displayItems $win variable configSpecs return [mwutil::configureSubCmd $win configSpecs tablelist::doConfig \ tablelist::doCget $argList] } #------------------------------------------------------------------------------ # tablelist::containingSubCmd #------------------------------------------------------------------------------ proc tablelist::containingSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win containing y" } set y [format "%d" [lindex $argList 0]] synchronize $win displayItems $win return [containingRow $win $y] } #------------------------------------------------------------------------------ # tablelist::containingcellSubCmd #------------------------------------------------------------------------------ proc tablelist::containingcellSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win containingcell x y" } set x [format "%d" [lindex $argList 0]] set y [format "%d" [lindex $argList 1]] synchronize $win displayItems $win return [containingRow $win $y],[containingCol $win $x] } #------------------------------------------------------------------------------ # tablelist::containingcolumnSubCmd #------------------------------------------------------------------------------ proc tablelist::containingcolumnSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win containingcolumn x" } set x [format "%d" [lindex $argList 0]] synchronize $win displayItems $win return [containingCol $win $x] } #------------------------------------------------------------------------------ # tablelist::curcellselectionSubCmd #------------------------------------------------------------------------------ proc tablelist::curcellselectionSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win curcellselection" } synchronize $win displayItems $win return [curCellSelection $win] } #------------------------------------------------------------------------------ # tablelist::curselectionSubCmd #------------------------------------------------------------------------------ proc tablelist::curselectionSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win curselection" } synchronize $win displayItems $win return [curSelection $win] } #------------------------------------------------------------------------------ # tablelist::deleteSubCmd #------------------------------------------------------------------------------ proc tablelist::deleteSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs "$win delete firstIndex lastIndex" \ "$win delete indexList" } upvar ::tablelist::ns${win}::data data if {$data(isDisabled)} { return "" } synchronize $win displayItems $win set first [lindex $argList 0] if {$argCount == 1} { if {[llength $first] == 1} { ;# just to save time set index [rowIndex $win [lindex $first 0] 0] return [deleteRows $win $index $index $data(hasListVar)] } elseif {$data(itemCount) == 0} { ;# no items present return "" } else { ;# a bit more work # # Sort the numerical equivalents of the # specified indices in decreasing order # set indexList {} foreach elem $first { set index [rowIndex $win $elem 0] if {$index < 0} { set index 0 } elseif {$index > $data(lastRow)} { set index $data(lastRow) } lappend indexList $index } set indexList [lsort -integer -decreasing $indexList] # # Traverse the sorted index list and ignore any duplicates # set prevIndex -1 foreach index $indexList { if {$index != $prevIndex} { deleteRows $win $index $index $data(hasListVar) set prevIndex $index } } return "" } } else { set first [rowIndex $win $first 0] set last [rowIndex $win [lindex $argList 1] 0] return [deleteRows $win $first $last $data(hasListVar)] } } #------------------------------------------------------------------------------ # tablelist::deletecolumnsSubCmd #------------------------------------------------------------------------------ proc tablelist::deletecolumnsSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs \ "$win deletecolumns firstColumnIndex lastColumnIndex" \ "$win deletecolumns columnIndexList" } upvar ::tablelist::ns${win}::data data if {$data(isDisabled)} { return "" } synchronize $win displayItems $win set first [lindex $argList 0] if {$argCount == 1} { if {[llength $first] == 1} { ;# just to save time set col [colIndex $win [lindex $first 0] 1] set selCells [curCellSelection $win] deleteCols $win $col $col selCells redisplay $win 0 $selCells } elseif {$data(colCount) == 0} { ;# no columns present return "" } else { ;# a bit more work # # Sort the numerical equivalents of the # specified column indices in decreasing order # set colList {} foreach elem $first { lappend colList [colIndex $win $elem 1] } set colList [lsort -integer -decreasing $colList] # # Traverse the sorted column index list and ignore any duplicates # set selCells [curCellSelection $win] set deleted 0 set prevCol -1 foreach col $colList { if {$col != $prevCol} { deleteCols $win $col $col selCells set deleted 1 set prevCol $col } } if {$deleted} { redisplay $win 0 $selCells } } } else { set first [colIndex $win $first 1] set last [colIndex $win [lindex $argList 1] 1] if {$first <= $last} { set selCells [curCellSelection $win] deleteCols $win $first $last selCells redisplay $win 0 $selCells } } return "" } #------------------------------------------------------------------------------ # tablelist::editcellSubCmd #------------------------------------------------------------------------------ proc tablelist::editcellSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win editcell cellIndex" } synchronize $win displayItems $win foreach {row col} [cellIndex $win [lindex $argList 0] 1] {} return [doEditCell $win $row $col 0] } #------------------------------------------------------------------------------ # tablelist::editwintagSubCmd #------------------------------------------------------------------------------ proc tablelist::editwintagSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win editwintag" } upvar ::tablelist::ns${win}::data data return $data(editwinTag) } #------------------------------------------------------------------------------ # tablelist::editwinpathSubCmd #------------------------------------------------------------------------------ proc tablelist::editwinpathSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win editwinpath" } upvar ::tablelist::ns${win}::data data if {[winfo exists $data(bodyFrEd)]} { return $data(bodyFrEd) } else { return "" } } #------------------------------------------------------------------------------ # tablelist::entrypathSubCmd #------------------------------------------------------------------------------ proc tablelist::entrypathSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win entrypath" } upvar ::tablelist::ns${win}::data data if {[winfo exists $data(bodyFrEd)]} { set class [winfo class $data(bodyFrEd)] if {[regexp {^(Mentry|T?Checkbutton)$} $class]} { return "" } else { return $data(editFocus) } } else { return "" } } #------------------------------------------------------------------------------ # tablelist::fillcolumnSubCmd #------------------------------------------------------------------------------ proc tablelist::fillcolumnSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win fillcolumn columnIndex text" } upvar ::tablelist::ns${win}::data data if {$data(isDisabled)} { return "" } synchronize $win displayItems $win set colIdx [colIndex $win [lindex $argList 0] 1] set text [lindex $argList 1] # # Update the item list # set newItemList {} foreach item $data(itemList) { set item [lreplace $item $colIdx $colIdx $text] lappend newItemList $item } set data(itemList) $newItemList # # Update the list variable if present # condUpdateListVar $win # # Adjust the columns and make sure the specified # column will be redisplayed at idle time # adjustColumns $win $colIdx 1 redisplayColWhenIdle $win $colIdx return "" } #------------------------------------------------------------------------------ # tablelist::finisheditingSubCmd #------------------------------------------------------------------------------ proc tablelist::finisheditingSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win finishediting" } synchronize $win displayItems $win return [doFinishEditing $win] } #------------------------------------------------------------------------------ # tablelist::formatinfoSubCmd #------------------------------------------------------------------------------ proc tablelist::formatinfoSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win formatinfo" } upvar ::tablelist::ns${win}::data data return [list $data(fmtKey) $data(fmtRow) $data(fmtCol)] } #------------------------------------------------------------------------------ # tablelist::getSubCmd #------------------------------------------------------------------------------ proc tablelist::getSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs "$win get firstIndex lastIndex" \ "$win get indexList" } synchronize $win set first [lindex $argList 0] # # Get the specified items from the internal list # upvar ::tablelist::ns${win}::data data set result {} if {$argCount == 1} { foreach elem $first { set index [rowIndex $win $elem 0] if {$index >= 0 && $index < $data(itemCount)} { set item [lindex $data(itemList) $index] lappend result [lrange $item 0 $data(lastCol)] } } if {[llength $first] == 1} { return [lindex $result 0] } else { return $result } } else { set first [rowIndex $win $first 0] set last [rowIndex $win [lindex $argList 1] 0] # # Adjust the range to fit within the existing items # if {$first > $data(lastRow)} { return {} } if {$first < 0} { set first 0 } if {$last > $data(lastRow)} { set last $data(lastRow) } foreach item [lrange $data(itemList) $first $last] { lappend result [lrange $item 0 $data(lastCol)] } return $result } } #------------------------------------------------------------------------------ # tablelist::getcellsSubCmd #------------------------------------------------------------------------------ proc tablelist::getcellsSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs \ "$win getcells firstCellIndex lastCellIndex" \ "$win getcells cellIndexList" } synchronize $win set first [lindex $argList 0] # # Get the specified elements from the internal list # upvar ::tablelist::ns${win}::data data set result {} if {$argCount == 1} { foreach elem $first { foreach {row col} [cellIndex $win $elem 1] {} lappend result [lindex [lindex $data(itemList) $row] $col] } if {[llength $first] == 1} { return [lindex $result 0] } else { return $result } } else { foreach {firstRow firstCol} [cellIndex $win $first 1] {} foreach {lastRow lastCol} [cellIndex $win [lindex $argList 1] 1] {} foreach item [lrange $data(itemList) $firstRow $lastRow] { foreach elem [lrange $item $firstCol $lastCol] { lappend result $elem } } return $result } } #------------------------------------------------------------------------------ # tablelist::getcolumnsSubCmd #------------------------------------------------------------------------------ proc tablelist::getcolumnsSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs \ "$win getcolumns firstColumnIndex lastColumnIndex" \ "$win getcolumns columnIndexList" } synchronize $win set first [lindex $argList 0] # # Get the specified columns from the internal list # upvar ::tablelist::ns${win}::data data set result {} if {$argCount == 1} { foreach elem $first { set col [colIndex $win $elem 1] set colResult {} foreach item $data(itemList) { lappend colResult [lindex $item $col] } lappend result $colResult } if {[llength $first] == 1} { return [lindex $result 0] } else { return $result } } else { set first [colIndex $win $first 1] set last [colIndex $win [lindex $argList 1] 1] for {set col $first} {$col <= $last} {incr col} { set colResult {} foreach item $data(itemList) { lappend colResult [lindex $item $col] } lappend result $colResult } return $result } } #------------------------------------------------------------------------------ # tablelist::getkeysSubCmd #------------------------------------------------------------------------------ proc tablelist::getkeysSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs "$win getkeys firstIndex lastIndex" \ "$win getkeys indexList" } synchronize $win set first [lindex $argList 0] # # Get the specified keys from the internal list # upvar ::tablelist::ns${win}::data data set result {} if {$argCount == 1} { foreach elem $first { set index [rowIndex $win $elem 0] if {$index >= 0 && $index < $data(itemCount)} { set item [lindex $data(itemList) $index] lappend result [string range [lindex $item end] 1 end] } } if {[llength $first] == 1} { return [lindex $result 0] } else { return $result } } else { set first [rowIndex $win $first 0] set last [rowIndex $win [lindex $argList 1] 0] # # Adjust the range to fit within the existing items # if {$first > $data(lastRow)} { return {} } if {$first < 0} { set first 0 } if {$last > $data(lastRow)} { set last $data(lastRow) } foreach item [lrange $data(itemList) $first $last] { lappend result [string range [lindex $item end] 1 end] } return $result } } #------------------------------------------------------------------------------ # tablelist::hasattribSubCmd #------------------------------------------------------------------------------ proc tablelist::hasattribSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win hasattrib name" } return [mwutil::hasattribSubCmd $win "widget" [lindex $argList 0]] } #------------------------------------------------------------------------------ # tablelist::hascellattribSubCmd #------------------------------------------------------------------------------ proc tablelist::hascellattribSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win hascellattrib cellIndex name" } synchronize $win foreach {row col} [cellIndex $win [lindex $argList 0] 1] {} upvar ::tablelist::ns${win}::data data set key [lindex [lindex $data(itemList) $row] end] return [mwutil::hasattribSubCmd $win $key,$col [lindex $argList 1]] } #------------------------------------------------------------------------------ # tablelist::hascolumnattribSubCmd #------------------------------------------------------------------------------ proc tablelist::hascolumnattribSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win hascolumnattrib columnIndex name" } synchronize $win set col [colIndex $win [lindex $argList 0] 1] return [mwutil::hasattribSubCmd $win $col [lindex $argList 1]] } #------------------------------------------------------------------------------ # tablelist::hasrowattribSubCmd #------------------------------------------------------------------------------ proc tablelist::hasrowattribSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win hasrowattrib index name" } synchronize $win set rowSpec [lindex $argList 0] set row [rowIndex $win $rowSpec 0] upvar ::tablelist::ns${win}::data data if {$row < 0 || $row > $data(lastRow)} { return -code error "row index \"$rowSpec\" out of range" } set key [lindex [lindex $data(itemList) $row] end] return [mwutil::hasattribSubCmd $win $key [lindex $argList 1]] } #------------------------------------------------------------------------------ # tablelist::imagelabelpathSubCmd #------------------------------------------------------------------------------ proc tablelist::imagelabelpathSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win imagelabelpath cellIndex" } synchronize $win foreach {row col} [cellIndex $win [lindex $argList 0] 1] {} upvar ::tablelist::ns${win}::data data set key [lindex [lindex $data(itemList) $row] end] set w $data(body).l$key,$col if {[winfo exists $w]} { return $w } else { return "" } } #------------------------------------------------------------------------------ # tablelist::indexSubCmd #------------------------------------------------------------------------------ proc tablelist::indexSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win index index" } synchronize $win return [rowIndex $win [lindex $argList 0] 1] } #------------------------------------------------------------------------------ # tablelist::insertSubCmd #------------------------------------------------------------------------------ proc tablelist::insertSubCmd {win argList} { if {[llength $argList] < 1} { mwutil::wrongNumArgs "$win insert index ?item item ...?" } synchronize $win set index [rowIndex $win [lindex $argList 0] 1] upvar ::tablelist::ns${win}::data data return [insertRows $win $index [lrange $argList 1 end] $data(hasListVar)] } #------------------------------------------------------------------------------ # tablelist::insertcolumnlistSubCmd #------------------------------------------------------------------------------ proc tablelist::insertcolumnlistSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win insertcolumnlist columnIndex columnList" } synchronize $win displayItems $win set arg0 [lindex $argList 0] upvar ::tablelist::ns${win}::data data if {[string first $arg0 "end"] == 0 || $arg0 == $data(colCount)} { set col $data(colCount) } else { set col [colIndex $win $arg0 1] } return [insertCols $win $col [lindex $argList 1]] } #------------------------------------------------------------------------------ # tablelist::insertcolumnsSubCmd #------------------------------------------------------------------------------ proc tablelist::insertcolumnsSubCmd {win argList} { if {[llength $argList] < 1} { mwutil::wrongNumArgs "$win insertcolumns columnIndex\ ?width title ?alignment? width title ?alignment? ...?" } synchronize $win displayItems $win set arg0 [lindex $argList 0] upvar ::tablelist::ns${win}::data data if {[string first $arg0 "end"] == 0 || $arg0 == $data(colCount)} { set col $data(colCount) } else { set col [colIndex $win $arg0 1] } return [insertCols $win $col [lrange $argList 1 end]] } #------------------------------------------------------------------------------ # tablelist::insertlistSubCmd #------------------------------------------------------------------------------ proc tablelist::insertlistSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win insertlist index list" } synchronize $win set index [rowIndex $win [lindex $argList 0] 1] upvar ::tablelist::ns${win}::data data return [insertRows $win $index [lindex $argList 1] $data(hasListVar)] } #------------------------------------------------------------------------------ # tablelist::iselemsnippedSubCmd #------------------------------------------------------------------------------ proc tablelist::iselemsnippedSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win iselemsnipped cellIndex fullTextName" } synchronize $win displayItems $win foreach {row col} [cellIndex $win [lindex $argList 0] 1] {} set fullTextName [lindex $argList 1] upvar 2 $fullTextName fullText upvar ::tablelist::ns${win}::data data set item [lindex $data(itemList) $row] set key [lindex $item end] set fullText [lindex $item $col] if {[lindex $data(fmtCmdFlagList) $col]} { set fullText [formatElem $win $key $row $col $fullText] } set fullText [strToDispStr $fullText] set pixels [lindex $data(colList) [expr {2*$col}]] if {$pixels == 0} { ;# convention: dynamic width if {$data($col-maxPixels) > 0 && $data($col-reqPixels) > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } if {$pixels == 0 || $data($col-wrap)} { return 0 } set text $fullText getAuxData $win $key $col auxType auxWidth $pixels set cellFont [getCellFont $win $key $col] incr pixels $data($col-delta) if {[string match "*\n*" $text]} { set list [split $text "\n"] adjustMlElem $win list auxWidth $cellFont $pixels "r" "" set text [join $list "\n"] } else { adjustElem $win text auxWidth $cellFont $pixels "r" "" } return [expr {[string compare $text $fullText] != 0}] } #------------------------------------------------------------------------------ # tablelist::istitlesnippedSubCmd #------------------------------------------------------------------------------ proc tablelist::istitlesnippedSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win istitlesnipped columnIndex fullTextName" } set col [colIndex $win [lindex $argList 0] 1] set fullTextName [lindex $argList 1] upvar 2 $fullTextName fullText upvar ::tablelist::ns${win}::data data set fullText [lindex $data(-columns) [expr {3*$col + 1}]] return $data($col-isSnipped) } #------------------------------------------------------------------------------ # tablelist::itemlistvarSubCmd #------------------------------------------------------------------------------ proc tablelist::itemlistvarSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win itemlistvar" } return ::tablelist::ns${win}::data(itemList) } #------------------------------------------------------------------------------ # tablelist::labelpathSubCmd #------------------------------------------------------------------------------ proc tablelist::labelpathSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win labelpath columnIndex" } set col [colIndex $win [lindex $argList 0] 1] upvar ::tablelist::ns${win}::data data return $data(hdrTxtFrLbl)$col } #------------------------------------------------------------------------------ # tablelist::labelsSubCmd #------------------------------------------------------------------------------ proc tablelist::labelsSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win labels" } upvar ::tablelist::ns${win}::data data set labelList {} for {set col 0} {$col < $data(colCount)} {incr col} { lappend labelList $data(hdrTxtFrLbl)$col } return $labelList } #------------------------------------------------------------------------------ # tablelist::moveSubCmd #------------------------------------------------------------------------------ proc tablelist::moveSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win move sourceIndex targetIndex" } synchronize $win displayItems $win set source [rowIndex $win [lindex $argList 0] 0] set target [rowIndex $win [lindex $argList 1] 1] return [moveRow $win $source $target] } #------------------------------------------------------------------------------ # tablelist::movecolumnSubCmd #------------------------------------------------------------------------------ proc tablelist::movecolumnSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win movecolumn sourceColumnIndex\ targetColumnIndex" } synchronize $win displayItems $win set arg0 [lindex $argList 0] set source [colIndex $win $arg0 1] set arg1 [lindex $argList 1] upvar ::tablelist::ns${win}::data data if {[string first $arg1 "end"] == 0 || $arg1 == $data(colCount)} { set target $data(colCount) } else { set target [colIndex $win $arg1 1] } return [moveCol $win $source $target] } #------------------------------------------------------------------------------ # tablelist::nearestSubCmd #------------------------------------------------------------------------------ proc tablelist::nearestSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win nearest y" } set y [format "%d" [lindex $argList 0]] synchronize $win displayItems $win return [rowIndex $win @0,$y 0] } #------------------------------------------------------------------------------ # tablelist::nearestcellSubCmd #------------------------------------------------------------------------------ proc tablelist::nearestcellSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win nearestcell x y" } set x [format "%d" [lindex $argList 0]] set y [format "%d" [lindex $argList 1]] synchronize $win displayItems $win return [join [cellIndex $win @$x,$y 0] ","] } #------------------------------------------------------------------------------ # tablelist::nearestcolumnSubCmd #------------------------------------------------------------------------------ proc tablelist::nearestcolumnSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win nearestcolumn x" } set x [format "%d" [lindex $argList 0]] synchronize $win displayItems $win return [colIndex $win @$x,0 0] } #------------------------------------------------------------------------------ # tablelist::rejectinputSubCmd #------------------------------------------------------------------------------ proc tablelist::rejectinputSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win rejectinput" } upvar ::tablelist::ns${win}::data data set data(rejected) 1 } #------------------------------------------------------------------------------ # tablelist::resetsortinfoSubCmd #------------------------------------------------------------------------------ proc tablelist::resetsortinfoSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win resetsortinfo" } upvar ::tablelist::ns${win}::data data foreach col $data(sortColList) { set data($col-sortRank) 0 set data($col-sortOrder) "" } set whichWidths {} foreach col $data(arrowColList) { lappend whichWidths l$col } set data(sortColList) {} set data(arrowColList) {} set data(sortOrder) {} if {[llength $whichWidths] > 0} { synchronize $win displayItems $win adjustColumns $win $whichWidths 1 } return "" } #------------------------------------------------------------------------------ # tablelist::rowattribSubCmd #------------------------------------------------------------------------------ proc tablelist::rowattribSubCmd {win argList} { if {[llength $argList] < 1} { mwutil::wrongNumArgs "$win rowattrib index ?name? ?value\ name value ...?" } synchronize $win set rowSpec [lindex $argList 0] set row [rowIndex $win $rowSpec 0] upvar ::tablelist::ns${win}::data data if {$row < 0 || $row > $data(lastRow)} { return -code error "row index \"$rowSpec\" out of range" } set key [lindex [lindex $data(itemList) $row] end] return [mwutil::attribSubCmd $win $key [lrange $argList 1 end]] } #------------------------------------------------------------------------------ # tablelist::rowcgetSubCmd #------------------------------------------------------------------------------ proc tablelist::rowcgetSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win rowcget index option" } synchronize $win set rowArg [lindex $argList 0] set row [rowIndex $win $rowArg 0] upvar ::tablelist::ns${win}::data data if {$row < 0 || $row > $data(lastRow)} { return -code error "row index \"$rowArg\" out of range" } variable rowConfigSpecs set opt [mwutil::fullConfigOpt [lindex $argList 1] rowConfigSpecs] return [doRowCget $row $win $opt] } #------------------------------------------------------------------------------ # tablelist::rowconfigureSubCmd #------------------------------------------------------------------------------ proc tablelist::rowconfigureSubCmd {win argList} { if {[llength $argList] < 1} { mwutil::wrongNumArgs "$win rowconfigure index ?option? ?value\ option value ...?" } synchronize $win displayItems $win variable rowConfigSpecs set rowSpec [lindex $argList 0] set row [rowIndex $win $rowSpec 0] upvar ::tablelist::ns${win}::data data if {$row < 0 || $row > $data(lastRow)} { return -code error "row index \"$rowSpec\" out of range" } return [mwutil::configureSubCmd $win rowConfigSpecs \ "tablelist::doRowConfig $row" "tablelist::doRowCget $row" \ [lrange $argList 1 end]] } #------------------------------------------------------------------------------ # tablelist::scanSubCmd #------------------------------------------------------------------------------ proc tablelist::scanSubCmd {win argList} { if {[llength $argList] != 3} { mwutil::wrongNumArgs "$win scan mark|dragto x y" } set x [format "%d" [lindex $argList 1]] set y [format "%d" [lindex $argList 2]] variable scanCmdOpts set opt [mwutil::fullOpt "option" [lindex $argList 0] $scanCmdOpts] synchronize $win displayItems $win return [doScan $win $opt $x $y] } #------------------------------------------------------------------------------ # tablelist::seeSubCmd #------------------------------------------------------------------------------ proc tablelist::seeSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win see index" } synchronize $win displayItems $win set index [rowIndex $win [lindex $argList 0] 0] return [seeRow $win $index] } #------------------------------------------------------------------------------ # tablelist::seecellSubCmd #------------------------------------------------------------------------------ proc tablelist::seecellSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win seecell cellIndex" } synchronize $win displayItems $win foreach {row col} [cellIndex $win [lindex $argList 0] 0] {} if {[winfo viewable $win]} { return [seeCell $win $row $col] } else { after idle [list tablelist::seeCell $win $row $col] return "" } } #------------------------------------------------------------------------------ # tablelist::seecolumnSubCmd #------------------------------------------------------------------------------ proc tablelist::seecolumnSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win seecolumn columnIndex" } synchronize $win displayItems $win set col [colIndex $win [lindex $argList 0] 0] if {[winfo viewable $win]} { return [seeCell $win [rowIndex $win @0,0 0] $col] } else { after idle [list tablelist::seeCell $win [rowIndex $win @0,0 0] $col] return "" } } #------------------------------------------------------------------------------ # tablelist::selectionSubCmd #------------------------------------------------------------------------------ proc tablelist::selectionSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 2 || $argCount > 3} { mwutil::wrongNumArgs "$win selection option firstIndex lastIndex" \ "$win selection option indexList" } synchronize $win displayItems $win variable selCmdOpts set opt [mwutil::fullOpt "option" [lindex $argList 0] $selCmdOpts] set first [lindex $argList 1] switch $opt { anchor - includes { if {$argCount != 2} { mwutil::wrongNumArgs "$win selection $opt index" } set index [rowIndex $win $first 0] return [rowSelection $win $opt $index $index] } clear - set { if {$argCount == 2} { foreach elem $first { set index [rowIndex $win $elem 0] rowSelection $win $opt $index $index } return "" } else { set first [rowIndex $win $first 0] set last [rowIndex $win [lindex $argList 2] 0] return [rowSelection $win $opt $first $last] } } } } #------------------------------------------------------------------------------ # tablelist::separatorpathSubCmd #------------------------------------------------------------------------------ proc tablelist::separatorpathSubCmd {win argList} { set argCount [llength $argList] if {$argCount > 1} { mwutil::wrongNumArgs "$win separatorpath ?columnIndex?" } upvar ::tablelist::ns${win}::data data if {$argCount == 0} { if {[winfo exists $data(sep)]} { return $data(sep) } else { return "" } } else { set col [colIndex $win [lindex $argList 0] 1] if {$data(-showseparators)} { return $data(sep)$col } else { return "" } } } #------------------------------------------------------------------------------ # tablelist::separatorsSubCmd #------------------------------------------------------------------------------ proc tablelist::separatorsSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win separators" } set sepList {} foreach w [winfo children $win] { if {[regexp {^sep([0-9]+)?$} [winfo name $w]]} { lappend sepList $w } } return [lsort -dictionary $sepList] } #------------------------------------------------------------------------------ # tablelist::sizeSubCmd #------------------------------------------------------------------------------ proc tablelist::sizeSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win size" } synchronize $win upvar ::tablelist::ns${win}::data data return $data(itemCount) } #------------------------------------------------------------------------------ # tablelist::sortSubCmd #------------------------------------------------------------------------------ proc tablelist::sortSubCmd {win argList} { set argCount [llength $argList] if {$argCount > 1} { mwutil::wrongNumArgs "$win sort ?-increasing|-decreasing?" } if {$argCount == 0} { set order -increasing } else { variable _sortOrders set order [mwutil::fullOpt "option" [lindex $argList 0] $_sortOrders] } synchronize $win displayItems $win return [sortItems $win -1 [string range $order 1 end]] } #------------------------------------------------------------------------------ # tablelist::sortbycolumnSubCmd #------------------------------------------------------------------------------ proc tablelist::sortbycolumnSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs "$win sortbycolumn columnIndex\ ?-increasing|-decreasing?" } synchronize $win displayItems $win set col [colIndex $win [lindex $argList 0] 1] if {$argCount == 1} { set order -increasing } else { variable _sortOrders set order [mwutil::fullOpt "option" [lindex $argList 1] $_sortOrders] } return [sortItems $win $col [string range $order 1 end]] } #------------------------------------------------------------------------------ # tablelist::sortbycolumnlistSubCmd #------------------------------------------------------------------------------ proc tablelist::sortbycolumnlistSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs "$win sortbycolumnlist columnIndexList\ ?sortOrderList?" } synchronize $win displayItems $win set sortColList {} foreach elem [lindex $argList 0] { set col [colIndex $win $elem 1] if {[lsearch -exact $sortColList $col] >= 0} { return -code error "duplicate column index \"$elem\"" } lappend sortColList $col } set sortOrderList {} if {$argCount == 2} { variable sortOrders foreach elem [lindex $argList 1] { lappend sortOrderList [mwutil::fullOpt "option" $elem $sortOrders] } } return [sortItems $win $sortColList $sortOrderList] } #------------------------------------------------------------------------------ # tablelist::sortcolumnSubCmd #------------------------------------------------------------------------------ proc tablelist::sortcolumnSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win sortcolumn" } upvar ::tablelist::ns${win}::data data if {[llength $data(sortColList)] == 0} { return -1 } else { return [lindex $data(sortColList) 0] } } #------------------------------------------------------------------------------ # tablelist::sortcolumnlistSubCmd #------------------------------------------------------------------------------ proc tablelist::sortcolumnlistSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win sortcolumnlist" } upvar ::tablelist::ns${win}::data data return $data(sortColList) } #------------------------------------------------------------------------------ # tablelist::sortorderSubCmd #------------------------------------------------------------------------------ proc tablelist::sortorderSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win sortorder" } upvar ::tablelist::ns${win}::data data if {[llength $data(sortColList)] == 0} { return $data(sortOrder) } else { set col [lindex $data(sortColList) 0] return $data($col-sortOrder) } } #------------------------------------------------------------------------------ # tablelist::sortorderlistSubCmd #------------------------------------------------------------------------------ proc tablelist::sortorderlistSubCmd {win argList} { if {[llength $argList] != 0} { mwutil::wrongNumArgs "$win sortorderlist" } upvar ::tablelist::ns${win}::data data set sortOrderList {} foreach col $data(sortColList) { lappend sortOrderList $data($col-sortOrder) } return $sortOrderList } #------------------------------------------------------------------------------ # tablelist::togglecolumnhideSubCmd #------------------------------------------------------------------------------ proc tablelist::togglecolumnhideSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs \ "$win togglecolumnhide firstColumnIndex lastColumnIndex" \ "$win togglecolumnhide columnIndexList" } synchronize $win displayItems $win set first [lindex $argList 0] # # Toggle the value of the -hide option of the specified columns # variable canElide if {!$canElide} { set selCells [curCellSelection $win] } upvar ::tablelist::ns${win}::data data set colIdxList {} if {$argCount == 1} { foreach elem $first { set col [colIndex $win $elem 1] if {$canElide && !$data($col-hide)} { cellSelection $win clear 0 $col $data(lastRow) $col } set data($col-hide) [expr {!$data($col-hide)}] if {$data($col-hide)} { incr data(hiddenColCount) if {$col == $data(editCol)} { doCancelEditing $win } } else { incr data(hiddenColCount) -1 } lappend colIdxList $col } } else { set first [colIndex $win $first 1] set last [colIndex $win [lindex $argList 1] 1] for {set col $first} {$col <= $last} {incr col} { if {$canElide && !$data($col-hide)} { cellSelection $win clear 0 $col $data(lastRow) $col } set data($col-hide) [expr {!$data($col-hide)}] if {$data($col-hide)} { incr data(hiddenColCount) if {$col == $data(editCol)} { doCancelEditing $win } } else { incr data(hiddenColCount) -1 } lappend colIdxList $col } } if {[llength $colIdxList] == 0} { return "" } # # Adjust the columns and redisplay the items # makeColFontAndTagLists $win adjustColumns $win $colIdxList 1 adjustColIndex $win data(anchorCol) 1 adjustColIndex $win data(activeCol) 1 if {$canElide} { adjustElidedTextWhenIdle $win } else { redisplay $win 0 $selCells } if {[string compare $data(-selecttype) "row"] == 0} { foreach row [curSelection $win] { rowSelection $win set $row $row } } return "" } #------------------------------------------------------------------------------ # tablelist::togglerowhideSubCmd #------------------------------------------------------------------------------ proc tablelist::togglerowhideSubCmd {win argList} { set argCount [llength $argList] if {$argCount < 1 || $argCount > 2} { mwutil::wrongNumArgs "$win togglerowhide firstIndex lastIndex" \ "$win togglerowhide indexList" } synchronize $win displayItems $win set first [lindex $argList 0] # # Toggle the value of the -hide option of the specified rows # upvar ::tablelist::ns${win}::data data if {$argCount == 1} { foreach elem $first { set row [rowIndex $win $elem 0] if {$row < 0 || $row > $data(lastRow)} { return -code error "row index \"$elem\" out of range" } doRowConfig $row $win -hide [expr {![doRowCget $row $win -hide]}] } } else { set firstRow [rowIndex $win $first 0] if {$firstRow < 0 || $firstRow > $data(lastRow)} { return -code error "row index \"$first\" out of range" } set lastRow [rowIndex $win [lindex $argList 1] 0] if {$lastRow < 0 || $lastRow > $data(lastRow)} { return -code error "row index \"$last\" out of range" } for {set row $firstRow} {$row <= $lastRow} {incr row} { doRowConfig $row $win -hide [expr {![doRowCget $row $win -hide]}] } } } #------------------------------------------------------------------------------ # tablelist::unsetattribSubCmd #------------------------------------------------------------------------------ proc tablelist::unsetattribSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win unsetattrib name" } return [mwutil::unsetattribSubCmd $win "widget" [lindex $argList 0]] } #------------------------------------------------------------------------------ # tablelist::unsetcellattribSubCmd #------------------------------------------------------------------------------ proc tablelist::unsetcellattribSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win unsetcellattrib cellIndex name" } synchronize $win foreach {row col} [cellIndex $win [lindex $argList 0] 1] {} upvar ::tablelist::ns${win}::data data set key [lindex [lindex $data(itemList) $row] end] return [mwutil::unsetattribSubCmd $win $key,$col [lindex $argList 1]] } #------------------------------------------------------------------------------ # tablelist::unsetcolumnattribSubCmd #------------------------------------------------------------------------------ proc tablelist::unsetcolumnattribSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win unsetcolumnattrib columnIndex name" } synchronize $win set col [colIndex $win [lindex $argList 0] 1] return [mwutil::unsetattribSubCmd $win $col [lindex $argList 1]] } #------------------------------------------------------------------------------ # tablelist::unsetrowattribSubCmd #------------------------------------------------------------------------------ proc tablelist::unsetrowattribSubCmd {win argList} { if {[llength $argList] != 2} { mwutil::wrongNumArgs "$win unsetrowattrib index name" } synchronize $win set rowSpec [lindex $argList 0] set row [rowIndex $win $rowSpec 0] upvar ::tablelist::ns${win}::data data if {$row < 0 || $row > $data(lastRow)} { return -code error "row index \"$rowSpec\" out of range" } set key [lindex [lindex $data(itemList) $row] end] return [mwutil::unsetattribSubCmd $win $key [lindex $argList 1]] } #------------------------------------------------------------------------------ # tablelist::windowpathSubCmd #------------------------------------------------------------------------------ proc tablelist::windowpathSubCmd {win argList} { if {[llength $argList] != 1} { mwutil::wrongNumArgs "$win windowpath cellIndex" } synchronize $win foreach {row col} [cellIndex $win [lindex $argList 0] 1] {} upvar ::tablelist::ns${win}::data data set key [lindex [lindex $data(itemList) $row] end] set w $data(body).f$key,$col.w if {[winfo exists $w]} { return $w } else { return "" } } #------------------------------------------------------------------------------ # tablelist::xviewSubCmd #------------------------------------------------------------------------------ proc tablelist::xviewSubCmd {win argList} { synchronize $win displayItems $win upvar ::tablelist::ns${win}::data data switch [llength $argList] { 0 { # # Command: $win xview # if {$data(-titlecolumns) == 0} { return [$data(hdrTxt) xview] } else { set scrlWindowWidth [getScrlWindowWidth $win] if {$scrlWindowWidth <= 0} { return [list 0 0] } set scrlContentWidth [getScrlContentWidth $win 0 $data(lastCol)] if {$scrlContentWidth == 0} { return [list 0 1] } set scrlXOffset \ [scrlColOffsetToXOffset $win $data(scrlColOffset)] set fraction1 [expr {$scrlXOffset/double($scrlContentWidth)}] set fraction2 [expr {($scrlXOffset + $scrlWindowWidth)/ double($scrlContentWidth)}] if {$fraction2 > 1.0} { set fraction2 1.0 } return [list [format "%g" $fraction1] [format "%g" $fraction2]] } } 1 { # # Command: $win xview # set units [format "%d" [lindex $argList 0]] if {$data(-titlecolumns) == 0} { foreach w [list $data(hdrTxt) $data(body)] { $w xview moveto 0 $w xview scroll $units units } } else { changeScrlColOffset $win $units updateColorsWhenIdle $win } return "" } default { # # Command: $win xview moveto # $win xview scroll units|pages # set argList [mwutil::getScrollInfo $argList] if {$data(-titlecolumns) == 0} { foreach w [list $data(hdrTxt) $data(body)] { eval [list $w xview] $argList } } else { if {[string compare [lindex $argList 0] "moveto"] == 0} { # # Compute the new scrolled column offset # set fraction [lindex $argList 1] set scrlContentWidth \ [getScrlContentWidth $win 0 $data(lastCol)] set pixels [expr {int($fraction*$scrlContentWidth + 0.5)}] set scrlColOffset [scrlXOffsetToColOffset $win $pixels] # # Increase the new scrolled column offset if necessary # if {$pixels + [getScrlWindowWidth $win] >= $scrlContentWidth} { incr scrlColOffset } changeScrlColOffset $win $scrlColOffset } else { set number [lindex $argList 1] if {[string compare [lindex $argList 2] "units"] == 0} { changeScrlColOffset $win \ [expr {$data(scrlColOffset) + $number}] } else { # # Compute the new scrolled column offset # set scrlXOffset \ [scrlColOffsetToXOffset $win $data(scrlColOffset)] set scrlWindowWidth [getScrlWindowWidth $win] set deltaPixels [expr {$number*$scrlWindowWidth}] set pixels [expr {$scrlXOffset + $deltaPixels}] set scrlColOffset [scrlXOffsetToColOffset $win $pixels] # # Adjust the new scrolled column offset if necessary # if {$number < 0 && [getScrlContentWidth $win $scrlColOffset \ $data(lastCol)] - [getScrlContentWidth $win $data(scrlColOffset) \ $data(lastCol)] > -$deltaPixels} { incr scrlColOffset } if {$scrlColOffset == $data(scrlColOffset)} { if {$number < 0} { incr scrlColOffset -1 } elseif {$number > 0} { incr scrlColOffset } } changeScrlColOffset $win $scrlColOffset } } updateColorsWhenIdle $win } variable winSys if {[string compare $winSys "aqua"] == 0 && [winfo viewable $win]} { # # Work around some Tk bugs on Mac OS X Aqua # if {[winfo exists $data(bodyFr)]} { lower $data(bodyFr) raise $data(bodyFr) } update } return "" } } } #------------------------------------------------------------------------------ # tablelist::yviewSubCmd #------------------------------------------------------------------------------ proc tablelist::yviewSubCmd {win argList} { synchronize $win displayItems $win upvar ::tablelist::ns${win}::data data set w $data(body) switch [llength $argList] { 0 { # # Command: $win yview # set totalNonHiddenCount \ [expr {$data(itemCount) - $data(hiddenRowCount)}] if {$totalNonHiddenCount == 0} { return [list 0 1] } set btmY [expr {[winfo height $w] - 1}] set topTextIdx [$w index @0,0] set btmTextIdx [$w index @0,$btmY] set topRow [expr {int($topTextIdx) - 1}] set btmRow [expr {int($btmTextIdx) - 1}] foreach {x y width height baselinePos} [$w dlineinfo $topTextIdx] {} if {$y < 0} { ;# top row incomplete incr topRow } foreach {x y width height baselinePos} [$w dlineinfo $btmTextIdx] {} set y2 [expr {$y + $height}] if {[$w index @0,$y] == [$w index @0,$y2]} { ;# btm row incomplete incr btmRow -1 } set upperNonHiddenCount \ [getNonHiddenRowCount $win 0 [expr {$topRow - 1}]] set winNonHiddenCount [getNonHiddenRowCount $win $topRow $btmRow] set fraction1 [expr {$upperNonHiddenCount/ double($totalNonHiddenCount)}] set fraction2 [expr {($upperNonHiddenCount + $winNonHiddenCount)/ double($totalNonHiddenCount)}] return [list [format "%g" $fraction1] [format "%g" $fraction2]] } 1 { # # Command: $win yview # set units [format "%d" [lindex $argList 0]] $w yview [nonHiddenRowOffsetToRowIndex $win $units] adjustElidedText $win updateColorsWhenIdle $win adjustSepsWhenIdle $win updateVScrlbarWhenIdle $win return "" } default { # # Command: $win yview moveto # $win yview scroll units|pages # set argList [mwutil::getScrollInfo $argList] if {[string compare [lindex $argList 0] "moveto"] == 0} { set fraction [lindex $argList 1] set totalNonHiddenCount \ [expr {$data(itemCount) - $data(hiddenRowCount)}] set offset [expr {int($fraction*$totalNonHiddenCount + 0.5)}] $w yview [nonHiddenRowOffsetToRowIndex $win $offset] } else { set number [lindex $argList 1] if {[string compare [lindex $argList 2] "units"] == 0} { set topRow [expr {int([$w index @0,0]) - 1}] set upperNonHiddenCount \ [getNonHiddenRowCount $win 0 [expr {$topRow - 1}]] set offset [expr {$upperNonHiddenCount + $number}] $w yview [nonHiddenRowOffsetToRowIndex $win $offset] } else { set absNumber [expr {abs($number)}] set btmY [expr {[winfo height $w] - 1}] for {set n 0} {$n < $absNumber} {incr n} { set topRow [expr {int([$w index @0,0]) - 1}] set btmRow [expr {int([$w index @0,$btmY]) - 1}] set upperNonHiddenCount \ [getNonHiddenRowCount $win 0 [expr {$topRow - 1}]] set winNonHiddenCount \ [getNonHiddenRowCount $win $topRow $btmRow] set delta [expr {$winNonHiddenCount - 2}] if {$number < 0} { set delta [expr {(-1)*$delta}] } set offset [expr {$upperNonHiddenCount + $delta}] $w yview [nonHiddenRowOffsetToRowIndex $win $offset] } } } adjustElidedText $win updateColorsWhenIdle $win adjustSepsWhenIdle $win updateVScrlbarWhenIdle $win variable winSys if {[string compare $winSys "aqua"] == 0 && [winfo viewable $win]} { # # Work around some Tk bugs on Mac OS X Aqua # if {[winfo exists $data(bodyFr)]} { lower $data(bodyFr) raise $data(bodyFr) } update } return "" } } } #------------------------------------------------------------------------------ # tablelist::cellSelection # # Processes the tablelist cellselection subcommand. #------------------------------------------------------------------------------ proc tablelist::cellSelection {win opt firstRow firstCol lastRow lastCol} { upvar ::tablelist::ns${win}::data data if {$data(isDisabled) && [string compare $opt "includes"] != 0} { return "" } switch $opt { anchor { # # Adjust the row and column indices to fit # within the existing non-hidden elements # adjustRowIndex $win firstRow 1 adjustColIndex $win firstCol 1 set data(anchorRow) $firstRow set data(anchorCol) $firstCol return "" } clear { # # Adjust the row and column indices # to fit within the existing elements # if {$data(itemCount) == 0 || $data(colCount) == 0} { return "" } adjustRowIndex $win firstRow adjustColIndex $win firstCol adjustRowIndex $win lastRow adjustColIndex $win lastCol # # Swap the indices if necessary # if {$lastRow < $firstRow} { set tmp $firstRow set firstRow $lastRow set lastRow $tmp } if {$lastCol < $firstCol} { set tmp $firstCol set firstCol $lastCol set lastCol $tmp } # # Shrink the column range to be delimited by non-hidden columns # while {$firstCol <= $lastCol && $data($firstCol-hide)} { incr firstCol } if {$firstCol > $lastCol} { return "" } while {$lastCol >= $firstCol && $data($lastCol-hide)} { incr lastCol -1 } set firstTextIdx [expr {$firstRow + 1}].0 set lastTextIdx [expr {$lastRow + 1}].end # # Find the (partly) selected lines of the body text # widget in the text range specified by the two indices # set w $data(body) variable canElide variable elide set selRange [$w tag nextrange select $firstTextIdx $lastTextIdx] while {[llength $selRange] != 0} { set selStart [lindex $selRange 0] set line [expr {int($selStart)}] set row [expr {$line - 1}] set key [lindex [lindex $data(itemList) $row] end] # # Deselect the relevant elements of the row and handle # the -(select)background and -(select)foreground # cell and column configuration options for them # findTabs $win $line $firstCol $lastCol firstTabIdx lastTabIdx set textIdx1 $firstTabIdx for {set col $firstCol} {$col <= $lastCol} {incr col} { if {$data($col-hide) && !$canElide} { continue } set textIdx2 \ [$w search $elide "\t" $textIdx1+1c $lastTabIdx+1c]+1c $w tag remove select $textIdx1 $textIdx2 foreach optTail {background foreground} { set opt -select$optTail foreach name [list $col$opt $key$opt $key,$col$opt] \ level [list col row cell] { if {[info exists data($name)]} { $w tag remove $level$opt-$data($name) \ $textIdx1 $textIdx2 } } foreach name [list $col-$optTail $key-$optTail \ $key,$col-$optTail] \ level [list col row cell] { if {[info exists data($name)]} { $w tag add $level-$optTail-$data($name) \ $textIdx1 $textIdx2 } } } set textIdx1 $textIdx2 } set selRange \ [$w tag nextrange select "$selStart lineend" $lastTextIdx] } updateColorsWhenIdle $win return "" } includes { variable canElide if {$firstRow < 0 || $firstRow > $data(lastRow) || \ $firstCol < 0 || $firstCol > $data(lastCol) || ($data($firstCol-hide) && !$canElide)} { return 0 } findTabs $win [expr {$firstRow + 1}] $firstCol $firstCol \ tabIdx1 tabIdx2 if {[lsearch -exact [$data(body) tag names $tabIdx1] select] < 0} { return 0 } else { return 1 } } set { # # Adjust the row and column indices # to fit within the existing elements # if {$data(itemCount) == 0 || $data(colCount) == 0} { return "" } adjustRowIndex $win firstRow adjustColIndex $win firstCol adjustRowIndex $win lastRow adjustColIndex $win lastCol # # Swap the indices if necessary # if {$lastRow < $firstRow} { set tmp $firstRow set firstRow $lastRow set lastRow $tmp } if {$lastCol < $firstCol} { set tmp $firstCol set firstCol $lastCol set lastCol $tmp } # # Shrink the column range to be delimited by non-hidden columns # while {$firstCol <= $lastCol && $data($firstCol-hide)} { incr firstCol } if {$firstCol > $lastCol} { return "" } while {$lastCol >= $firstCol && $data($lastCol-hide)} { incr lastCol -1 } set w $data(body) variable canElide variable elide for {set row $firstRow; set line [expr {$firstRow + 1}]} \ {$row <= $lastRow} {set row $line; incr line} { # # Check whether the row is selectable and non-hidden # set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key-selectable)] || [info exists data($key-hide)]} { continue } # # Select the relevant non-hidden elements of the row and # handle the -(select)background and -(select)foreground # cell and column configuration options for them # findTabs $win $line $firstCol $lastCol firstTabIdx lastTabIdx set textIdx1 $firstTabIdx for {set col $firstCol} {$col <= $lastCol} {incr col} { if {$data($col-hide) && !$canElide} { continue } set textIdx2 \ [$w search $elide "\t" $textIdx1+1c $lastTabIdx+1c]+1c if {$data($col-hide)} { set textIdx1 $textIdx2 continue } $w tag add select $textIdx1 $textIdx2 foreach optTail {background foreground} { set opt -select$optTail foreach name [list $col$opt $key$opt $key,$col$opt] \ level [list col row cell] { if {[info exists data($name)]} { $w tag add $level$opt-$data($name) \ $textIdx1 $textIdx2 } } foreach name [list $col-$optTail $key-$optTail \ $key,$col-$optTail] \ level [list col row cell] { if {[info exists data($name)]} { set tag $level-$optTail-$data($name) $w tag remove $level-$optTail-$data($name) \ $textIdx1 $textIdx2 } } } set textIdx1 $textIdx2 } } # # If the selection is exported and there are any selected # cells in the widget then make win the new owner of the # PRIMARY selection and register a callback to be invoked # when it loses ownership of the PRIMARY selection # if {$data(-exportselection) && [llength [$w tag nextrange select 1.0]] != 0} { selection own -command \ [list ::tablelist::lostSelection $win] $win } updateColorsWhenIdle $win return "" } } } #------------------------------------------------------------------------------ # tablelist::colWidth # # Processes the tablelist columnwidth subcommand. #------------------------------------------------------------------------------ proc tablelist::colWidth {win col opt} { upvar ::tablelist::ns${win}::data data set pixels [lindex $data(colList) [expr {2*$col}]] if {$pixels == 0} { ;# convention: dynamic width set pixels $data($col-reqPixels) if {$data($col-maxPixels) > 0} { if {$pixels > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } } switch -- $opt { -requested { return $pixels } -stretched { return [expr {$pixels + $data($col-delta)}] } -total { return [expr {$pixels + $data($col-delta) + 2*$data(charWidth)}] } } } #------------------------------------------------------------------------------ # tablelist::containingRow # # Processes the tablelist containing subcommand. #------------------------------------------------------------------------------ proc tablelist::containingRow {win y} { upvar ::tablelist::ns${win}::data data if {$data(itemCount) == 0} { return -1 } set row [rowIndex $win @0,$y 0] set w $data(body) incr y -[winfo y $w] if {$y < 0} { return -1 } set dlineinfo [$w dlineinfo [expr {double($row + 1)}]] if {$y < [lindex $dlineinfo 1] + [lindex $dlineinfo 3]} { return $row } else { return -1 } } #------------------------------------------------------------------------------ # tablelist::containingCol # # Processes the tablelist containingcolumn subcommand. #------------------------------------------------------------------------------ proc tablelist::containingCol {win x} { upvar ::tablelist::ns${win}::data data if {$x < [winfo x $data(body)]} { return -1 } set col [colIndex $win @$x,0 0] if {$col < 0} { return -1 } set lbl $data(hdrTxtFrLbl)$col if {$x + [winfo rootx $win] < [winfo width $lbl] + [winfo rootx $lbl]} { return $col } else { return -1 } } #------------------------------------------------------------------------------ # tablelist::curCellSelection # # Processes the tablelist curcellselection subcommand. #------------------------------------------------------------------------------ proc tablelist::curCellSelection {win {getKeys 0}} { variable canElide variable elide upvar ::tablelist::ns${win}::data data # # Find the (partly) selected lines of the body text widget # set result {} set w $data(body) set selRange [$w tag nextrange select 1.0] while {[llength $selRange] != 0} { foreach {selStart selEnd} $selRange {} set line [expr {int($selStart)}] set row [expr {$line - 1}] # # Get the index of the column starting at the text position selStart # set textIdx $line.0 for {set col 0} {$col < $data(colCount)} {incr col} { if {!$data($col-hide) || $canElide} { if {[$w compare $textIdx == $selStart]} { set firstCol $col break } else { set textIdx [$w search $elide "\t" $textIdx+1c $selEnd]+1c } } } # # Process the columns, starting at the found one # and ending just before the text position selEnd # if {$getKeys} { set key [lindex [lindex $data(itemList) $row] end] } set textIdx [$w search $elide "\t" $textIdx+1c $selEnd]+1c for {set col $firstCol} {$col < $data(colCount)} {incr col} { if {!$data($col-hide) || $canElide} { if {$getKeys} { lappend result $key $col } else { lappend result $row,$col } if {[$w compare $textIdx == $selEnd]} { break } else { set textIdx [$w search $elide "\t" $textIdx+1c $selEnd]+1c } } } set selRange [$w tag nextrange select $selEnd] } return $result } #------------------------------------------------------------------------------ # tablelist::curSelection # # Processes the tablelist curselection subcommand. #------------------------------------------------------------------------------ proc tablelist::curSelection win { # # Find the (partly) selected lines of the body text widget # set result {} upvar ::tablelist::ns${win}::data data set w $data(body) set selRange [$w tag nextrange select 1.0] while {[llength $selRange] != 0} { set selStart [lindex $selRange 0] lappend result [expr {int($selStart) - 1}] set selRange [$w tag nextrange select "$selStart lineend"] } return $result } #------------------------------------------------------------------------------ # tablelist::deleteRows # # Processes the tablelist delete subcommand. #------------------------------------------------------------------------------ proc tablelist::deleteRows {win first last updateListVar} { # # Adjust the range to fit within the existing items # if {$first < 0} { set first 0 } upvar ::tablelist::ns${win}::data data \ ::tablelist::ns${win}::attribs attribs if {$last > $data(lastRow)} { set last $data(lastRow) } set count [expr {$last - $first + 1}] if {$count <= 0} { return "" } # # Check whether the width of any dynamic-width # column might be affected by the deletion # set w $data(body) set itemListRange [lrange $data(itemList) $first $last] if {$count == $data(itemCount)} { set colWidthsChanged 1 ;# just to save time set data(seqNum) -1 set data(freeKeyList) {} } else { variable canElide set colWidthsChanged 0 set snipStr $data(-snipstring) set row 0 foreach item $itemListRange { # # Format the item # set key [lindex $item end] set dispItem [lrange $item 0 $data(lastCol)] if {$data(hasFmtCmds)} { set dispItem [formatItem $win $key $row $dispItem] } set col 0 foreach text [strToDispStr $dispItem] \ {pixels alignment} $data(colList) { if {($data($col-hide) && !$canElide) || $pixels != 0} { incr col continue } getAuxData $win $key $col auxType auxWidth set cellFont [getCellFont $win $key $col] set elemWidth [getElemWidth $win $text $auxWidth $cellFont] if {$elemWidth == $data($col-elemWidth) && [incr data($col-widestCount) -1] == 0} { set colWidthsChanged 1 break } incr col } if {$colWidthsChanged} { break } incr row } } # # Delete the given items from the body text widget. Interestingly, # for a large number of items it is much more efficient to delete # each line individually than to invoke a global delete command. # set textIdx1 [expr {double($first + 1)}] set textIdx2 [expr {double($first + 2)}] foreach item $itemListRange { $w delete $textIdx1 $textIdx2 set key [lindex $item end] if {$count != $data(itemCount)} { lappend data(freeKeyList) $key } foreach opt {-background -foreground -font} { if {[info exists data($key$opt)]} { unset data($key$opt) incr data(rowTagRefCount) -1 } } if {[info exists data($key-hide)]} { unset data($key-hide) incr data(hiddenRowCount) -1 } foreach opt {-name -selectable -selectbackground -selectforeground} { if {[info exists data($key$opt)]} { unset data($key$opt) } } foreach name [array names attribs $key-*] { unset attribs($name) } for {set col 0} {$col < $data(colCount)} {incr col} { foreach opt {-background -foreground -font} { if {[info exists data($key,$col$opt)]} { unset data($key,$col$opt) incr data(cellTagRefCount) -1 } } foreach opt {-editable -editwindow -selectbackground -selectforeground -windowdestroy} { if {[info exists data($key,$col$opt)]} { unset data($key,$col$opt) } } if {[info exists data($key,$col-image)]} { unset data($key,$col-image) incr data(imgCount) -1 } if {[info exists data($key,$col-window)]} { unset data($key,$col-window) unset data($key,$col-reqWidth) unset data($key,$col-reqHeight) incr data(winCount) -1 } } foreach name [array names attribs $key,*-*] { unset attribs($name) } } # # Delete the given items from the internal list # set data(itemList) [lreplace $data(itemList) $first $last] incr data(itemCount) -$count incr data(lastRow) -$count # # Delete the given items from the list variable if needed # if {$updateListVar} { upvar #0 $data(-listvariable) var trace vdelete var wu $data(listVarTraceCmd) set var [lreplace $var $first $last] trace variable var wu $data(listVarTraceCmd) } # # Update the indices anchorRow and activeRow # if {$first <= $data(anchorRow)} { incr data(anchorRow) -$count if {$data(anchorRow) < $first} { set data(anchorRow) $first } adjustRowIndex $win data(anchorRow) 1 } if {$last < $data(activeRow)} { incr data(activeRow) -$count adjustRowIndex $win data(activeRow) 1 } elseif {$first <= $data(activeRow)} { set data(activeRow) $first adjustRowIndex $win data(activeRow) 1 } # # Update data(editRow) if the edit window is present # if {$data(editRow) >= 0} { set data(editRow) [lsearch $data(itemList) "* $data(editKey)"] } # # Adjust the heights of the body text widget # and of the listbox child, if necessary # if {$data(-height) <= 0} { set nonHiddenRowCount [expr {$data(itemCount) - $data(hiddenRowCount)}] $w configure -height $nonHiddenRowCount $data(lb) configure -height $nonHiddenRowCount } # # Invalidate the list of the row indices indicating the # non-hidden rows, adjust the columns if necessary, and # schedule some operations for execution at idle time # set data(nonHiddenRowList) {-1} if {$colWidthsChanged} { adjustColumns $win allCols 1 } adjustElidedTextWhenIdle $win makeStripesWhenIdle $win adjustSepsWhenIdle $win updateVScrlbarWhenIdle $win showLineNumbersWhenIdle $win return "" } #------------------------------------------------------------------------------ # tablelist::deleteCols # # Processes the tablelist deletecolumns subcommand. #------------------------------------------------------------------------------ proc tablelist::deleteCols {win first last selCellsName} { upvar ::tablelist::ns${win}::data data \ ::tablelist::ns${win}::attribs attribs $selCellsName selCells # # Delete the data and attributes corresponding to the given range # for {set col $first} {$col <= $last} {incr col} { if {$data($col-hide)} { incr data(hiddenColCount) -1 } deleteColData $win $col deleteColAttribs $win $col set selCells [deleteColFromCellList $selCells $col] } # # Shift the elements of data and attribs corresponding to the # column indices > last to the left by last - first + 1 positions # for {set oldCol [expr {$last + 1}]; set newCol $first} \ {$oldCol < $data(colCount)} {incr oldCol; incr newCol} { moveColData data data imgs $oldCol $newCol moveColAttribs attribs attribs $oldCol $newCol set selCells [replaceColInCellList $selCells $oldCol $newCol] } # # Update the item list # set newItemList {} foreach item $data(itemList) { set item [lreplace $item $first $last] lappend newItemList $item } set data(itemList) $newItemList # # Update the list variable if present # condUpdateListVar $win # # Set up and adjust the columns, and rebuild some columns-related lists # setupColumns $win \ [lreplace $data(-columns) [expr {3*$first}] [expr {3*$last + 2}]] 1 makeColFontAndTagLists $win makeSortAndArrowColLists $win adjustColumns $win {} 1 # # Reconfigure the relevant column labels # for {set col $first} {$col < $data(colCount)} {incr col} { reconfigColLabels $win imgs $col } # # Update the indices anchorCol and activeCol # set count [expr {$last - $first + 1}] if {$first <= $data(anchorCol)} { incr data(anchorCol) -$count if {$data(anchorCol) < $first} { set data(anchorCol) $first } adjustColIndex $win data(anchorCol) 1 } if {$last < $data(activeCol)} { incr data(activeCol) -$count adjustColIndex $win data(activeCol) 1 } elseif {$first <= $data(activeCol)} { set data(activeCol) $first adjustColIndex $win data(activeCol) 1 } } #------------------------------------------------------------------------------ # tablelist::insertRows # # Processes the tablelist insert and insertlist subcommands. #------------------------------------------------------------------------------ proc tablelist::insertRows {win index argList updateListVar} { set argCount [llength $argList] upvar ::tablelist::ns${win}::data data if {$argCount == 0 || $data(isDisabled)} { return "" } if {$index < $data(itemCount)} { displayItems $win } if {$index < 0} { set index 0 } elseif {$index > $data(itemCount)} { set index $data(itemCount) } # # Insert the items into the internal list # set appending [expr {$index == $data(itemCount)}] set row $index foreach item $argList { # # Adjust the item # set item [adjustItem $item $data(colCount)] # # Get a free key for the new item # if {[llength $data(freeKeyList)] == 0} { set key k[incr data(seqNum)] } else { set key [lindex $data(freeKeyList) 0] set data(freeKeyList) [lrange $data(freeKeyList) 1 end] } # # Insert the item into the list variable if needed # if {$updateListVar} { upvar #0 $data(-listvariable) var trace vdelete var wu $data(listVarTraceCmd) if {$appending} { lappend var $item ;# this works much faster } else { set var [linsert $var $row $item] } trace variable var wu $data(listVarTraceCmd) } # # Insert the item into the internal list # lappend item $key if {$appending} { lappend data(itemList) $item ;# this works much faster } else { set data(itemList) [linsert $data(itemList) $row $item] } lappend data(rowsToDisplay) $row incr row } incr data(itemCount) $argCount set data(lastRow) [expr {$data(itemCount) - 1}] if {![info exists data(dispId)]} { # # Arrange for the inserted items to be displayed at idle time # set data(dispId) [after idle [list tablelist::displayItems $win]] } # # Update the indices anchorRow and activeRow # if {$index <= $data(anchorRow)} { incr data(anchorRow) $argCount adjustRowIndex $win data(anchorRow) 1 } if {$index <= $data(activeRow)} { incr data(activeRow) $argCount adjustRowIndex $win data(activeRow) 1 } # # Update data(editRow) if the edit window is present # if {$data(editRow) >= 0} { set data(editRow) [lsearch $data(itemList) "* $data(editKey)"] } return "" } #------------------------------------------------------------------------------ # tablelist::displayItems # # This procedure is invoked either as an idle callback after inserting some # items into the internal list of the tablelist widget win, or directly, upon # execution of some widget commands. It displays the inserted items. #------------------------------------------------------------------------------ proc tablelist::displayItems win { # # Nothing to do if there are no items to display # upvar ::tablelist::ns${win}::data data if {![info exists data(dispId)]} { return "" } # # Here we are in the case that the procedure was scheduled for # execution at idle time. However, it might have been invoked # directly, before the idle time occured; in this case we should # cancel the execution of the previously scheduled idle callback. # after cancel $data(dispId) ;# no harm if data(dispId) is no longer valid unset data(dispId) # # Insert the items into the body text widget and into the internal list # variable canElide variable snipSides set w $data(body) set widgetFont $data(-font) set snipStr $data(-snipstring) set padY [expr {[$w cget -spacing1] == 0}] set wasEmpty [expr {[llength $data(rowsToDisplay)] == $data(itemCount)}] set isEmpty $wasEmpty set colWidthsChanged 0 foreach row $data(rowsToDisplay) { set line [expr {$row + 1}] set item [lindex $data(itemList) $row] set key [lindex $item end] # # Format the item # set dispItem [lrange $item 0 $data(lastCol)] if {$data(hasFmtCmds)} { set dispItem [formatItem $win $key $row $dispItem] } if {$isEmpty} { set isEmpty 0 } else { $w insert $line.0 "\n" } if {$data(hiddenRowCount) != 0} { $w tag remove hiddenRow $line.0 } set multilineData {} set col 0 if {$data(hasColTags)} { set insertArgs {} foreach text [strToDispStr $dispItem] \ colFont $data(colFontList) \ colTags $data(colTagsList) \ {pixels alignment} $data(colList) { if {$data($col-hide) && !$canElide} { incr col continue } # # Update the column width or clip the element if necessary # set multiline [string match "*\n*" $text] if {$pixels == 0} { ;# convention: dynamic width if {$multiline} { set list [split $text "\n"] set textWidth [getListWidth $win $list $colFont] } else { set textWidth \ [font measure $colFont -displayof $win $text] } if {$data($col-maxPixels) > 0} { if {$textWidth > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } if {$textWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$textWidth > $data($col-elemWidth)} { set data($col-elemWidth) $textWidth set data($col-widestCount) 1 if {$textWidth > $data($col-reqPixels)} { set data($col-reqPixels) $textWidth set colWidthsChanged 1 } } } if {$pixels != 0} { incr pixels $data($col-delta) if {$data($col-wrap) && !$multiline} { if {[font measure $colFont -displayof $win $text] > $pixels} { set multiline 1 } } set snipSide \ $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { if {$data($col-wrap)} { set snipSide "" } set list [split $text "\n"] set text [joinList $win $list $colFont \ $pixels $snipSide $snipStr] } else { set text [strRange $win $text $colFont \ $pixels $snipSide $snipStr] } } if {$multiline} { lappend insertArgs "\t\t" $colTags lappend multilineData $col $text $colFont $pixels $alignment } else { lappend insertArgs "\t$text\t" $colTags } incr col } # # Insert the item into the body text widget # if {[llength $insertArgs] != 0} { eval [list $w insert $line.0] $insertArgs } } else { set insertStr "" foreach text [strToDispStr $dispItem] \ {pixels alignment} $data(colList) { if {$data($col-hide) && !$canElide} { incr col continue } # # Update the column width or clip the element if necessary # set multiline [string match "*\n*" $text] if {$pixels == 0} { ;# convention: dynamic width if {$multiline} { set list [split $text "\n"] set textWidth [getListWidth $win $list $widgetFont] } else { set textWidth \ [font measure $widgetFont -displayof $win $text] } if {$data($col-maxPixels) > 0} { if {$textWidth > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } if {$textWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$textWidth > $data($col-elemWidth)} { set data($col-elemWidth) $textWidth set data($col-widestCount) 1 if {$textWidth > $data($col-reqPixels)} { set data($col-reqPixels) $textWidth set colWidthsChanged 1 } } } if {$pixels != 0} { incr pixels $data($col-delta) if {$data($col-wrap) && !$multiline} { if {[font measure $widgetFont -displayof $win $text] > $pixels} { set multiline 1 } } set snipSide \ $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { if {$data($col-wrap)} { set snipSide "" } set list [split $text "\n"] set text [joinList $win $list $widgetFont \ $pixels $snipSide $snipStr] } else { set text [strRange $win $text $widgetFont \ $pixels $snipSide $snipStr] } } if {$multiline} { append insertStr "\t\t" lappend multilineData $col $text $widgetFont \ $pixels $alignment } else { append insertStr "\t$text\t" } incr col } # # Insert the item into the body text widget # $w insert $line.0 $insertStr } # # Embed the message widgets displaying multiline elements # foreach {col text font pixels alignment} $multilineData { findTabs $win $line $col $col tabIdx1 tabIdx2 set msgScript [list ::tablelist::displayText $win $key \ $col $text $font $pixels $alignment] $w window create $tabIdx2 -pady $padY -create $msgScript } } unset data(rowsToDisplay) # # Adjust the heights of the body text widget # and of the listbox child, if necessary # if {$data(-height) <= 0} { set nonHiddenRowCount [expr {$data(itemCount) - $data(hiddenRowCount)}] $w configure -height $nonHiddenRowCount $data(lb) configure -height $nonHiddenRowCount } # # Invalidate the list of the row indices indicating the # non-hidden rows, adjust the columns if necessary, and # schedule some operations for execution at idle time # set data(nonHiddenRowList) {-1} if {$colWidthsChanged} { adjustColumns $win {} 1 } adjustElidedTextWhenIdle $win makeStripesWhenIdle $win adjustSepsWhenIdle $win updateVScrlbarWhenIdle $win showLineNumbersWhenIdle $win activeTrace $win data activeRow w if {$wasEmpty} { $w xview moveto [lindex [$data(hdrTxt) xview] 0] } } #------------------------------------------------------------------------------ # tablelist::insertCols # # Processes the tablelist insertcolumns and insertcolumnlist subcommands. #------------------------------------------------------------------------------ proc tablelist::insertCols {win colIdx argList} { set argCount [llength $argList] upvar ::tablelist::ns${win}::data data \ ::tablelist::ns${win}::attribs attribs if {$argCount == 0 || $data(isDisabled)} { return "" } # # Check the syntax of argList and get the number of columns to be inserted # variable alignments set count 0 for {set n 0} {$n < $argCount} {incr n} { # # Check the column width # format "%d" [lindex $argList $n] ;# integer check with error message # # Check whether the column title is present # if {[incr n] == $argCount} { return -code error "column title missing" } # # Check the column alignment # set alignment left if {[incr n] < $argCount} { set next [lindex $argList $n] if {[catch {format "%d" $next}] == 0} { ;# integer check incr n -1 } else { mwutil::fullOpt "alignment" $next $alignments } } incr count } # # Shift the elements of data and attribs corresponding to the # column indices >= colIdx to the right by count positions # set selCells [curCellSelection $win] for {set oldCol $data(lastCol); set newCol [expr {$oldCol + $count}]} \ {$oldCol >= $colIdx} {incr oldCol -1; incr newCol -1} { moveColData data data imgs $oldCol $newCol moveColAttribs attribs attribs $oldCol $newCol set selCells [replaceColInCellList $selCells $oldCol $newCol] } # # Update the item list # set emptyStrs {} for {set n 0} {$n < $count} {incr n} { lappend emptyStrs "" } set newItemList {} foreach item $data(itemList) { set item [eval [list linsert $item $colIdx] $emptyStrs] lappend newItemList $item } set data(itemList) $newItemList # # Update the list variable if present # condUpdateListVar $win # # Set up and adjust the columns, and rebuild some columns-related lists # setupColumns $win \ [eval [list linsert $data(-columns) [expr {3*$colIdx}]] $argList] 1 makeColFontAndTagLists $win makeSortAndArrowColLists $win set limit [expr {$colIdx + $count}] set colIdxList {} for {set col $colIdx} {$col < $limit} {incr col} { lappend colIdxList $col } adjustColumns $win $colIdxList 1 # # Reconfigure the relevant column labels # for {set col $limit} {$col < $data(colCount)} {incr col} { reconfigColLabels $win imgs $col } # # Redisplay the items # redisplay $win 0 $selCells # # Update the indices anchorCol and activeCol # if {$colIdx <= $data(anchorCol)} { incr data(anchorCol) $argCount adjustColIndex $win data(anchorCol) 1 } if {$colIdx <= $data(activeCol)} { incr data(activeCol) $argCount adjustColIndex $win data(activeCol) 1 } return "" } #------------------------------------------------------------------------------ # tablelist::doScan # # Processes the tablelist scan subcommand. #------------------------------------------------------------------------------ proc tablelist::doScan {win opt x y} { upvar ::tablelist::ns${win}::data data set w $data(body) incr x -[winfo x $w] incr y -[winfo y $w] if {$data(-titlecolumns) == 0} { $w scan $opt $x $y $data(hdrTxt) scan $opt $x 0 if {[string compare $opt "dragto"] == 0} { adjustElidedText $win updateColorsWhenIdle $win adjustSepsWhenIdle $win updateVScrlbarWhenIdle $win } } elseif {[string compare $opt "mark"] == 0} { $w scan mark 0 $y set data(scanMarkX) $x set data(scanMarkXOffset) \ [scrlColOffsetToXOffset $win $data(scrlColOffset)] } else { $w scan dragto 0 $y # # Compute the new scrolled x offset by amplifying the # difference between the current horizontal position and # the place where the scan started (the "mark" position) # set scrlXOffset \ [expr {$data(scanMarkXOffset) - 10*($x - $data(scanMarkX))}] set maxScrlXOffset [scrlColOffsetToXOffset $win \ [getMaxScrlColOffset $win]] if {$scrlXOffset > $maxScrlXOffset} { set scrlXOffset $maxScrlXOffset set data(scanMarkX) $x set data(scanMarkXOffset) $maxScrlXOffset } elseif {$scrlXOffset < 0} { set scrlXOffset 0 set data(scanMarkX) $x set data(scanMarkXOffset) 0 } # # Change the scrolled column offset and adjust the elided text # changeScrlColOffset $win [scrlXOffsetToColOffset $win $scrlXOffset] adjustElidedText $win updateColorsWhenIdle $win adjustSepsWhenIdle $win updateVScrlbarWhenIdle $win } return "" } #------------------------------------------------------------------------------ # tablelist::seeRow # # Processes the tablelist see subcommand. #------------------------------------------------------------------------------ proc tablelist::seeRow {win index} { # # Adjust the index to fit within the existing items # adjustRowIndex $win index upvar ::tablelist::ns${win}::data data set key [lindex [lindex $data(itemList) $index] end] if {$data(itemCount) == 0 || [info exists data($key-hide)]} { return "" } # # Bring the given row into the window and restore # the horizontal view in the body text widget # $data(body) see [expr {double($index + 1)}] $data(body) xview moveto [lindex [$data(hdrTxt) xview] 0] adjustElidedText $win updateColorsWhenIdle $win adjustSepsWhenIdle $win updateVScrlbarWhenIdle $win return "" } #------------------------------------------------------------------------------ # tablelist::seeCell # # Processes the tablelist seecell subcommand. #------------------------------------------------------------------------------ proc tablelist::seeCell {win row col} { # # This might be an "after idle" callback; check whether the window exists # if {![winfo exists $win]} { return "" } upvar ::tablelist::ns${win}::data data set h $data(hdrTxt) set b $data(body) # # Adjust the row and column indices to fit within the existing elements # adjustRowIndex $win row adjustColIndex $win col set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key-hide)]} { return "" } if {$data(colCount) == 0} { $b see [expr {double($row + 1)}] return "" } elseif {$data($col-hide)} { return "" } # # Force any geometry manager calculations to be completed first # update idletasks if {![winfo exists $win]} { ;# because of update idletasks return "" } # # If the tablelist is empty then insert a temporary row # if {$data(itemCount) == 0} { variable canElide for {set n 0} {$n < $data(colCount)} {incr n} { if {!$data($n-hide) || $canElide} { $b insert end "\t\t" } } $b xview moveto [lindex [$h xview] 0] } if {$data(-titlecolumns) == 0} { findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 set nextIdx [$b index $tabIdx2+1c] set alignment [lindex $data(colList) [expr {2*$col + 1}]] set lX [winfo x $data(hdrTxtFrLbl)$col] set rX [expr {$lX + [winfo width $data(hdrTxtFrLbl)$col] - 1}] switch $alignment { left { # # Bring the cell's left edge into view # $b see $tabIdx1 $h xview moveto [lindex [$b xview] 0] # # Shift the view in the header text widget until the right # edge of the cell becomes visible but finish the scrolling # before the cell's left edge would become invisible # while {![isHdrTxtFrXPosVisible $win $rX]} { $h xview scroll 1 units if {![isHdrTxtFrXPosVisible $win $lX]} { $h xview scroll -1 units break } } } center { # # Bring the cell's left edge into view # $b see $tabIdx1 set winWidth [winfo width $h] if {[winfo width $data(hdrTxtFrLbl)$col] > $winWidth} { # # The cell doesn't fit into the window: Bring its # center into the window's middle horizontal position # $h xview moveto \ [expr {double($lX + $rX - $winWidth)/2/$data(hdrPixels)}] } else { # # Shift the view in the header text widget until # the right edge of the cell becomes visible # $h xview moveto [lindex [$b xview] 0] while {![isHdrTxtFrXPosVisible $win $rX]} { $h xview scroll 1 units } } } right { # # Bring the cell's right edge into view # $b see $nextIdx $h xview moveto [lindex [$b xview] 0] # # Shift the view in the header text widget until the left # edge of the cell becomes visible but finish the scrolling # before the cell's right edge would become invisible # while {![isHdrTxtFrXPosVisible $win $lX]} { $h xview scroll -1 units if {![isHdrTxtFrXPosVisible $win $rX]} { $h xview scroll 1 units break } } } } $b xview moveto [lindex [$h xview] 0] } else { # # Bring the cell's row into view # $b see [expr {double($row + 1)}] set scrlWindowWidth [getScrlWindowWidth $win] if {($col < $data(-titlecolumns)) || (!$data($col-elide) && [getScrlContentWidth $win $data(scrlColOffset) $col] <= $scrlWindowWidth)} { # # The given column index specifies either a title column or # one that is fully visible; restore the horizontal view # $b xview moveto [lindex [$h xview] 0] adjustElidedText $win } elseif {$data($col-elide) || [winfo width $data(hdrTxtFrLbl)$col] > $scrlWindowWidth} { # # The given column index specifies either an elided column or one # that doesn't fit into the window; shift the horizontal view to # make the column the first visible one among all scrollable columns # set scrlColOffset 0 for {incr col -1} {$col >= $data(-titlecolumns)} {incr col -1} { if {!$data($col-hide)} { incr scrlColOffset } } changeScrlColOffset $win $scrlColOffset } else { # # The given column index specifies a non-elided # scrollable column; shift the horizontal view # repeatedly until the column becomes visible # set scrlColOffset [expr {$data(scrlColOffset) + 1}] while {[getScrlContentWidth $win $scrlColOffset $col] > $scrlWindowWidth} { incr scrlColOffset } changeScrlColOffset $win $scrlColOffset } } # # Delete the temporary row if any # if {$data(itemCount) == 0} { $b delete 1.0 end } updateColorsWhenIdle $win adjustSepsWhenIdle $win updateVScrlbarWhenIdle $win return "" } #------------------------------------------------------------------------------ # tablelist::rowSelection # # Processes the tablelist selection subcommand. #------------------------------------------------------------------------------ proc tablelist::rowSelection {win opt first last} { upvar ::tablelist::ns${win}::data data if {$data(isDisabled) && [string compare $opt "includes"] != 0} { return "" } switch $opt { anchor { # # Adjust the index to fit within the existing non-hidden items # adjustRowIndex $win first 1 set data(anchorRow) $first return "" } clear { # # Swap the indices if necessary # if {$last < $first} { set tmp $first set first $last set last $tmp } set firstTextIdx [expr {$first + 1}].0 set lastTextIdx [expr {$last + 1}].end # # Find the (partly) selected lines of the body text # widget in the text range specified by the two indices # set w $data(body) variable canElide variable elide set selRange [$w tag nextrange select $firstTextIdx $lastTextIdx] while {[llength $selRange] != 0} { set selStart [lindex $selRange 0] $w tag remove select $selStart "$selStart lineend" # # Handle the -(select)background and -(select)foreground cell # and column configuration options for each element of the row # set row [expr {int($selStart) - 1}] set key [lindex [lindex $data(itemList) $row] end] set textIdx1 "$selStart linestart" for {set col 0} {$col < $data(colCount)} {incr col} { if {$data($col-hide) && !$canElide} { continue } set textIdx2 [$w search $elide "\t" \ $textIdx1+1c "$selStart lineend"]+1c foreach optTail {background foreground} { set opt -select$optTail foreach name [list $col$opt $key$opt $key,$col$opt] \ level [list col row cell] { if {[info exists data($name)]} { $w tag remove $level$opt-$data($name) \ $textIdx1 $textIdx2 } } foreach name [list $col-$optTail $key-$optTail \ $key,$col-$optTail] \ level [list col row cell] { if {[info exists data($name)]} { $w tag add $level-$optTail-$data($name) \ $textIdx1 $textIdx2 } } } set textIdx1 $textIdx2 } set selRange \ [$w tag nextrange select "$selStart lineend" $lastTextIdx] } updateColorsWhenIdle $win return "" } includes { set w $data(body) set textIdx [expr {double($first + 1)}] set selRange [$w tag nextrange select $textIdx "$textIdx lineend"] if {[llength $selRange] > 0} { return 1 } else { return 0 } } set { # # Swap the indices if necessary and adjust # the range to fit within the existing items # if {$last < $first} { set tmp $first set first $last set last $tmp } if {$first < 0} { set first 0 } if {$last > $data(lastRow)} { set last $data(lastRow) } set w $data(body) variable canElide variable elide for {set row $first; set line [expr {$first + 1}]} \ {$row <= $last} {set row $line; incr line} { # # Check whether the row is selectable and non-hidden # set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key-selectable)] || [info exists data($key-hide)]} { continue } # # Select the non-hidden elements of the row and handle # the -(select)background and -(select)foreground # cell and column configuration options for them # set textIdx1 $line.0 for {set col 0} {$col < $data(colCount)} {incr col} { if {$data($col-hide) && !$canElide} { continue } set textIdx2 \ [$w search $elide "\t" $textIdx1+1c $line.end]+1c if {$data($col-hide)} { set textIdx1 $textIdx2 continue } $w tag add select $textIdx1 $textIdx2 foreach optTail {background foreground} { set opt -select$optTail foreach name [list $col$opt $key$opt $key,$col$opt] \ level [list col row cell] { if {[info exists data($name)]} { $w tag add $level$opt-$data($name) \ $textIdx1 $textIdx2 } } foreach name [list $col-$optTail $key-$optTail \ $key,$col-$optTail] \ level [list col row cell] { if {[info exists data($name)]} { $w tag remove $level-$optTail-$data($name) \ $textIdx1 $textIdx2 } } } set textIdx1 $textIdx2 } } # # If the selection is exported and there are any selected # cells in the widget then make win the new owner of the # PRIMARY selection and register a callback to be invoked # when it loses ownership of the PRIMARY selection # if {$data(-exportselection) && [llength [$w tag nextrange select 1.0]] != 0} { selection own -command \ [list ::tablelist::lostSelection $win] $win } updateColorsWhenIdle $win return "" } } } # # Private callback procedures # =========================== # #------------------------------------------------------------------------------ # tablelist::fetchSelection # # This procedure is invoked when the PRIMARY selection is owned by the # tablelist widget win and someone attempts to retrieve it as a STRING. It # returns part or all of the selection, as given by offset and maxChars. The # string which is to be (partially) returned is built by joining all of the # selected elements of the (partly) selected rows together with tabs and the # rows themselves with newlines. #------------------------------------------------------------------------------ proc tablelist::fetchSelection {win offset maxChars} { upvar ::tablelist::ns${win}::data data if {!$data(-exportselection)} { return "" } set selection "" set prevRow -1 foreach cellIdx [curCellSelection $win] { scan $cellIdx "%d,%d" row col if {$row != $prevRow} { if {$prevRow != -1} { append selection "\n" } set prevRow $row set item [lindex $data(itemList) $row] set isFirstCol 1 } set key [lindex $item end] set text [lindex $item $col] if {[lindex $data(fmtCmdFlagList) $col]} { set text [formatElem $win $key $row $col $text] } if {!$isFirstCol} { append selection "\t" } append selection $text set isFirstCol 0 } return [string range $selection $offset [expr {$offset + $maxChars - 1}]] } #------------------------------------------------------------------------------ # tablelist::lostSelection # # This procedure is invoked when the tablelist widget win loses ownership of # the PRIMARY selection. It deselects all items of the widget with the aid of # the rowSelection procedure if the selection is exported. #------------------------------------------------------------------------------ proc tablelist::lostSelection win { upvar ::tablelist::ns${win}::data data if {$data(-exportselection)} { rowSelection $win clear 0 $data(lastRow) event generate $win <> } } #------------------------------------------------------------------------------ # tablelist::activeTrace # # This procedure is executed whenever the array element data(activeRow), # data(activeCol), or data(-selecttype) is written. It moves the "active" tag # to the line or cell that displays the active item or element of the widget in # its body text child if the latter has the keyboard focus. #------------------------------------------------------------------------------ proc tablelist::activeTrace {win varName index op} { upvar ::tablelist::ns${win}::data data set w $data(body) if {$data(ownsFocus) && ![info exists data(dispId)]} { $w tag remove active 1.0 end set line [expr {$data(activeRow) + 1}] set col $data(activeCol) if {[string compare $data(-selecttype) "row"] == 0} { $w tag add active $line.0 $line.end } elseif {$data(itemCount) > 0 && $data(colCount) > 0 && $line > 0 && !$data($col-hide)} { findTabs $win $line $data(activeCol) $data(activeCol) \ tabIdx1 tabIdx2 $w tag add active $tabIdx1 $tabIdx2+1c } } } #------------------------------------------------------------------------------ # tablelist::listVarTrace # # This procedure is executed whenever the global variable specified by varName # is written or unset. It makes sure that the contents of the widget will be # synchronized with the value of the variable at idle time, and that the # variable is recreated if it was unset. #------------------------------------------------------------------------------ proc tablelist::listVarTrace {win varName index op} { upvar ::tablelist::ns${win}::data data switch $op { w { if {![info exists data(syncId)]} { # # Arrange for the contents of the widget to be synchronized # with the value of the variable ::$varName at idle time # set data(syncId) [after idle [list tablelist::synchronize $win]] } } u { # # Recreate the variable ::$varName by setting it according to # the value of data(itemList), and set the trace on it again # if {[string compare $index ""] != 0} { set varName ${varName}($index) } set ::$varName {} foreach item $data(itemList) { lappend ::$varName [lrange $item 0 $data(lastCol)] } trace variable ::$varName wu $data(listVarTraceCmd) } } } kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/ConvertResources.sh0000644000175000017500000000060010425754106024626 0ustar domibeldomibelKWConvertImageToHeader --zlib --base64 \ vtkKWTablelistTclLibrary.h \ mwutil.tcl \ tablelist.tcl \ tablelistBind.tcl \ tablelistBitmaps.tcl \ tablelistConfig.tcl \ tablelistEdit.tcl \ tablelistMove.tcl \ tablelistPublic.tcl \ tablelistSort.tcl \ tablelistThemes.tcl \ tablelistUtil.tcl \ tablelistUtil2.tcl \ tablelistWidget.tclkwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistUtil.tcl0000644000175000017500000037624211073220147024317 0ustar domibeldomibel#============================================================================== # Contains private utility procedures for tablelist widgets. # # Structure of the module: # - Namespace initialization # - Private utility procedures # # Copyright (c) 2000-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== # # Namespace initialization # ======================== # namespace eval tablelist { # # alignment -> anchor mapping # variable anchors array set anchors { left w right e center center } # # -> snipSide mapping # variable snipSides array set snipSides { left,0 r left,1 l right,0 l right,1 r center,0 r center,1 l } # # -> direction mapping # variable directions array set directions { up,increasing Up up,decreasing Dn down,increasing Dn down,decreasing Up } } # # Private utility procedures # ========================== # #------------------------------------------------------------------------------ # tablelist::rowIndex # # Checks the row index idx and returns either its numerical value or an error. # endIsSize must be a boolean value: if true, end refers to the number of items # in the tablelist, i.e., to the element just after the last one; if false, end # refers to 1 less than the number of items, i.e., to the last element in the # tablelist. #------------------------------------------------------------------------------ proc tablelist::rowIndex {win idx endIsSize} { upvar ::tablelist::ns${win}::data data if {[catch {format "%d" $idx} index] == 0} { return $index } elseif {[string first $idx "end"] == 0} { if {$endIsSize} { return $data(itemCount) } else { return $data(lastRow) } } elseif {[string first $idx "active"] == 0 && [string length $idx] >= 2} { return $data(activeRow) } elseif {[string first $idx "anchor"] == 0 && [string length $idx] >= 2} { return $data(anchorRow) } elseif {[scan $idx "@%d,%d" x y] == 2} { displayItems $win incr x -[winfo x $data(body)] incr y -[winfo y $data(body)] set textIdx [$data(body) index @$x,$y] return [expr {int($textIdx) - 1}] } elseif {[string compare [string index $idx 0] "k"] == 0 && [set index [lsearch $data(itemList) "* $idx"]] >= 0} { return $index } else { for {set row 0} {$row < $data(itemCount)} {incr row} { set key [lindex [lindex $data(itemList) $row] end] set hasName [info exists data($key-name)] if {($hasName && [string compare $idx $data($key-name)] == 0) || (!$hasName && [string compare $idx ""] == 0)} { return $row } } return -code error \ "bad row index \"$idx\": must be active, anchor,\ end, @x,y, a number, a full key, or a name" } } #------------------------------------------------------------------------------ # tablelist::colIndex # # Checks the column index idx and returns either its numerical value or an # error. checkRange must be a boolean value: if true, it is additionally # checked whether the numerical value corresponding to idx is within the # allowed range. #------------------------------------------------------------------------------ proc tablelist::colIndex {win idx checkRange} { upvar ::tablelist::ns${win}::data data if {[catch {format "%d" $idx} index] == 0} { # nothing } elseif {[string first $idx "end"] == 0} { set index $data(lastCol) } elseif {[string first $idx "active"] == 0 && [string length $idx] >= 2} { set index $data(activeCol) } elseif {[string first $idx "anchor"] == 0 && [string length $idx] >= 2} { set index $data(anchorCol) } elseif {[scan $idx "@%d,%d" x y] == 2} { synchronize $win displayItems $win incr x -[winfo x $data(body)] set bodyWidth [winfo width $data(body)] if {$x >= $bodyWidth} { set x [expr {$bodyWidth - 1}] } elseif {$x < 0} { set x 0 } set x [expr {$x + [winfo rootx $data(body)]}] set lastVisibleCol -1 for {set col 0} {$col < $data(colCount)} {incr col} { if {$data($col-hide) || $data($col-elide)} { continue } set lastVisibleCol $col set w $data(hdrTxtFrLbl)$col set wX [winfo rootx $w] if {$x >= $wX && $x < $wX + [winfo width $w]} { return $col } } set index $lastVisibleCol } else { for {set col 0} {$col < $data(colCount)} {incr col} { set hasName [info exists data($col-name)] if {($hasName && [string compare $idx $data($col-name)] == 0) || (!$hasName && [string compare $idx ""] == 0)} { set index $col break } } if {$col == $data(colCount)} { return -code error \ "bad column index \"$idx\": must be active, anchor,\ end, @x,y, a number, or a name" } } if {$checkRange && ($index < 0 || $index > $data(lastCol))} { return -code error "column index \"$idx\" out of range" } else { return $index } } #------------------------------------------------------------------------------ # tablelist::cellIndex # # Checks the cell index idx and returns either a list of the form {row col} or # an error. checkRange must be a boolean value: if true, it is additionally # checked whether the two numerical values corresponding to idx are within the # respective allowed ranges. #------------------------------------------------------------------------------ proc tablelist::cellIndex {win idx checkRange} { upvar ::tablelist::ns${win}::data data set lst [split $idx ","] if {[llength $lst] == 2 && [catch {rowIndex $win [lindex $lst 0] 0} row] == 0 && [catch {colIndex $win [lindex $lst 1] 0} col] == 0} { # nothing } elseif {[string first $idx "end"] == 0} { set row [rowIndex $win $idx 0] set col [colIndex $win $idx 0] } elseif {[string first $idx "active"] == 0 && [string length $idx] >= 2} { set row $data(activeRow) set col $data(activeCol) } elseif {[string first $idx "anchor"] == 0 && [string length $idx] >= 2} { set row $data(anchorRow) set col $data(anchorCol) } elseif {[string compare [string index $idx 0] "@"] == 0 && [catch {rowIndex $win $idx 0} row] == 0 && [catch {colIndex $win $idx 0} col] == 0} { # nothing } else { return -code error \ "bad cell index \"$idx\": must be active, anchor,\ end, @x,y, or row,col, where row must be active,\ anchor, end, a number, a full key, or a name, and\ col must be active, anchor, end, a number, or a name" } if {$checkRange && ($row < 0 || $row > $data(lastRow) || $col < 0 || $col > $data(lastCol))} { return -code error "cell index \"$idx\" out of range" } else { return [list $row $col] } } #------------------------------------------------------------------------------ # tablelist::adjustRowIndex # # Sets the row index specified by $rowName to the index of the nearest # (non-hidden) row. #------------------------------------------------------------------------------ proc tablelist::adjustRowIndex {win rowName {forceNonHidden 0}} { upvar ::tablelist::ns${win}::data data $rowName row # # Don't operate on row directly, because $rowName might # be data(activeRow), in which case any temporary changes # made on row would trigger the activeTrace procedure # set _row $row if {$_row > $data(lastRow)} { set _row $data(lastRow) } if {$_row < 0} { set _row 0 } if {$forceNonHidden} { set _rowSav $_row for {} {$_row < $data(itemCount)} {incr _row} { set key [lindex [lindex $data(itemList) $_row] end] if {![info exists data($key-hide)]} { set row $_row return "" } } for {set _row [expr {$_rowSav - 1}]} {$_row >= 0} {incr _row -1} { set key [lindex [lindex $data(itemList) $_row] end] if {![info exists data($key-hide)]} { set row $_row return "" } } set row 0 } else { set row $_row } } #------------------------------------------------------------------------------ # tablelist::adjustColIndex # # Sets the column index specified by $colName to the index of the nearest # (non-hidden) column. #------------------------------------------------------------------------------ proc tablelist::adjustColIndex {win colName {forceNonHidden 0}} { upvar ::tablelist::ns${win}::data data $colName col # # Don't operate on col directly, because $colName might # be data(activeCol), in which case any temporary changes # made on col would trigger the activeTrace procedure # set _col $col if {$_col > $data(lastCol)} { set _col $data(lastCol) } if {$_col < 0} { set _col 0 } if {$forceNonHidden} { set _colSav $_col for {} {$_col < $data(colCount)} {incr _col} { if {!$data($_col-hide)} { set col $_col return "" } } for {set _col [expr {$_colSav - 1}]} {$_col >= 0} {incr _col -1} { if {!$data($_col-hide)} { set col $_col return "" } } set _col 0 } else { set col $_col } } #------------------------------------------------------------------------------ # tablelist::findTabs # # Searches for the first and last occurrences of the tab character in the cell # range specified by firstCol and lastCol in the given line of the body text # child of the tablelist widget win. Assigns the index of the first tab to # $idx1Name and the index of the last tab to $idx2Name. It is assumed that # both columns are non-hidden (but there may be hidden ones between them). #------------------------------------------------------------------------------ proc tablelist::findTabs {win line firstCol lastCol idx1Name idx2Name} { upvar ::tablelist::ns${win}::data data $idx1Name idx1 $idx2Name idx2 set w $data(body) set endIdx $line.end variable canElide variable elide set idx $line.1 for {set col 0} {$col < $firstCol} {incr col} { if {!$data($col-hide) || $canElide} { set idx [$w search $elide "\t" $idx $endIdx]+2c if {[string compare $idx "+2c"] == 0} { return 0 } } } set idx1 [$w index $idx-1c] for {} {$col < $lastCol} {incr col} { if {!$data($col-hide) || $canElide} { set idx [$w search $elide "\t" $idx $endIdx]+2c if {[string compare $idx "+2c"] == 0} { return 0 } } } set idx2 [$w search $elide "\t" $idx $endIdx] if {[string compare $idx2 ""] == 0} { return 0 } return 1 } #------------------------------------------------------------------------------ # tablelist::sortStretchableColList # # Replaces the column indices different from end in the list of the stretchable # columns of the tablelist widget win with their numerical equivalents and # sorts the resulting list. #------------------------------------------------------------------------------ proc tablelist::sortStretchableColList win { upvar ::tablelist::ns${win}::data data if {[llength $data(-stretch)] == 0 || [string first $data(-stretch) "all"] == 0} { return "" } set containsEnd 0 foreach elem $data(-stretch) { if {[string first $elem "end"] == 0} { set containsEnd 1 } else { set tmp([colIndex $win $elem 0]) "" } } set data(-stretch) [lsort -integer [array names tmp]] if {$containsEnd} { lappend data(-stretch) end } } #------------------------------------------------------------------------------ # tablelist::deleteColData # # Cleans up the data associated with the col'th column of the tablelist widget # win. #------------------------------------------------------------------------------ proc tablelist::deleteColData {win col} { upvar ::tablelist::ns${win}::data data if {$data(editCol) == $col} { set data(editCol) -1 set data(editRow) -1 } # # Remove the elements with names of the form $col-* # if {[info exists data($col-redispId)]} { after cancel $data($col-redispId) } foreach name [array names data $col-*] { unset data($name) } # # Remove the elements with names of the form k*,$col-* # foreach name [array names data k*,$col-*] { unset data($name) if {[string match "k*,$col-\[bf\]*" $name]} { incr data(cellTagRefCount) -1 } elseif {[string match "k*,$col-image" $name]} { incr data(imgCount) -1 } elseif {[string match "k*,$col-window" $name]} { incr data(winCount) -1 } } # # Remove col from the list of stretchable columns if explicitly specified # if {[string first $data(-stretch) "all"] != 0} { set stretchableCols {} foreach elem $data(-stretch) { if {[string first $elem "end"] == 0 || $elem != $col} { lappend stretchableCols $elem } } set data(-stretch) $stretchableCols } } #------------------------------------------------------------------------------ # tablelist::deleteColAttribs # # Cleans up the attributes associated with the col'th column of the tablelist # widget win. #------------------------------------------------------------------------------ proc tablelist::deleteColAttribs {win col} { upvar ::tablelist::ns${win}::attribs attribs # # Remove the elements with names of the form $col-* # foreach name [array names attribs $col-*] { unset attribs($name) } # # Remove the elements with names of the form k*,$col-* # foreach name [array names attribs k*,$col-*] { unset attribs($name) } } #------------------------------------------------------------------------------ # tablelist::moveColData # # Moves the elements of oldArrName corresponding to oldCol to those of # newArrName corresponding to newCol. #------------------------------------------------------------------------------ proc tablelist::moveColData {oldArrName newArrName imgArrName oldCol newCol} { upvar $oldArrName oldArr $newArrName newArr $imgArrName imgArr foreach specialCol {activeCol anchorCol editCol} { if {$oldArr($specialCol) == $oldCol} { set newArr($specialCol) $newCol } } if {$newCol < $newArr(colCount)} { foreach l [getSublabels $newArr(hdrTxtFrLbl)$newCol] { destroy $l } set newArr(fmtCmdFlagList) \ [lreplace $newArr(fmtCmdFlagList) $newCol $newCol 0] } # # Move the elements of oldArr with names of the form $oldCol-* # to those of newArr with names of the form $newCol-* # foreach newName [array names newArr $newCol-*] { unset newArr($newName) } foreach oldName [array names oldArr $oldCol-*] { regsub "$oldCol-" $oldName "$newCol-" newName set newArr($newName) $oldArr($oldName) unset oldArr($oldName) set tail [lindex [split $newName "-"] 1] switch $tail { formatcommand { if {$newCol < $newArr(colCount)} { set newArr(fmtCmdFlagList) \ [lreplace $newArr(fmtCmdFlagList) $newCol $newCol 1] } } labelimage { set imgArr($newCol-$tail) $newArr($newName) unset newArr($newName) } } } # # Move the elements of oldArr with names of the form k*,$oldCol-* # to those of newArr with names of the form k*,$newCol-* # foreach newName [array names newArr k*,$newCol-*] { unset newArr($newName) } foreach oldName [array names oldArr k*,$oldCol-*] { regsub -- ",$oldCol-" $oldName ",$newCol-" newName set newArr($newName) $oldArr($oldName) unset oldArr($oldName) } # # Replace oldCol with newCol in the list of # stretchable columns if explicitly specified # if {[info exists oldArr(-stretch)] && [string first $oldArr(-stretch) "all"] != 0} { set stretchableCols {} foreach elem $oldArr(-stretch) { if {[string first $elem "end"] != 0 && $elem == $oldCol} { lappend stretchableCols $newCol } else { lappend stretchableCols $elem } } set newArr(-stretch) $stretchableCols } } #------------------------------------------------------------------------------ # tablelist::moveColAttribs # # Moves the elements of oldArrName corresponding to oldCol to those of # newArrName corresponding to newCol. #------------------------------------------------------------------------------ proc tablelist::moveColAttribs {oldArrName newArrName oldCol newCol} { upvar $oldArrName oldArr $newArrName newArr # # Move the elements of oldArr with names of the form $oldCol-* # to those of newArr with names of the form $newCol-* # foreach newName [array names newArr $newCol-*] { unset newArr($newName) } foreach oldName [array names oldArr $oldCol-*] { regsub "$oldCol-" $oldName "$newCol-" newName set newArr($newName) $oldArr($oldName) unset oldArr($oldName) } # # Move the elements of oldArr with names of the form k*,$oldCol-* # to those of newArr with names of the form k*,$newCol-* # foreach newName [array names newArr k*,$newCol-*] { unset newArr($newName) } foreach oldName [array names oldArr k*,$oldCol-*] { regsub -- ",$oldCol-" $oldName ",$newCol-" newName set newArr($newName) $oldArr($oldName) unset oldArr($oldName) } } #------------------------------------------------------------------------------ # tablelist::deleteColFromCellList # # Returns the list obtained from a given list of cell indices by removing the # elements whose column component equals a given column number. #------------------------------------------------------------------------------ proc tablelist::deleteColFromCellList {cellList col} { set newCellList {} foreach cellIdx $cellList { scan $cellIdx "%d,%d" cellRow cellCol if {$cellCol != $col} { lappend newCellList $cellIdx } } return $newCellList } #------------------------------------------------------------------------------ # tablelist::extractColFromCellList # # Returns the list of row indices obtained from those elements of a given list # of cell indices whose column component equals a given column number. #------------------------------------------------------------------------------ proc tablelist::extractColFromCellList {cellList col} { set rowList {} foreach cellIdx $cellList { scan $cellIdx "%d,%d" cellRow cellCol if {$cellCol == $col} { lappend rowList $cellRow } } return $rowList } #------------------------------------------------------------------------------ # tablelist::replaceColInCellList # # Returns the list obtained from a given list of cell indices by replacing the # occurrences of oldCol in the column components with newCol. #------------------------------------------------------------------------------ proc tablelist::replaceColInCellList {cellList oldCol newCol} { set cellList [deleteColFromCellList $cellList $newCol] set newCellList {} foreach cellIdx $cellList { scan $cellIdx "%d,%d" cellRow cellCol if {$cellCol == $oldCol} { lappend newCellList $cellRow,$newCol } else { lappend newCellList $cellIdx } } return $newCellList } #------------------------------------------------------------------------------ # tablelist::condUpdateListVar # # Updates the list variable of the tablelist widget win if present. #------------------------------------------------------------------------------ proc tablelist::condUpdateListVar win { upvar ::tablelist::ns${win}::data data if {$data(hasListVar)} { upvar #0 $data(-listvariable) var trace vdelete var wu $data(listVarTraceCmd) set var {} foreach item $data(itemList) { lappend var [lrange $item 0 $data(lastCol)] } trace variable var wu $data(listVarTraceCmd) } } #------------------------------------------------------------------------------ # tablelist::reconfigColLabels # # Reconfigures the labels of the col'th column of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::reconfigColLabels {win imgArrName col} { upvar ::tablelist::ns${win}::data data $imgArrName imgArr set optList {-labelalign -labelbackground -labelborderwidth -labelfont -labelforeground -labelpady -labelrelief} variable usingTile if {!$usingTile} { lappend optList -labelheight } foreach opt $optList { if {[info exists data($col$opt)]} { doColConfig $col $win $opt $data($col$opt) } else { doColConfig $col $win $opt "" } } if {[info exists imgArr($col-labelimage)]} { doColConfig $col $win -labelimage $imgArr($col-labelimage) } } #------------------------------------------------------------------------------ # tablelist::charsToPixels # # Returns the width in pixels of the string consisting of a given number of "0" # characters. #------------------------------------------------------------------------------ proc tablelist::charsToPixels {win font charCount} { ### set str [string repeat "0" $charCount] set str "" for {set n 0} {$n < $charCount} {incr n} { append str 0 } return [font measure $font -displayof $win $str] } #------------------------------------------------------------------------------ # tablelist::strRange # # Gets the largest initial (for snipSide = r) or final (for snipSide = l) range # of characters from str whose width, when displayed in the given font, is no # greater than pixels decremented by the width of snipStr. Returns a string # obtained from this substring by appending (for snipSide = r) or prepending # (for snipSide = l) (part of) snipStr to it. #------------------------------------------------------------------------------ proc tablelist::strRange {win str font pixels snipSide snipStr} { if {$pixels < 0} { return "" } if {[string compare $snipSide ""] == 0} { return $str } set width [font measure $font -displayof $win $str] if {$width <= $pixels} { return $str } set snipWidth [font measure $font -displayof $win $snipStr] if {$pixels <= $snipWidth} { set str $snipStr set snipStr "" } else { incr pixels -$snipWidth } if {[string compare $snipSide "r"] == 0} { set idx [expr {[string length $str]*$pixels/$width - 1}] set subStr [string range $str 0 $idx] set width [font measure $font -displayof $win $subStr] if {$width < $pixels} { while 1 { incr idx set subStr [string range $str 0 $idx] set width [font measure $font -displayof $win $subStr] if {$width > $pixels} { incr idx -1 set subStr [string range $str 0 $idx] return $subStr$snipStr } elseif {$width == $pixels} { return $subStr$snipStr } } } elseif {$width == $pixels} { return $subStr$snipStr } else { while 1 { incr idx -1 set subStr [string range $str 0 $idx] set width [font measure $font -displayof $win $subStr] if {$width <= $pixels} { return $subStr$snipStr } } } } else { set idx [expr {[string length $str]*($width - $pixels)/$width}] set subStr [string range $str $idx end] set width [font measure $font -displayof $win $subStr] if {$width < $pixels} { while 1 { incr idx -1 set subStr [string range $str $idx end] set width [font measure $font -displayof $win $subStr] if {$width > $pixels} { incr idx set subStr [string range $str $idx end] return $snipStr$subStr } elseif {$width == $pixels} { return $snipStr$subStr } } } elseif {$width == $pixels} { return $snipStr$subStr } else { while 1 { incr idx set subStr [string range $str $idx end] set width [font measure $font -displayof $win $subStr] if {$width <= $pixels} { return $snipStr$subStr } } } } } #------------------------------------------------------------------------------ # tablelist::adjustItem # # Returns the list obtained by adjusting the list specified by item to the # length expLen. #------------------------------------------------------------------------------ proc tablelist::adjustItem {item expLen} { set len [llength $item] if {$len < $expLen} { for {set n $len} {$n < $expLen} {incr n} { lappend item "" } return $item } else { return [lrange $item 0 [expr {$expLen - 1}]] } } #------------------------------------------------------------------------------ # tablelist::formatElem # # Returns the string obtained by formatting the last argument. #------------------------------------------------------------------------------ proc tablelist::formatElem {win key row col text} { upvar ::tablelist::ns${win}::data data array set data [list fmtKey $key fmtRow $row fmtCol $col] return [uplevel #0 $data($col-formatcommand) [list $text]] } #------------------------------------------------------------------------------ # tablelist::formatItem # # Returns the list obtained by formatting the elements of the last argument. #------------------------------------------------------------------------------ proc tablelist::formatItem {win key row item} { upvar ::tablelist::ns${win}::data data array set data [list fmtKey $key fmtRow $row] set formattedItem {} set col 0 foreach text $item fmtCmdFlag $data(fmtCmdFlagList) { if {$fmtCmdFlag} { set data(fmtCol) $col set text [uplevel #0 $data($col-formatcommand) [list $text]] } lappend formattedItem $text incr col } return $formattedItem } #------------------------------------------------------------------------------ # tablelist::hasChars # # Checks whether at least one element of the given list is a nonempty string. #------------------------------------------------------------------------------ proc tablelist::hasChars list { foreach str $list { if {[string compare $str ""] != 0} { return 1 } } return 0 } #------------------------------------------------------------------------------ # tablelist::getListWidth # # Returns the max. number of pixels that the elements of the given list would # use in the specified font when displayed in the window win. #------------------------------------------------------------------------------ proc tablelist::getListWidth {win list font} { set width 0 foreach str $list { set strWidth [font measure $font -displayof $win $str] if {$strWidth > $width} { set width $strWidth } } return $width } #------------------------------------------------------------------------------ # tablelist::joinList # # Returns the string formed by joining together with "\n" the strings obtained # by applying strRange to the elements of the given list, with the specified # arguments. #------------------------------------------------------------------------------ proc tablelist::joinList {win list font pixels snipSide snipStr} { set list2 {} foreach str $list { lappend list2 [strRange $win $str $font $pixels $snipSide $snipStr] } return [join $list2 "\n"] } #------------------------------------------------------------------------------ # tablelist::displayText # # Displays the given text in a message widget to be embedded into the specified # cell of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::displayText {win key col text font pixels alignment} { upvar ::tablelist::ns${win}::data data set w $data(body).m$key,$col if {![winfo exists $w]} { # # Create a message widget and replace the binding tag Message with # $data(bodyTag) and TablelistBody in the list of its binding tags # message $w -borderwidth 0 -highlightthickness 0 -padx 0 -pady 0 \ -relief flat -takefocus 0 bindtags $w [lreplace [bindtags $w] 1 1 $data(bodyTag) TablelistBody] } variable anchors set width $pixels if {$pixels == 0} { set width 1000000 } $w configure -anchor $anchors($alignment) -font $font \ -justify $alignment -text $text -width $width updateColorsWhenIdle $win return $w } #------------------------------------------------------------------------------ # tablelist::displayImage # # Displays an image in a label widget to be embedded into the specified cell of # the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::displayImage {win key col anchor width} { # # Create a label widget and replace the binding tag Label with # $data(bodyTag) and TablelistBody in the list of its binding tags # upvar ::tablelist::ns${win}::data data set w $data(body).l$key,$col tk::label $w -anchor $anchor -borderwidth 0 -height 0 \ -highlightthickness 0 -image $data($key,$col-image) \ -padx 0 -pady 0 -relief flat -takefocus 0 -width $width bindtags $w [lreplace [bindtags $w] 1 1 $data(bodyTag) TablelistBody] updateColorsWhenIdle $win return $w } #------------------------------------------------------------------------------ # tablelist::getAuxData # # Gets the name, type, and width of the image or window associated with the # specified cell of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::getAuxData {win key col auxTypeName auxWidthName {pixels 0}} { upvar ::tablelist::ns${win}::data data \ $auxTypeName auxType $auxWidthName auxWidth if {[info exists data($key,$col-window)]} { if {$pixels != 0 && [info exists data($key,$col-stretchwindow)]} { set auxType 3 ;# dynamic-width window set auxWidth [expr {$pixels + $data($col-delta)}] } else { set auxType 2 ;# static-width window set auxWidth $data($key,$col-reqWidth) } return $data(body).f$key,$col } elseif {[info exists data($key,$col-image)]} { set auxType 1 ;# image set auxWidth [image width $data($key,$col-image)] return [list ::tablelist::displayImage $win $key $col w 0] } else { set auxType 0 ;# none set auxWidth 0 return "" } } #------------------------------------------------------------------------------ # tablelist::getMaxTextWidth # # Returns the number of pixels available for displaying the text of a static- # width tablelist cell. #------------------------------------------------------------------------------ proc tablelist::getMaxTextWidth {pixels auxWidth} { if {$auxWidth == 0} { return $pixels } else { set lessPixels [expr {$pixels - $auxWidth - 4}] if {$lessPixels > 0} { return $lessPixels } else { return 1 } } } #------------------------------------------------------------------------------ # tablelist::adjustElem # # Prepares the text specified by $textName and the auxiliary object width # specified by $auxWidthName for insertion into a cell of the tablelist widget # win. #------------------------------------------------------------------------------ proc tablelist::adjustElem {win textName auxWidthName font pixels snipSide snipStr} { upvar $textName text $auxWidthName auxWidth if {$pixels == 0} { ;# convention: dynamic width if {$auxWidth != 0 && [string compare $text ""] != 0} { incr auxWidth 4 } } elseif {$auxWidth == 0} { ;# no image or window set text [strRange $win $text $font $pixels $snipSide $snipStr] } elseif {[string compare $text ""] == 0} { ;# aux. object w/o text if {$auxWidth > $pixels} { set auxWidth $pixels } } else { ;# both aux. object and text if {$auxWidth + 4 <= $pixels} { incr auxWidth 4 incr pixels -$auxWidth set text [strRange $win $text $font $pixels $snipSide $snipStr] } elseif {$auxWidth <= $pixels} { set text "" ;# can't display the text } else { set auxWidth $pixels set text "" ;# can't display the text } } } #------------------------------------------------------------------------------ # tablelist::adjustMlElem # # Prepares the list specified by $listName and the auxiliary object width # specified by $auxWidthName for insertion into a multiline cell of the # tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::adjustMlElem {win listName auxWidthName font pixels snipSide snipStr} { upvar $listName list $auxWidthName auxWidth set list2 {} if {$pixels == 0} { ;# convention: dynamic width if {$auxWidth != 0 && [hasChars $list]} { incr auxWidth 4 } } elseif {$auxWidth == 0} { ;# no image or window foreach str $list { lappend list2 [strRange $win $str $font $pixels $snipSide $snipStr] } set list $list2 } elseif {![hasChars $list]} { ;# aux. object w/o text if {$auxWidth > $pixels} { set auxWidth $pixels } } else { ;# both aux. object and text if {$auxWidth + 4 <= $pixels} { incr auxWidth 4 incr pixels -$auxWidth foreach str $list { lappend list2 \ [strRange $win $str $font $pixels $snipSide $snipStr] } set list $list2 } elseif {$auxWidth <= $pixels} { foreach str $list { lappend list2 "" } set list $list2 ;# can't display the text } else { set auxWidth $pixels foreach str $list { lappend list2 "" } set list $list2 ;# can't display the text } } } #------------------------------------------------------------------------------ # tablelist::getElemWidth # # Returns the number of pixels that the given text together with the aux. # object (image or window) of the specified width would use when displayed in a # cell of a dynamic-width column of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::getElemWidth {win text auxWidth cellFont} { if {[string match "*\n*" $text]} { set list [split $text "\n"] if {$auxWidth != 0 && [hasChars $list]} { incr auxWidth 4 } return [expr {[getListWidth $win $list $cellFont] + $auxWidth}] } else { if {$auxWidth != 0 && [string compare $text ""] != 0} { incr auxWidth 4 } return [expr {[font measure $cellFont -displayof $win $text] + $auxWidth}] } } #------------------------------------------------------------------------------ # tablelist::insertElem # # Inserts the given text and auxiliary object (image or window) into the text # widget w, just before the character position specified by index. The object # will follow the text if alignment is "right", and will precede it otherwise. #------------------------------------------------------------------------------ proc tablelist::insertElem {w index text aux auxType alignment} { set index [$w index $index] if {$auxType == 0} { ;# no image or window $w insert $index $text } elseif {[string compare $alignment "right"] == 0} { set padY [expr {[$w cget -spacing1] == 0}] if {$auxType == 1} { ;# image set aux [lreplace $aux 4 4 e] $w window create $index -pady $padY -create $aux } else { ;# window if {$auxType == 2} { ;# static width place $aux.w -anchor ne -relwidth "" } else { ;# dynamic width place $aux.w -anchor ne -relwidth 1.0 } $w window create $index -pady $padY -window $aux } $w insert $index $text } else { $w insert $index $text set padY [expr {[$w cget -spacing1] == 0}] if {$auxType == 1} { ;# image set aux [lreplace $aux 4 4 w] $w window create $index -pady $padY -create $aux } else { ;# window if {$auxType == 2} { ;# static width place $aux.w -anchor nw -relwidth "" } else { ;# dynamic width place $aux.w -anchor nw -relwidth 1.0 } $w window create $index -pady $padY -window $aux } } } #------------------------------------------------------------------------------ # tablelist::insertMlElem # # Inserts the given message widget and auxiliary object (image or window) into # the text widget w, just before the character position specified by index. # The object will follow the message widget if alignment is "right", and will # precede it otherwise. #------------------------------------------------------------------------------ proc tablelist::insertMlElem {w index msgScript aux auxType alignment} { set index [$w index $index] set padY [expr {[$w cget -spacing1] == 0}] if {$auxType == 0} { ;# no image or window $w window create $index -pady $padY -create $msgScript } elseif {[string compare $alignment "right"] == 0} { if {$auxType == 1} { ;# image set aux [lreplace $aux 4 4 e] $w window create $index -pady $padY -create $aux } else { ;# window if {$auxType == 2} { ;# static width place $aux.w -anchor ne -relwidth "" } else { ;# dynamic width place $aux.w -anchor ne -relwidth 1.0 } $w window create $index -pady $padY -window $aux } $w window create $index -pady $padY -create $msgScript } else { $w window create $index -pady $padY -create $msgScript if {$auxType == 1} { ;# image set aux [lreplace $aux 4 4 w] $w window create $index -pady $padY -create $aux } else { ;# window if {$auxType == 2} { ;# static width place $aux.w -anchor nw -relwidth "" } else { ;# dynamic width place $aux.w -anchor nw -relwidth 1.0 } $w window create $index -pady $padY -window $aux } } } #------------------------------------------------------------------------------ # tablelist::updateCell # # Updates the contents of the text widget w starting at index1 and ending just # before index2 by keeping the auxiliary object (image or window) (if any) and # replacing only the text between the two character positions. #------------------------------------------------------------------------------ proc tablelist::updateCell {w index1 index2 text aux auxType auxWidth alignment} { if {$auxType == 0} { ;# no image or window $w delete $index1 $index2 $w insert $index1 $text } else { # # Check whether the image label or the frame containing a # window is mapped at the first or last position of the cell # if {$auxType == 1} { ;# image if {[setImgLabelWidth $w $index1 $auxWidth]} { set auxFound 1 $w delete $index1+1c $index2 } elseif {[setImgLabelWidth $w $index2-1c $auxWidth]} { set auxFound 1 $w delete $index1 $index2-1c } else { set auxFound 0 $w delete $index1 $index2 } } else { ;# window if {[$aux cget -width] != $auxWidth} { $aux configure -width $auxWidth } if {[string compare [lindex [$w dump -window $index1] 1] \ $aux] == 0} { set auxFound 1 $w delete $index1+1c $index2 } elseif {[string compare [lindex [$w dump -window $index2-1c] 1] \ $aux] == 0} { set auxFound 1 $w delete $index1 $index2-1c } else { set auxFound 0 $w delete $index1 $index2 } } if {$auxFound} { # # Adjust the aux. window and insert the text # if {[string compare $alignment "right"] == 0} { if {$auxType == 1} { ;# image setImgLabelAnchor $w $index1 e } else { ;# window if {$auxType == 2} { ;# static width place $aux.w -anchor ne -relwidth "" } else { ;# dynamic width place $aux.w -anchor ne -relwidth 1.0 } } set index $index1 } else { if {$auxType == 1} { ;# image setImgLabelAnchor $w $index1 w } else { ;# window if {$auxType == 2} { ;# static width place $aux.w -anchor nw -relwidth "" } else { ;# dynamic width place $aux.w -anchor nw -relwidth 1.0 } } set index $index1+1c } $w insert $index $text } else { # # Insert the text and the aux. window # if {$auxType == 1} { ;# image set aux [lreplace $aux end end $auxWidth] } else { ;# window if {[$aux cget -width] != $auxWidth} { $aux configure -width $auxWidth } } insertElem $w $index1 $text $aux $auxType $alignment } } } #------------------------------------------------------------------------------ # tablelist::updateMlCell # # Updates the contents of the text widget w starting at index1 and ending just # before index2 by keeping the auxiliary object (image or window) (if any) and # replacing only the multiline text between the two character positions. #------------------------------------------------------------------------------ proc tablelist::updateMlCell {w index1 index2 msgScript aux auxType auxWidth alignment} { if {$auxType == 0} { ;# no image or window set areEqual [$w compare $index1 == $index2] $w delete $index1+1c $index2 set padY [expr {[$w cget -spacing1] == 0}] if {[catch {$w window cget $index1 -create} script] == 0 && [string match "::tablelist::displayText*" $script]} { $w window configure $index1 -pady $padY -create $msgScript set path [lindex [$w dump -window $index1] 1] if {[string compare $path ""] != 0 && [string compare [winfo class $path] "Message"] == 0} { eval $msgScript } } else { if {!$areEqual} { $w delete $index1 } $w window create $index1 -pady $padY -create $msgScript } } else { # # Check whether the image label or the frame containing a # window is mapped at the first or last position of the cell # $w mark set index2Mark $index2 if {$auxType == 1} { ;# image if {[setImgLabelWidth $w $index1 $auxWidth]} { set auxFound 1 if {[string compare $alignment "right"] == 0} { $w delete $index1+1c $index2 } } elseif {[setImgLabelWidth $w $index2-1c $auxWidth]} { set auxFound 1 if {[string compare $alignment "right"] != 0} { $w delete $index1 $index2-1c } } else { set auxFound 0 $w delete $index1 $index2 } } else { ;# window if {[$aux cget -width] != $auxWidth} { $aux configure -width $auxWidth } if {[string compare [lindex [$w dump -window $index1] 1] \ $aux] == 0} { set auxFound 1 if {[string compare $alignment "right"] == 0} { $w delete $index1+1c $index2 } } elseif {[string compare [lindex [$w dump -window $index2-1c] 1] \ $aux] == 0} { set auxFound 1 if {[string compare $alignment "right"] != 0} { $w delete $index1 $index2-1c } } else { set auxFound 0 $w delete $index1 $index2 } } if {$auxFound} { # # Adjust the aux. window and insert the message widget # if {[string compare $alignment "right"] == 0} { if {$auxType == 1} { ;# image setImgLabelAnchor $w index2Mark-1c e } else { ;# window if {$auxType == 2} { ;# static width place $aux.w -anchor ne -relwidth "" } else { ;# dynamic width place $aux.w -anchor ne -relwidth 1.0 } } set index index2Mark-2c } else { if {$auxType == 1} { ;# image setImgLabelAnchor $w $index1 w } else { ;# window if {$auxType == 2} { ;# static width place $aux.w -anchor nw -relwidth "" } else { ;# dynamic width place $aux.w -anchor nw -relwidth 1.0 } } set index $index1+1c } set padY [expr {[$w cget -spacing1] == 0}] if {[catch {$w window cget $index -create} script] == 0 && [string match "::tablelist::displayText*" $script]} { $w window configure $index -pady $padY -create $msgScript set path [lindex [$w dump -window $index] 1] if {[string compare $path ""] != 0 && [string compare [winfo class $path] "Message"] == 0} { eval $msgScript } } elseif {[string compare $alignment "right"] == 0} { $w window create index2Mark-1c -pady $padY -create $msgScript $w delete $index1 index2Mark-2c } else { $w window create $index1+1c -pady $padY -create $msgScript $w delete $index1+2c index2Mark } } else { # # Insert the message and aux. windows # if {$auxType == 1} { ;# image set aux [lreplace $aux end end $auxWidth] } else { ;# window if {[$aux cget -width] != $auxWidth} { $aux configure -width $auxWidth } } insertMlElem $w $index1 $msgScript $aux $auxType $alignment } } } #------------------------------------------------------------------------------ # tablelist::setImgLabelWidth # # Sets the width of the image label embedded into the text widget w at the # given index to the specified value. #------------------------------------------------------------------------------ proc tablelist::setImgLabelWidth {w index width} { if {[catch {$w window cget $index -create} script] == 0 && [string match "::tablelist::displayImage *" $script]} { if {$width != [lindex $script end]} { set padY [expr {[$w cget -spacing1] == 0}] set script [lreplace $script end end $width] $w window configure $index -pady $padY -create $script set path [lindex [$w dump -window $index] 1] if {[string compare $path ""] != 0} { $path configure -width $width } } return 1 } else { return 0 } } #------------------------------------------------------------------------------ # tablelist::setImgLabelAnchor # # Sets the anchor of the image label embedded into the text widget w at the # given index to the specified value. #------------------------------------------------------------------------------ proc tablelist::setImgLabelAnchor {w index anchor} { set script [$w window cget $index -create] if {[string compare $anchor [lindex $script 4]] != 0} { set padY [expr {[$w cget -spacing1] == 0}] set script [lreplace $script 4 4 $anchor] $w window configure $index -pady $padY -create $script set path [lindex [$w dump -window $index] 1] if {[string compare $path ""] != 0} { $path configure -anchor $anchor } } } #------------------------------------------------------------------------------ # tablelist::appendComplexElem # # Adjusts the given text and the width of the auxiliary object (image or # window) corresponding to the specified cell of the tablelist widget win, and # inserts the text and the auxiliary object (if any) just before the newline # character at the end of the specified line of the tablelist's body. #------------------------------------------------------------------------------ proc tablelist::appendComplexElem {win key row col text pixels alignment snipStr cellFont cellTags line} { # # Adjust the cell text and the image or window width # set multiline [string match "*\n*" $text] upvar ::tablelist::ns${win}::data data if {$pixels == 0} { ;# convention: dynamic width if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } } set aux [getAuxData $win $key $col auxType auxWidth $pixels] set maxTextWidth $pixels if {$pixels != 0} { incr pixels $data($col-delta) set maxTextWidth [getMaxTextWidth $pixels $auxWidth] if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > \ $maxTextWidth} { set multiline 1 } } } variable snipSides set snipSide $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } adjustMlElem $win list auxWidth $cellFont $pixels $snipSide $snipStr set msgScript [list ::tablelist::displayText $win $key $col \ [join $list "\n"] $cellFont $maxTextWidth $alignment] } else { adjustElem $win text auxWidth $cellFont $pixels $snipSide $snipStr } # # Insert the text and the auxiliary object (if any) just before the newline # set w $data(body) if {$auxType == 0} { ;# no image or window if {$multiline} { $w insert $line.end "\t\t" $cellTags set padY [expr {[$w cget -spacing1] == 0}] $w window create $line.end-1c -pady $padY -create $msgScript } else { $w insert $line.end "\t$text\t" $cellTags } } else { $w insert $line.end "\t\t" $cellTags if {$auxType == 1} { ;# image # # Update the creation script for the image label # set aux [lreplace $aux end end $auxWidth] } else { ;# window # # Create a frame and evaluate the script that # creates a child window within the frame # tk::frame $aux -borderwidth 0 -class TablelistWindow -container 0 \ -height $data($key,$col-reqHeight) \ -highlightthickness 0 -relief flat \ -takefocus 0 -width $auxWidth catch {$aux configure -padx 0 -pady 0} bindtags $aux [linsert [bindtags $aux] 1 \ $data(bodyTag) TablelistBody] uplevel #0 $data($key,$col-window) [list $win $row $col $aux.w] } if {$multiline} { insertMlElem $w $line.end-1c $msgScript $aux $auxType $alignment } else { insertElem $w $line.end-1c $text $aux $auxType $alignment } } } #------------------------------------------------------------------------------ # tablelist::makeColFontAndTagLists # # Builds the lists data(colFontList) of the column fonts and data(colTagsList) # of the column tag names for the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::makeColFontAndTagLists win { upvar ::tablelist::ns${win}::data data set widgetFont $data(-font) set data(colFontList) {} set data(colTagsList) {} set data(hasColTags) 0 set viewable [winfo viewable $win] variable canElide for {set col 0} {$col < $data(colCount)} {incr col} { set tagNames {} if {[info exists data($col-font)]} { lappend data(colFontList) $data($col-font) lappend tagNames col-font-$data($col-font) set data(hasColTags) 1 } else { lappend data(colFontList) $widgetFont } foreach opt {-background -foreground} { if {[info exists data($col$opt)]} { lappend tagNames col$opt-$data($col$opt) set data(hasColTags) 1 } } if {$viewable && $data($col-hide) && $canElide} { lappend tagNames hiddenCol set data(hasColTags) 1 } lappend data(colTagsList) $tagNames } } #------------------------------------------------------------------------------ # tablelist::makeSortAndArrowColLists # # Builds the lists data(sortColList) of the sort columns and data(arrowColList) # of the arrow columns for the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::makeSortAndArrowColLists win { upvar ::tablelist::ns${win}::data data set data(sortColList) {} set data(arrowColList) {} # # Build a list of {col sortRank} pairs and sort it based on sortRank # set pairList {} for {set col 0} {$col < $data(colCount)} {incr col} { if {$data($col-sortRank) > 0} { lappend pairList [list $col $data($col-sortRank)] } } set pairList [lsort -integer -index 1 $pairList] # # Build data(sortColList) and data(arrowColList), and update # the sort ranks to have values from 1 to [llength $pairList] # set sortRank 1 foreach pair $pairList { set col [lindex $pair 0] lappend data(sortColList) $col set data($col-sortRank) $sortRank if {$sortRank < 10 && $data(-showarrow) && $data($col-showarrow)} { lappend data(arrowColList) $col configCanvas $win $col raiseArrow $win $col } incr sortRank } } #------------------------------------------------------------------------------ # tablelist::setupColumns # # Updates the value of the -colums configuration option for the tablelist # widget win by using the width, title, and alignment specifications given in # the columns argument, and creates the corresponding label (and separator) # widgets if createLabels is true. #------------------------------------------------------------------------------ proc tablelist::setupColumns {win columns createLabels} { variable usingTile variable configSpecs variable configOpts variable alignments upvar ::tablelist::ns${win}::data data set argCount [llength $columns] set colConfigVals {} # # Check the syntax of columns before performing any changes # for {set n 0} {$n < $argCount} {incr n} { # # Get the column width # set width [lindex $columns $n] set width [format "%d" $width] ;# integer check with error message # # Get the column title # if {[incr n] == $argCount} { return -code error "column title missing" } set title [lindex $columns $n] # # Get the column alignment # set alignment left if {[incr n] < $argCount} { set next [lindex $columns $n] if {[catch {format "%d" $next}] == 0} { ;# integer check incr n -1 } else { set alignment [mwutil::fullOpt "alignment" $next $alignments] } } # # Append the properly formatted values of width, # title, and alignment to the list colConfigVals # lappend colConfigVals $width $title $alignment } # # Save the value of colConfigVals in data(-columns) # set data(-columns) $colConfigVals # # Delete the labels, canvases, and separators if requested # if {$createLabels} { foreach w [winfo children $data(hdrTxtFr)] { destroy $w } foreach w [winfo children $win] { if {[regexp {^sep[0-9]+$} [winfo name $w]]} { destroy $w } } set data(fmtCmdFlagList) {} set data(hiddenColCount) 0 } # # Build the list data(colList), and create # the labels and canvases if requested # set widgetFont $data(-font) set oldColCount $data(colCount) set data(colList) {} set data(colCount) 0 set data(lastCol) -1 set col 0 foreach {width title alignment} $data(-columns) { # # Append the width in pixels and the # alignment to the list data(colList) # if {$width > 0} { ;# convention: width in characters set pixels [charsToPixels $win $widgetFont $width] set data($col-lastStaticWidth) $pixels } elseif {$width < 0} { ;# convention: width in pixels set pixels [expr {(-1)*$width}] set data($col-lastStaticWidth) $pixels } else { ;# convention: dynamic width set pixels 0 } lappend data(colList) $pixels $alignment incr data(colCount) set data(lastCol) $col if {$createLabels} { set data($col-elide) 0 foreach {name val} {delta 0 lastStaticWidth 0 maxPixels 0 sortOrder "" sortRank 0 isSnipped 0 changesnipside 0 editable 0 editwindow entry hide 0 maxwidth 0 resizable 1 showarrow 1 showlinenumbers 0 sortmode ascii wrap 0} { if {![info exists data($col-$name)]} { set data($col-$name) $val } } lappend data(fmtCmdFlagList) [info exists data($col-formatcommand)] incr data(hiddenColCount) $data($col-hide) # # Create the label # set w $data(hdrTxtFrLbl)$col if {$usingTile} { ttk::label $w -style TablelistHeader.TLabel -image "" \ -padding {1 1 1 1} -takefocus 0 -text "" \ -textvariable "" -underline -1 -wraplength 0 } else { tk::label $w -bitmap "" -highlightthickness 0 -image "" \ -takefocus 0 -text "" -textvariable "" \ -underline -1 -wraplength 0 } # # Apply to it the current configuration options # foreach opt $configOpts { set optGrp [lindex $configSpecs($opt) 2] if {[string compare $optGrp "l"] == 0} { set optTail [string range $opt 6 end] if {[info exists data($col$opt)]} { configLabel $w -$optTail $data($col$opt) } else { configLabel $w -$optTail $data($opt) } } elseif {[string compare $optGrp "c"] == 0} { configLabel $w $opt $data($opt) } } catch {configLabel $w -state $data(-state)} # # Replace the binding tag (T)Label with TablelistLabel # in the list of binding tags of the label # bindtags $w [lreplace [bindtags $w] 1 1 TablelistLabel] # # Create a canvas containing the sort arrows # set w $data(hdrTxtFrCanv)$col canvas $w -borderwidth 0 -highlightthickness 0 \ -relief flat -takefocus 0 regexp {^(flat|sunken)([0-9]+)x([0-9]+)$} $data(-arrowstyle) \ dummy relief width height createArrows $w $width $height $relief # # Apply to it the current configuration options # foreach opt $configOpts { if {[string compare [lindex $configSpecs($opt) 2] "c"] == 0} { $w configure $opt $data($opt) } } # # Replace the binding tag Canvas with TablelistArrow # in the list of binding tags of the canvas # bindtags $w [lreplace [bindtags $w] 1 1 TablelistArrow] if {[info exists data($col-labelimage)]} { doColConfig $col $win -labelimage $data($col-labelimage) } } # # Configure the edit window if present # if {$col == $data(editCol) && [string compare [winfo class $data(bodyFrEd)] "Mentry"] != 0} { catch {$data(bodyFrEd) configure -justify $alignment} } incr col } set data(hasFmtCmds) [expr {[lsearch -exact $data(fmtCmdFlagList) 1] >= 0}] # # Clean up the data and attributes associated with the deleted columns # for {set col $data(colCount)} {$col < $oldColCount} {incr col} { deleteColData $win $col deleteColAttribs $win $col } # # Create the separators if needed # if {$createLabels && $data(-showseparators)} { createSeps $win } } #------------------------------------------------------------------------------ # tablelist::createSeps # # Creates and manages the separators in the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::createSeps win { set sepX [getSepX] variable usingTile upvar ::tablelist::ns${win}::data data for {set col 0} {$col < $data(colCount)} {incr col} { # # Create the col'th separator and attach it to # the right edge of the col'th header label # set w $data(sep)$col if {$usingTile} { ttk::separator $w -style Seps$win.TSeparator \ -cursor $data(-cursor) -orient vertical \ -takefocus 0 } else { tk::frame $w -background $data(-background) -borderwidth 1 \ -container 0 -cursor $data(-cursor) \ -highlightthickness 0 -relief sunken \ -takefocus 0 -width 2 } place $w -in $data(hdrTxtFrLbl)$col -anchor ne -bordermode outside \ -relx 1.0 -x $sepX # # Replace the binding tag TSeparator or Frame with $data(bodyTag) # and TablelistBody in the list of binding tags of the separator # bindtags $w [lreplace [bindtags $w] 1 1 $data(bodyTag) TablelistBody] } adjustSepsWhenIdle $win } #------------------------------------------------------------------------------ # tablelist::adjustSepsWhenIdle # # Arranges for the height and vertical position of each separator in the # tablelist widget win to be adjusted at idle time. #------------------------------------------------------------------------------ proc tablelist::adjustSepsWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(sepsId)]} { return "" } set data(sepsId) [after idle [list tablelist::adjustSeps $win]] } #------------------------------------------------------------------------------ # tablelist::adjustSeps # # Adjusts the height and vertical position of each separator in the tablelist # widget win. #------------------------------------------------------------------------------ proc tablelist::adjustSeps win { upvar ::tablelist::ns${win}::data data if {[info exists data(sepsId)]} { after cancel $data(sepsId) unset data(sepsId) } # # Get the height to be applied to the separators # set w $data(body) set textIdx [$w index @0,[expr {[winfo height $w] - 1}]] set dlineinfo [$w dlineinfo $textIdx] if {$data(itemCount) == 0 || [string compare $dlineinfo ""] == 0} { set sepHeight 1 } else { foreach {x y width height baselinePos} $dlineinfo {} set sepHeight [expr {$y + $height}] } # # Set the height of the main separator (if any) and attach the # latter to the right edge of the last non-hidden title column # set startCol [expr {$data(-titlecolumns) - 1}] if {$startCol > $data(lastCol)} { set startCol $data(lastCol) } for {set col $startCol} {$col >= 0} {incr col -1} { if {!$data($col-hide)} { break } } set w $data(sep) if {$col < 0} { if {[winfo exists $w]} { place forget $w } } else { place $w -in $data(hdrTxtFrLbl)$col -anchor ne -bordermode outside \ -height [expr {$sepHeight + [winfo height $data(hdr)] - 1}] \ -relx 1.0 -x [getSepX] -y 1 if {!$data(-showlabels)} { place configure $w -y 2 } raise $w } # # Set the height and vertical position of each separator # variable usingTile if {$data(-showlabels)} { set relY 1.0 if {$usingTile} { set y 0 } else { incr sepHeight set y -1 } } else { set relY 0.0 set y 2 } foreach w [winfo children $win] { if {[regexp {^sep[0-9]+$} [winfo name $w]]} { place configure $w -height $sepHeight -rely $relY -y $y } } } #------------------------------------------------------------------------------ # tablelist::getSepX # # Returns the value of the -x option to be used when placing a separator # relative to the corresponding header label, with -anchor ne. #------------------------------------------------------------------------------ proc tablelist::getSepX {} { set x 1 variable usingTile if {$usingTile} { set currentTheme [getCurrentTheme] variable xpStyle if {([string compare $currentTheme "aqua"] == 0) || ([string compare $currentTheme "xpnative"] == 0 && $xpStyle)} { set x 0 } elseif {[string compare $currentTheme "tileqt"] == 0 && [string compare [string tolower [tileqt_currentThemeName]] \ "qtcurve"] == 0} { set x 2 } } return $x } #------------------------------------------------------------------------------ # tablelist::adjustColumns # # Applies some configuration options to the labels of the tablelist widget win, # places them in the header frame, computes and sets the tab stops for the body # text widget, and adjusts the width and height of the header frame. The # whichWidths argument specifies the dynamic-width columns or labels whose # widths are to be computed when performing these operations. The stretchCols # argument specifies whether to stretch the stretchable columns. #------------------------------------------------------------------------------ proc tablelist::adjustColumns {win whichWidths stretchCols} { set compAllColWidths [expr {[string compare $whichWidths "allCols"] == 0}] set compAllLabelWidths \ [expr {[string compare $whichWidths "allLabels"] == 0}] variable usingTile set usingAquaTheme \ [expr {$usingTile && [string compare [getCurrentTheme] "aqua"] == 0}] # # Configure the labels and compute the positions of # the tab stops to be set in the body text widget # upvar ::tablelist::ns${win}::data data set data(hdrPixels) 0 variable canElide set tabs {} set col 0 set x 0 foreach {pixels alignment} $data(colList) { set w $data(hdrTxtFrLbl)$col if {$data($col-hide) && !$canElide} { place forget $w incr col continue } # # Adjust the col'th label # if {[info exists data($col-labelalign)]} { set labelAlignment $data($col-labelalign) } else { set labelAlignment $alignment } if {$pixels != 0} { ;# convention: static width incr pixels $data($col-delta) } adjustLabel $win $col $pixels $labelAlignment if {$pixels == 0} { ;# convention: dynamic width # # Compute the column or label width if requested # if {$compAllColWidths || [lsearch -exact $whichWidths $col] >= 0} { computeColWidth $win $col } elseif {$compAllLabelWidths || [lsearch -exact $whichWidths l$col] >= 0} { computeLabelWidth $win $col } set pixels $data($col-reqPixels) if {$data($col-maxPixels) > 0 && $pixels > $data($col-maxPixels)} { set pixels $data($col-maxPixels) incr pixels $data($col-delta) adjustLabel $win $col $pixels $labelAlignment } else { incr pixels $data($col-delta) } } if {$col == $data(editCol) && ![string match "*Checkbutton" [winfo class $data(bodyFrEd)]]} { adjustEditWindow $win $pixels } set canvas $data(hdrTxtFrCanv)$col if {[lsearch -exact $data(arrowColList) $col] >= 0 && !$data($col-elide) && !$data($col-hide)} { # # Place the canvas to the left side of the label if the # latter is right-justified and to its right side otherwise # if {[string compare $labelAlignment "right"] == 0} { place $canvas -in $w -anchor w -bordermode outside \ -relx 0.0 -x $data(charWidth) -rely 0.499 -y -1 } else { place $canvas -in $w -anchor e -bordermode outside \ -relx 1.0 -x -$data(charWidth) -rely 0.499 -y -1 } raise $canvas } else { place forget $canvas } # # Place the label in the header frame # if {$data($col-elide) || $data($col-hide)} { foreach l [getSublabels $w] { place forget $l } place $w -x [expr {$x - 1}] -relheight 1.0 -width 1 lower $w } else { set labelPixels [expr {$pixels + 2*$data(charWidth)}] if {$usingAquaTheme && $col < $data(lastCol)} { incr labelPixels } place $w -x $x -relheight 1.0 -width $labelPixels } # # Append a tab stop and the alignment to the tabs list # if {!$data($col-elide) && !$data($col-hide)} { incr x $data(charWidth) switch $alignment { left { lappend tabs $x left incr x $pixels } right { incr x $pixels lappend tabs $x right } center { lappend tabs [expr {$x + $pixels/2}] center incr x $pixels } } incr x $data(charWidth) lappend tabs $x left } incr col } if {$usingAquaTheme} { place $data(hdrLbl) -x [expr {$x - 1}] } else { place $data(hdrLbl) -x $x } # # Apply the value of tabs to the body text widget # if {[info exists data(colBeingResized)]} { $data(body) tag configure visibleLines -tabs $tabs } else { $data(body) configure -tabs $tabs } # # Adjust the width and height of the frames data(hdrTxtFr) and data(hdr) # set data(hdrPixels) $x $data(hdrTxtFr) configure -width $data(hdrPixels) if {$data(-width) <= 0} { if {$stretchCols} { $data(hdr) configure -width $data(hdrPixels) $data(lb) configure -width \ [expr {$data(hdrPixels) / $data(charWidth)}] } } else { $data(hdr) configure -width 0 } adjustHeaderHeight $win # # Stretch the stretchable columns if requested, and update # the scrolled column offset and the horizontal scrollbar # if {$stretchCols} { stretchColumnsWhenIdle $win } if {![info exists data(colBeingResized)]} { updateScrlColOffsetWhenIdle $win } updateHScrlbarWhenIdle $win } #------------------------------------------------------------------------------ # tablelist::adjustLabel # # Applies some configuration options to the col'th label of the tablelist # widget win as well as to the label's sublabels (if any), and places the # sublabels. #------------------------------------------------------------------------------ proc tablelist::adjustLabel {win col pixels alignment} { # # Apply some configuration options to the label and its sublabels (if any) # upvar ::tablelist::ns${win}::data data set w $data(hdrTxtFrLbl)$col variable anchors set anchor $anchors($alignment) set borderWidth [winfo pixels $w [$w cget -borderwidth]] if {$borderWidth < 0} { set borderWidth 0 } set padX [expr {$data(charWidth) - $borderWidth}] configLabel $w -anchor $anchor -justify $alignment -padx $padX if {[info exists data($col-labelimage)]} { set imageWidth [image width $data($col-labelimage)] $w-tl configure -anchor $anchor -justify $alignment } else { set imageWidth 0 } # # Make room for the canvas displaying an up- or down-arrow if needed # set title [lindex $data(-columns) [expr {3*$col + 1}]] set labelFont [$w cget -font] if {[lsearch -exact $data(arrowColList) $col] >= 0} { set spaceWidth [font measure $labelFont -displayof $w " "] set canvas $data(hdrTxtFrCanv)$col set canvasWidth $data(arrowWidth) if {[llength $data(arrowColList)] > 1} { incr canvasWidth 6 $canvas itemconfigure sortRank \ -image sortRank$data($col-sortRank)$win } $canvas configure -width $canvasWidth set spaces " " set n 2 while {$n*$spaceWidth < $canvasWidth + $data(charWidth)} { append spaces " " incr n } set spacePixels [expr {$n * $spaceWidth}] } else { set spaces "" set spacePixels 0 } set data($col-isSnipped) 0 if {$pixels == 0} { ;# convention: dynamic width # # Set the label text # if {$imageWidth == 0} { ;# no image if {[string compare $title ""] == 0} { set text $spaces } else { set lines {} foreach line [split $title "\n"] { if {[string compare $alignment "right"] == 0} { lappend lines $spaces$line } else { lappend lines $line$spaces } } set text [join $lines "\n"] } $w configure -text $text } elseif {[string compare $title ""] == 0} { ;# image w/o text $w configure -text "" set text $spaces $w-tl configure -text $text $w-il configure -width $imageWidth } else { ;# both image and text $w configure -text "" set lines {} foreach line [split $title "\n"] { if {[string compare $alignment "right"] == 0} { lappend lines "$spaces$line " } else { lappend lines " $line$spaces" } } set text [join $lines "\n"] $w-tl configure -text $text $w-il configure -width $imageWidth } } else { # # Clip each line of title according to pixels and alignment # set lessPixels [expr {$pixels - $spacePixels}] variable snipSides set snipSide $snipSides($alignment,0) if {$imageWidth == 0} { ;# no image if {[string compare $title ""] == 0} { set text $spaces } else { set lines {} foreach line [split $title "\n"] { set lineSav $line set line [strRange $win $line $labelFont \ $lessPixels $snipSide $data(-snipstring)] if {[string compare $line $lineSav] != 0} { set data($col-isSnipped) 1 } if {[string compare $alignment "right"] == 0} { lappend lines $spaces$line } else { lappend lines $line$spaces } } set text [join $lines "\n"] } $w configure -text $text } elseif {[string compare $title ""] == 0} { ;# image w/o text $w configure -text "" if {$imageWidth + $spacePixels <= $pixels} { set text $spaces $w-tl configure -text $text $w-il configure -width $imageWidth } elseif {$spacePixels < $pixels} { set text $spaces $w-tl configure -text $text $w-il configure -width [expr {$pixels - $spacePixels}] } else { set imageWidth 0 ;# can't disp. the image set text "" } } else { ;# both image and text $w configure -text "" set gap [font measure $labelFont -displayof $win " "] if {$imageWidth + $gap + $spacePixels <= $pixels} { incr lessPixels -[expr {$imageWidth + $gap}] set lines {} foreach line [split $title "\n"] { set lineSav $line set line [strRange $win $line $labelFont \ $lessPixels $snipSide $data(-snipstring)] if {[string compare $line $lineSav] != 0} { set data($col-isSnipped) 1 } if {[string compare $alignment "right"] == 0} { lappend lines "$spaces$line " } else { lappend lines " $line$spaces" } } set text [join $lines "\n"] $w-tl configure -text $text $w-il configure -width $imageWidth } elseif {$imageWidth + $spacePixels <= $pixels} { set data($col-isSnipped) 1 set text $spaces ;# can't display the orig. text $w-tl configure -text $text $w-il configure -width $imageWidth } elseif {$spacePixels < $pixels} { set data($col-isSnipped) 1 set text $spaces ;# can't display the orig. text $w-tl configure -text $text $w-il configure -width [expr {$pixels - $spacePixels}] } else { set data($col-isSnipped) 1 set imageWidth 0 ;# can't display the image set text "" ;# can't display the text } } } # # Place the label's sublabels (if any) # if {$imageWidth == 0} { if {[info exists data($col-labelimage)]} { place forget $w-il place forget $w-tl } } else { if {[string compare $text ""] == 0} { place forget $w-tl } set margin $data(charWidth) variable usingTile switch $alignment { left { place $w-il -in $w -anchor w -bordermode outside \ -relx 0.0 -x $margin -rely 0.499 if {[string compare $text ""] != 0} { if {$usingTile} { set padding [$w cget -padding] lset padding 0 [expr {$padX + [winfo reqwidth $w-il]}] $w configure -padding $padding -text $text } else { set textX [expr {$margin + [winfo reqwidth $w-il]}] place $w-tl -in $w -anchor w -bordermode outside \ -relx 0.0 -x $textX -rely 0.499 } } } right { place $w-il -in $w -anchor e -bordermode outside \ -relx 1.0 -x -$margin -rely 0.499 if {[string compare $text ""] != 0} { if {$usingTile} { set padding [$w cget -padding] lset padding 2 [expr {$padX + [winfo reqwidth $w-il]}] $w configure -padding $padding -text $text } else { set textX [expr {-$margin - [winfo reqwidth $w-il]}] place $w-tl -in $w -anchor e -bordermode outside \ -relx 1.0 -x $textX -rely 0.499 } } } center { if {[string compare $text ""] == 0} { place $w-il -in $w -anchor center -relx 0.5 -x 0 -rely 0.499 } else { set reqWidth [expr {[winfo reqwidth $w-il] + [winfo reqwidth $w-tl]}] set iX [expr {-$reqWidth/2}] place $w-il -in $w -anchor w -relx 0.5 -x $iX -rely 0.499 if {$usingTile} { set padding [$w cget -padding] lset padding 0 [expr {$padX + [winfo reqwidth $w-il]}] $w configure -padding $padding -text $text } else { set tX [expr {$reqWidth + $iX}] place $w-tl -in $w -anchor e -relx 0.5 -x $tX \ -rely 0.499 } } } } } } #------------------------------------------------------------------------------ # tablelist::computeColWidth # # Computes the width of the col'th column of the tablelist widget win to be just # large enough to hold all the elements of the column (including its label). #------------------------------------------------------------------------------ proc tablelist::computeColWidth {win col} { upvar ::tablelist::ns${win}::data data set fmtCmdFlag [lindex $data(fmtCmdFlagList) $col] set data($col-elemWidth) 0 set data($col-widestCount) 0 # # Column elements # set row -1 foreach item $data(itemList) { incr row if {$col >= [llength $item] - 1} { continue } set key [lindex $item end] if {[info exists data($key-hide)]} { continue } set text [lindex $item $col] if {$fmtCmdFlag} { set text [formatElem $win $key $row $col $text] } set text [strToDispStr $text] getAuxData $win $key $col auxType auxWidth set cellFont [getCellFont $win $key $col] set elemWidth [getElemWidth $win $text $auxWidth $cellFont] if {$elemWidth == $data($col-elemWidth)} { incr data($col-widestCount) } elseif {$elemWidth > $data($col-elemWidth)} { set data($col-elemWidth) $elemWidth set data($col-widestCount) 1 } } set data($col-reqPixels) $data($col-elemWidth) # # Column label # computeLabelWidth $win $col } #------------------------------------------------------------------------------ # tablelist::computeLabelWidth # # Computes the width of the col'th label of the tablelist widget win and # adjusts the column's width accordingly. #------------------------------------------------------------------------------ proc tablelist::computeLabelWidth {win col} { upvar ::tablelist::ns${win}::data data set w $data(hdrTxtFrLbl)$col if {[info exists data($col-labelimage)]} { set netLabelWidth \ [expr {[winfo reqwidth $w-il] + [winfo reqwidth $w-tl]}] } else { ;# no image set netLabelWidth [expr {[winfo reqwidth $w] - 2*$data(charWidth)}] } if {$netLabelWidth < $data($col-elemWidth)} { set data($col-reqPixels) $data($col-elemWidth) } else { set data($col-reqPixels) $netLabelWidth } } #------------------------------------------------------------------------------ # tablelist::adjustHeaderHeight # # Sets the height of the header frame of the tablelist widget win to the max. # height of its children. #------------------------------------------------------------------------------ proc tablelist::adjustHeaderHeight win { # # Compute the max. label height # upvar ::tablelist::ns${win}::data data set maxLabelHeight [winfo reqheight $data(hdrLbl)] for {set col 0} {$col < $data(colCount)} {incr col} { set w $data(hdrTxtFrLbl)$col if {[string compare [winfo manager $w] ""] == 0} { continue } set reqHeight [winfo reqheight $w] if {$reqHeight > $maxLabelHeight} { set maxLabelHeight $reqHeight } foreach l [getSublabels $w] { if {[string compare [winfo manager $l] ""] == 0} { continue } set borderWidth [winfo pixels $w [$w cget -borderwidth]] if {$borderWidth < 0} { set borderWidth 0 } set reqHeight [expr {[winfo reqheight $l] + 2*$borderWidth}] if {$reqHeight > $maxLabelHeight} { set maxLabelHeight $reqHeight } } } # # Set the height of the header frame, update # the colors, and adjust the separators # $data(hdrTxtFr) configure -height $maxLabelHeight if {$data(-showlabels)} { $data(hdr) configure -height $maxLabelHeight place configure $data(hdrTxt) -y 0 place configure $data(hdrLbl) -y 0 } else { $data(hdr) configure -height 1 place configure $data(hdrTxt) -y -1 place configure $data(hdrLbl) -y -1 } updateColorsWhenIdle $win adjustSepsWhenIdle $win } #------------------------------------------------------------------------------ # tablelist::stretchColumnsWhenIdle # # Arranges for the stretchable columns of the tablelist widget win to be # stretched at idle time. #------------------------------------------------------------------------------ proc tablelist::stretchColumnsWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(stretchId)]} { return "" } set data(stretchId) [after idle [list tablelist::stretchColumns $win -1]] } #------------------------------------------------------------------------------ # tablelist::stretchColumns # # Stretches the stretchable columns to fill the tablelist window win # horizontally. The colOfFixedDelta argument specifies the column for which # the stretching is to be made using a precomputed amount of pixels. #------------------------------------------------------------------------------ proc tablelist::stretchColumns {win colOfFixedDelta} { upvar ::tablelist::ns${win}::data data if {[info exists data(stretchId)]} { after cancel $data(stretchId) unset data(stretchId) } set forceAdjust $data(forceAdjust) set data(forceAdjust) 0 if {$data(hdrPixels) == 0 || $data(-width) <= 0} { return "" } # # Get the list data(stretchableCols) of the # numerical indices of the stretchable columns # set data(stretchableCols) {} if {[string first $data(-stretch) "all"] == 0} { for {set col 0} {$col < $data(colCount)} {incr col} { lappend data(stretchableCols) $col } } else { foreach col $data(-stretch) { lappend data(stretchableCols) [colIndex $win $col 0] } } # # Compute the total number data(delta) of pixels by which the # columns are to be stretched and the total amount # data(stretchablePixels) of stretchable column widths in pixels # set data(delta) [winfo width $data(hdr)] set data(stretchablePixels) 0 set lastColToStretch -1 set col 0 foreach {pixels alignment} $data(colList) { if {$data($col-hide)} { incr col continue } if {$pixels == 0} { ;# convention: dynamic width set pixels $data($col-reqPixels) if {$data($col-maxPixels) > 0} { if {$pixels > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } } incr data(delta) -[expr {$pixels + 2*$data(charWidth)}] if {[lsearch -exact $data(stretchableCols) $col] >= 0} { incr data(stretchablePixels) $pixels set lastColToStretch $col } incr col } if {$data(delta) < 0} { set delta 0 } else { set delta $data(delta) } if {$data(stretchablePixels) == 0 && !$forceAdjust} { return "" } # # Distribute the value of delta to the stretchable # columns, proportionally to their widths in pixels # set rest $delta set col 0 foreach {pixels alignment} $data(colList) { if {$data($col-hide) || [lsearch -exact $data(stretchableCols) $col] < 0} { set data($col-delta) 0 } else { set oldDelta $data($col-delta) if {$pixels == 0} { ;# convention: dynamic width set dynamic 1 set pixels $data($col-reqPixels) if {$data($col-maxPixels) > 0} { if {$pixels > $data($col-maxPixels)} { set pixels $data($col-maxPixels) set dynamic 0 } } } else { set dynamic 0 } if {$data(stretchablePixels) == 0} { set data($col-delta) 0 } else { if {$col != $colOfFixedDelta} { set data($col-delta) \ [expr {$delta*$pixels/$data(stretchablePixels)}] } incr rest -$data($col-delta) } if {$col == $lastColToStretch} { incr data($col-delta) $rest } if {!$dynamic && $data($col-delta) != $oldDelta} { redisplayColWhenIdle $win $col } } incr col } # # Adjust the columns # adjustColumns $win {} 0 } #------------------------------------------------------------------------------ # tablelist::updateColorsWhenIdle # # Arranges for the background and foreground colors of the label, frame, and # message widgets containing the currently visible images and multiline # elements of the tablelist widget win to be updated at idle time. #------------------------------------------------------------------------------ proc tablelist::updateColorsWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(colorId)] || $data(itemCount) == 0} { return "" } set data(colorId) [after idle [list tablelist::updateColors $win]] } #------------------------------------------------------------------------------ # tablelist::updateColors # # Updates the background and foreground colors of the label, frame, and message # widgets containing the currently visible images, embedded windows, and # multiline elements of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::updateColors win { upvar ::tablelist::ns${win}::data data if {[info exists data(colorId)]} { after cancel $data(colorId) unset data(colorId) } set w $data(body) if {$data(isDisabled)} { $w tag add disabled 1.0 end } set topLeftIdx "[$w index @0,0] linestart" set btmRightIdx "[$w index @0,[expr {[winfo height $w] - 1}]] lineend" foreach {dummy path textIdx} [$w dump -window $topLeftIdx $btmRightIdx] { if {[string compare $path ""] == 0} { continue } set class [winfo class $path] set isLabel [expr {[string compare $class "Label"] == 0}] set isTblWin [expr {[string compare $class "TablelistWindow"] == 0}] set isMessage [expr {[string compare $class "Message"] == 0}] if {!$isLabel && !$isTblWin && !$isMessage} { continue } set name [winfo name $path] foreach {key col} [split [string range $name 1 end] ","] {} set tagNames [$w tag names $textIdx] # # Set the widget's background and foreground # colors to those of the containing cell # if {$data(isDisabled)} { set bg $data(-background) set fg $data(-disabledforeground) } elseif {[lsearch -exact $tagNames select] < 0} { ;# not selected if {[info exists data($key,$col-background)]} { set bg $data($key,$col-background) } elseif {[info exists data($key-background)]} { set bg $data($key-background) } elseif {[lsearch -exact $tagNames stripe] < 0 || [string compare $data(-stripebackground) ""] == 0} { if {[info exists data($col-background)]} { set bg $data($col-background) } else { set bg $data(-background) } } else { set bg $data(-stripebackground) } if {$isMessage} { if {[info exists data($key,$col-foreground)]} { set fg $data($key,$col-foreground) } elseif {[info exists data($key-foreground)]} { set fg $data($key-foreground) } elseif {[lsearch -exact $tagNames stripe] < 0 || [string compare $data(-stripeforeground) ""] == 0} { if {[info exists data($col-foreground)]} { set fg $data($col-foreground) } else { set fg $data(-foreground) } } else { set fg $data(-stripeforeground) } } } else { ;# selected if {[info exists data($key,$col-selectbackground)]} { set bg $data($key,$col-selectbackground) } elseif {[info exists data($key-selectbackground)]} { set bg $data($key-selectbackground) } elseif {[info exists data($col-selectbackground)]} { set bg $data($col-selectbackground) } else { set bg $data(-selectbackground) } if {$isMessage} { if {[info exists data($key,$col-selectforeground)]} { set fg $data($key,$col-selectforeground) } elseif {[info exists data($key-selectforeground)]} { set fg $data($key-selectforeground) } elseif {[info exists data($col-selectforeground)]} { set fg $data($col-selectforeground) } else { set fg $data(-selectforeground) } } } if {[string compare [$path cget -background] $bg] != 0} { $path configure -background $bg } if {$isMessage && [string compare [$path cget -foreground] $fg] != 0} { $path configure -foreground $fg } } } #------------------------------------------------------------------------------ # tablelist::updateScrlColOffsetWhenIdle # # Arranges for the scrolled column offset of the tablelist widget win to be # updated at idle time. #------------------------------------------------------------------------------ proc tablelist::updateScrlColOffsetWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(offsetId)]} { return "" } set data(offsetId) [after idle [list tablelist::updateScrlColOffset $win]] } #------------------------------------------------------------------------------ # tablelist::updateScrlColOffset # # Updates the scrolled column offset of the tablelist widget win to fit into # the allowed range. #------------------------------------------------------------------------------ proc tablelist::updateScrlColOffset win { upvar ::tablelist::ns${win}::data data if {[info exists data(offsetId)]} { after cancel $data(offsetId) unset data(offsetId) } set maxScrlColOffset [getMaxScrlColOffset $win] if {$data(scrlColOffset) > $maxScrlColOffset} { set data(scrlColOffset) $maxScrlColOffset adjustElidedTextWhenIdle $win } } #------------------------------------------------------------------------------ # tablelist::updateHScrlbarWhenIdle # # Arranges for the horizontal scrollbar associated with the tablelist widget # win to be updated at idle time. #------------------------------------------------------------------------------ proc tablelist::updateHScrlbarWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(hScrlbarId)]} { return "" } set data(hScrlbarId) [after idle [list tablelist::updateHScrlbar $win]] } #------------------------------------------------------------------------------ # tablelist::updateHScrlbar # # Updates the horizontal scrollbar associated with the tablelist widget win by # invoking the command specified as the value of the -xscrollcommand option. #------------------------------------------------------------------------------ proc tablelist::updateHScrlbar win { upvar ::tablelist::ns${win}::data data if {[info exists data(hScrlbarId)]} { after cancel $data(hScrlbarId) unset data(hScrlbarId) } if {$data(-titlecolumns) > 0 && [string compare $data(-xscrollcommand) ""] != 0} { eval $data(-xscrollcommand) [xviewSubCmd $win {}] } } #------------------------------------------------------------------------------ # tablelist::updateVScrlbarWhenIdle # # Arranges for the vertical scrollbar associated with the tablelist widget win # to be updated at idle time. #------------------------------------------------------------------------------ proc tablelist::updateVScrlbarWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(vScrlbarId)]} { return "" } set data(vScrlbarId) [after idle [list tablelist::updateVScrlbar $win]] } #------------------------------------------------------------------------------ # tablelist::updateVScrlbar # # Updates the vertical scrollbar associated with the tablelist widget win by # invoking the command specified as the value of the -yscrollcommand option. #------------------------------------------------------------------------------ proc tablelist::updateVScrlbar win { upvar ::tablelist::ns${win}::data data if {[info exists data(vScrlbarId)]} { after cancel $data(vScrlbarId) unset data(vScrlbarId) } if {[string compare $data(-yscrollcommand) ""] != 0} { eval $data(-yscrollcommand) [yviewSubCmd $win {}] } if {[winfo exists $data(bodyFr)]} { raise $data(bodyFr) } if {[winfo viewable $win]} { update idletasks if {![winfo exists $win]} { ;# because of update idletasks return "" } } if {$data(winCount) != 0 || $::tk_version > 8.4} { return "" } # # Destroy those label widgets containing embedded images # and those message widgets containing multiline elements # that are outside the currently visible range of text lines # set w $data(body) foreach path [$w window names] { set class [winfo class $path] if {[string compare $class "Label"] == 0 || [string compare $class "Message"] == 0} { set widgets($path) 1 } } set topLeftIdx "[$w index @0,0] linestart" set btmRightIdx "[$w index @0,[expr {[winfo height $w] - 1}]] lineend" foreach {dummy path textIdx} [$w dump -window $topLeftIdx $btmRightIdx] { set widgets($path) 0 } foreach path [array names widgets] { if {$widgets($path)} { destroy $path } } } #------------------------------------------------------------------------------ # tablelist::adjustElidedTextWhenIdle # # Arranges for the elided text ranges of the body text child of the tablelist # widget win to be updated at idle time. #------------------------------------------------------------------------------ proc tablelist::adjustElidedTextWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(elidedId)] || $data(itemCount) == 0} { return "" } set data(elidedId) [after idle [list tablelist::adjustElidedText $win]] } #------------------------------------------------------------------------------ # tablelist::adjustElidedText # # Updates the elided text ranges of the body text child of the tablelist widget # win. #------------------------------------------------------------------------------ proc tablelist::adjustElidedText win { upvar ::tablelist::ns${win}::data data if {[info exists data(elidedId)]} { after cancel $data(elidedId) unset data(elidedId) } if {[info exists data(dispId)]} { return "" } # # Remove the "hiddenCol" tag # set w $data(body) $w tag remove hiddenCol 1.0 end # # Add the "hiddenCol" tag to the contents of the hidden # columns from the top to the bottom window line # variable canElide if {$canElide && $data(hiddenColCount) > 0 && $data(itemCount) > 0} { set btmY [expr {[winfo height $w] - 1}] set topLine [expr {int([$w index @0,0])}] set btmLine [expr {int([$w index @0,$btmY])}] for {set line $topLine; set row [expr {$line - 1}]} \ {$line <= $btmLine} {set row $line; incr line} { set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key-hide)]} { continue } set textIdx1 $line.0 for {set col 0; set count 0} \ {$col < $data(colCount) && $count < $data(hiddenColCount)} \ {incr col} { set textIdx2 \ [$w search -elide "\t" $textIdx1+1c $line.end]+1c if {[string compare $textIdx2 "+1c"] == 0} { break } if {$data($col-hide)} { incr count $w tag add hiddenCol $textIdx1 $textIdx2 } set textIdx1 $textIdx2 } # # Update btmLine because it may # change due to the "hiddenCol" tag # set btmLine [expr {int([$w index @0,$btmY])}] } if {[lindex [$w yview] 1] == 1} { for {set line $btmLine; set row [expr {$line - 1}]} \ {$line >= $topLine} {set line $row; incr row -1} { set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key-hide)]} { continue } set textIdx1 $line.0 for {set col 0; set count 0} \ {$col < $data(colCount) && $count < $data(hiddenColCount)} \ {incr col} { set textIdx2 \ [$w search -elide "\t" $textIdx1+1c $line.end]+1c if {[string compare $textIdx2 "+1c"] == 0} { break } if {$data($col-hide)} { incr count $w tag add hiddenCol $textIdx1 $textIdx2 } set textIdx1 $textIdx2 } # # Update topLine because it may # change due to the "hiddenCol" tag # set topLine [expr {int([$w index @0,0])}] } } } if {$data(-titlecolumns) == 0} { return "" } # # Remove the "elidedCol" tag # $w tag remove elidedCol 1.0 end for {set col 0} {$col < $data(colCount)} {incr col} { set data($col-elide) 0 } if {$data(scrlColOffset) == 0} { adjustColumns $win {} 0 return "" } # # Find max. $data(scrlColOffset) non-hidden columns with indices >= # $data(-titlecolumns) and retain the first and last of these indices # set firstCol $data(-titlecolumns) while {$firstCol < $data(colCount) && $data($firstCol-hide)} { incr firstCol } if {$firstCol >= $data(colCount)} { return "" } set lastCol $firstCol set nonHiddenCount 1 while {$nonHiddenCount < $data(scrlColOffset) && $lastCol < $data(colCount)} { incr lastCol if {!$data($lastCol-hide)} { incr nonHiddenCount } } # # Add the "elidedCol" tag to the contents of these # columns from the top to the bottom window line # if {$data(itemCount) > 0} { set btmY [expr {[winfo height $w] - 1}] set topLine [expr {int([$w index @0,0])}] set btmLine [expr {int([$w index @0,$btmY])}] for {set line $topLine; set row [expr {$line - 1}]} \ {$line <= $btmLine} {set row $line; incr line} { set key [lindex [lindex $data(itemList) $row] end] if {![info exists data($key-hide)]} { if {[findTabs $win $line $firstCol $lastCol tabIdx1 tabIdx2]} { $w tag add elidedCol $tabIdx1 $tabIdx2+1c } } # # Update btmLine because it may # change due to the "elidedCol" tag # set btmLine [expr {int([$w index @0,$btmY])}] } if {[lindex [$w yview] 1] == 1} { for {set line $btmLine; set row [expr {$line - 1}]} \ {$line >= $topLine} {set line $row; incr row -1} { set key [lindex [lindex $data(itemList) $row] end] if {![info exists data($key-hide)]} { if {[findTabs $win $line $firstCol $lastCol \ tabIdx1 tabIdx2]} { $w tag add elidedCol $tabIdx1 $tabIdx2+1c } } # # Update topLine because it may # change due to the "elidedCol" tag # set topLine [expr {int([$w index @0,0])}] } } } # # Adjust the columns # for {set col $firstCol} {$col <= $lastCol} {incr col} { set data($col-elide) 1 } adjustColumns $win {} 0 } #------------------------------------------------------------------------------ # tablelist::redisplayWhenIdle # # Arranges for the items of the tablelist widget win to be redisplayed at idle # time. #------------------------------------------------------------------------------ proc tablelist::redisplayWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(redispId)] || $data(itemCount) == 0} { return "" } set data(redispId) [after idle [list tablelist::redisplay $win]] # # Cancel the execution of all delayed redisplayCol commands # foreach name [array names data *-redispId] { after cancel $data($name) unset data($name) } } #------------------------------------------------------------------------------ # tablelist::redisplay # # Redisplays the items of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::redisplay {win {getSelCells 1} {selCells {}}} { upvar ::tablelist::ns${win}::data data if {[info exists data(redispId)]} { after cancel $data(redispId) unset data(redispId) } # # Save the indices of the selected cells # if {$getSelCells} { set selCells [curCellSelection $win] } # # Save some data of the edit window if present # if {[set editCol $data(editCol)] >= 0} { set editRow $data(editRow) saveEditData $win } set w $data(body) set snipStr $data(-snipstring) set rowTagRefCount $data(rowTagRefCount) set cellTagRefCount $data(cellTagRefCount) set isSimple [expr {$data(imgCount) == 0 && $data(winCount) == 0}] set padY [expr {[$w cget -spacing1] == 0}] variable canElide variable snipSides set newItemList {} set row 0 set line 1 foreach item $data(itemList) { # # Empty the line, clip the elements if necessary, # and insert them with the corresponding tags # $w delete $line.0 $line.end set keyIdx [expr {[llength $item] - 1}] set key [lindex $item end] if {$rowTagRefCount == 0} { set hasRowFont 0 } else { set hasRowFont [info exists data($key-font)] } set newItem {} set col 0 if {$isSimple} { set insertArgs {} set multilineData {} foreach fmtCmdFlag $data(fmtCmdFlagList) \ colFont $data(colFontList) \ colTags $data(colTagsList) \ {pixels alignment} $data(colList) { if {$col < $keyIdx} { set text [lindex $item $col] } else { set text "" } lappend newItem $text if {$data($col-hide) && !$canElide} { incr col continue } if {$fmtCmdFlag} { set text [formatElem $win $key $row $col $text] } set text [strToDispStr $text] # # Build the list of tags to be applied to the cell # if {$hasRowFont} { set cellFont $data($key-font) } else { set cellFont $colFont } set cellTags $colTags if {$cellTagRefCount != 0} { if {[info exists data($key,$col-font)]} { set cellFont $data($key,$col-font) lappend cellTags cell-font-$data($key,$col-font) } foreach opt {-background -foreground} { if {[info exists data($key,$col$opt)]} { lappend cellTags cell$opt-$data($key,$col$opt) } } } # # Clip the element if necessary # set multiline [string match "*\n*" $text] if {$pixels == 0} { ;# convention: dynamic width if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } } if {$pixels != 0} { incr pixels $data($col-delta) if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $pixels} { set multiline 1 } } set snipSide \ $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } set text [joinList $win $list $cellFont \ $pixels $snipSide $snipStr] } else { set text [strRange $win $text $cellFont \ $pixels $snipSide $snipStr] } } if {$multiline} { lappend insertArgs "\t\t" $cellTags lappend multilineData $col $text $cellFont $alignment } else { lappend insertArgs "\t$text\t" $cellTags } incr col } # # Insert the item into the body text widget # if {[llength $insertArgs] != 0} { eval [list $w insert $line.0] $insertArgs } # # Embed the message widgets displaying multiline elements # foreach {col text font alignment} $multilineData { findTabs $win $line $col $col tabIdx1 tabIdx2 set msgScript [list ::tablelist::displayText $win $key \ $col $text $font $pixels $alignment] $w window create $tabIdx2 -pady $padY -create $msgScript } } else { foreach fmtCmdFlag $data(fmtCmdFlagList) \ colFont $data(colFontList) \ colTags $data(colTagsList) \ {pixels alignment} $data(colList) { if {$col < $keyIdx} { set text [lindex $item $col] } else { set text "" } lappend newItem $text if {$data($col-hide) && !$canElide} { incr col continue } if {$fmtCmdFlag} { set text [formatElem $win $key $row $col $text] } set text [strToDispStr $text] # # Build the list of tags to be applied to the cell # if {$hasRowFont} { set cellFont $data($key-font) } else { set cellFont $colFont } set cellTags $colTags if {$cellTagRefCount != 0} { if {[info exists data($key,$col-font)]} { set cellFont $data($key,$col-font) lappend cellTags cell-font-$data($key,$col-font) } foreach opt {-background -foreground} { if {[info exists data($key,$col$opt)]} { lappend cellTags cell$opt-$data($key,$col$opt) } } } # # Insert the text and the label or window # (if any) into the body text widget # appendComplexElem $win $key $row $col $text $pixels \ $alignment $snipStr $cellFont $cellTags $line incr col } } if {$rowTagRefCount != 0} { foreach opt {-background -foreground -font} { if {[info exists data($key$opt)]} { $w tag add row$opt-$data($key$opt) $line.0 $line.end } } } if {[info exists data($key-hide)]} { $w tag add hiddenRow $line.0 $line.end+1c } lappend newItem $key lappend newItemList $newItem set row $line incr line } set data(itemList) $newItemList # # Select the cells that were selected before # foreach cellIdx $selCells { scan $cellIdx "%d,%d" row col if {$col < $data(colCount)} { cellSelection $win set $row $col $row $col } } # # Adjust the elided text and restore the stripes in the body text widget # adjustElidedText $win makeStripes $win # # Restore the edit window if it was present before # if {$editCol >= 0} { doEditCell $win $editRow $editCol 1 } } #------------------------------------------------------------------------------ # tablelist::redisplayColWhenIdle # # Arranges for the elements of the col'th column of the tablelist widget win to # be redisplayed at idle time. #------------------------------------------------------------------------------ proc tablelist::redisplayColWhenIdle {win col} { upvar ::tablelist::ns${win}::data data if {[info exists data($col-redispId)] || [info exists data(redispId)] || $data(itemCount) == 0} { return "" } set data($col-redispId) \ [after idle [list tablelist::redisplayCol $win $col 0 end]] } #------------------------------------------------------------------------------ # tablelist::redisplayCol # # Redisplays the elements of the col'th column of the tablelist widget win, in # the range specified by first and last. #------------------------------------------------------------------------------ proc tablelist::redisplayCol {win col first last} { upvar ::tablelist::ns${win}::data data if {$first == 0 && [string first $last "end"] == 0 && [info exists data($col-redispId)]} { after cancel $data($col-redispId) unset data($col-redispId) } if {$data(itemCount) == 0 || $first < 0 || $data($col-hide)} { return "" } if {[string first $last "end"] == 0} { set last $data(lastRow) } displayItems $win set fmtCmdFlag [lindex $data(fmtCmdFlagList) $col] set colFont [lindex $data(colFontList) $col] set snipStr $data(-snipstring) set w $data(body) set pixels [lindex $data(colList) [expr {2*$col}]] if {$pixels == 0} { ;# convention: dynamic width if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } } if {$pixels != 0} { incr pixels $data($col-delta) } set alignment [lindex $data(colList) [expr {2*$col + 1}]] variable snipSides set snipSide $snipSides($alignment,$data($col-changesnipside)) for {set row $first; set line [expr {$first + 1}]} {$row <= $last} \ {set row $line; incr line} { if {$row == $data(editRow) && $col == $data(editCol)} { continue } # # Adjust the cell text and the image or window width # set item [lindex $data(itemList) $row] set key [lindex $item end] set text [lindex $item $col] if {$fmtCmdFlag} { set text [formatElem $win $key $row $col $text] } set text [strToDispStr $text] set multiline [string match "*\n*" $text] set aux [getAuxData $win $key $col auxType auxWidth $pixels] set maxTextWidth $pixels if {[info exists data($key,$col-font)]} { set cellFont $data($key,$col-font) } elseif {[info exists data($key-font)]} { set cellFont $data($key-font) } else { set cellFont $colFont } if {$pixels != 0} { set maxTextWidth [getMaxTextWidth $pixels $auxWidth] if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $maxTextWidth} { set multiline 1 } } } if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } adjustMlElem $win list auxWidth $cellFont \ $pixels $snipSide $snipStr set msgScript [list ::tablelist::displayText $win $key $col \ [join $list "\n"] $cellFont $maxTextWidth $alignment] } else { adjustElem $win text auxWidth $cellFont $pixels $snipSide $snipStr } # # Update the text widget's contents between the two tabs # findTabs $win $line $col $col tabIdx1 tabIdx2 if {$multiline} { updateMlCell $w $tabIdx1+1c $tabIdx2 $msgScript \ $aux $auxType $auxWidth $alignment } else { updateCell $w $tabIdx1+1c $tabIdx2 $text \ $aux $auxType $auxWidth $alignment } } } #------------------------------------------------------------------------------ # tablelist::makeStripesWhenIdle # # Arranges for the stripes in the body of the tablelist widget win to be # redrawn at idle time. #------------------------------------------------------------------------------ proc tablelist::makeStripesWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(stripesId)] || $data(itemCount) == 0} { return "" } set data(stripesId) [after idle [list tablelist::makeStripes $win]] } #------------------------------------------------------------------------------ # tablelist::makeStripes # # Redraws the stripes in the body of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::makeStripes win { upvar ::tablelist::ns${win}::data data if {[info exists data(stripesId)]} { after cancel $data(stripesId) unset data(stripesId) } if {[info exists data(dispId)]} { return "" } set w $data(body) $w tag remove stripe 1.0 end if {[string compare $data(-stripebackground) ""] != 0 || [string compare $data(-stripeforeground) ""] != 0} { set count 0 set inStripe 0 for {set row 0; set line 1} {$row < $data(itemCount)} \ {set row $line; incr line} { set key [lindex [lindex $data(itemList) $row] end] if {![info exists data($key-hide)]} { if {$inStripe} { $w tag add stripe $line.0 $line.end } if {[incr count] == $data(-stripeheight)} { set count 0 set inStripe [expr {!$inStripe}] } } } } updateColors $win } #------------------------------------------------------------------------------ # tablelist::showLineNumbersWhenIdle # # Arranges for the line numbers in the tablelist widget win to be redisplayed # at idle time. #------------------------------------------------------------------------------ proc tablelist::showLineNumbersWhenIdle win { upvar ::tablelist::ns${win}::data data if {[info exists data(lineNumsId)] || $data(itemCount) == 0} { return "" } set data(lineNumsId) [after idle [list tablelist::showLineNumbers $win]] } #------------------------------------------------------------------------------ # tablelist::showLineNumbers # # Redisplays the line numbers (if any) in the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::showLineNumbers win { upvar ::tablelist::ns${win}::data data if {[info exists data(lineNumsId)]} { after cancel $data(lineNumsId) unset data(lineNumsId) } # # Update the item list # set colIdxList {} for {set col 0} {$col < $data(colCount)} {incr col} { if {!$data($col-showlinenumbers)} { continue } lappend colIdxList $col set newItemList {} set line 1 foreach item $data(itemList) { set item [lreplace $item $col $col $line] lappend newItemList $item set key [lindex $item end] if {![info exists data($key-hide)]} { incr line } } set data(itemList) $newItemList redisplayColWhenIdle $win $col } if {[llength $colIdxList] == 0} { return "" } # # Update the list variable if present # condUpdateListVar $win # # Adjust the columns # adjustColumns $win $colIdxList 1 return "" } #------------------------------------------------------------------------------ # tablelist::synchronize # # This procedure is invoked either as an idle callback after the list variable # associated with the tablelist widget win was written, or directly, upon # execution of some widget commands. It makes sure that the content of the # widget is synchronized with the value of the list variable. #------------------------------------------------------------------------------ proc tablelist::synchronize win { # # Nothing to do if the list variable was not written # upvar ::tablelist::ns${win}::data data if {![info exists data(syncId)]} { return "" } # # Here we are in the case that the procedure was scheduled for # execution at idle time. However, it might have been invoked # directly, before the idle time occured; in this case we should # cancel the execution of the previously scheduled idle callback. # after cancel $data(syncId) ;# no harm if data(syncId) is no longer valid unset data(syncId) upvar #0 $data(-listvariable) var set newCount [llength $var] if {$newCount < $data(itemCount)} { # # Delete the items with indices >= newCount from the widget # set updateCount $newCount deleteRows $win $newCount $data(lastRow) 0 } elseif {$newCount > $data(itemCount)} { # # Insert the items of var with indices # >= data(itemCount) into the widget # set updateCount $data(itemCount) insertRows $win $data(itemCount) [lrange $var $data(itemCount) end] 0 } else { set updateCount $newCount } # # Update the first updateCount items of the internal list # set itemsChanged 0 for {set row 0} {$row < $updateCount} {incr row} { set oldItem [lindex $data(itemList) $row] set newItem [adjustItem [lindex $var $row] $data(colCount)] lappend newItem [lindex $oldItem end] if {[string compare $oldItem $newItem] != 0} { set data(itemList) [lreplace $data(itemList) $row $row $newItem] set itemsChanged 1 } } # # If necessary, adjust the columns and make sure # that the items will be redisplayed at idle time # if {$itemsChanged} { adjustColumns $win allCols 1 redisplayWhenIdle $win showLineNumbersWhenIdle $win } } #------------------------------------------------------------------------------ # tablelist::getSublabels # # Returns the list of the existing sublabels $w-il and $w-tl associated with # the label widget w. #------------------------------------------------------------------------------ proc tablelist::getSublabels w { set lst {} foreach lbl [list $w-il $w-tl] { if {[winfo exists $lbl]} { lappend lst $lbl } } return $lst } #------------------------------------------------------------------------------ # tablelist::parseLabelPath # # Extracts the path name of the tablelist widget as well as the column number # from the path name w of a header label. #------------------------------------------------------------------------------ proc tablelist::parseLabelPath {w winName colName} { upvar $winName win $colName col return [regexp {^(.+)\.hdr\.t\.f\.l([0-9]+)$} $w dummy win col] } #------------------------------------------------------------------------------ # tablelist::configLabel # # This procedure configures the label widget w according to the options and # their values given in args. It is needed for label widgets with sublabels. #------------------------------------------------------------------------------ proc tablelist::configLabel {w args} { foreach {opt val} $args { switch -- $opt { -active { if {[string compare [winfo class $w] "TLabel"] == 0} { set state [expr {$val ? "active" : "!active"}] $w state $state if {$val} { variable themeDefaults set bg $themeDefaults(-labelactiveBg) } else { set bg [$w cget -background] } foreach l [getSublabels $w] { $l configure -background $bg } } else { set state [expr {$val ? "active" : "normal"}] catch { $w configure -state $state foreach l [getSublabels $w] { $l configure -state $state } } } parseLabelPath $w win col upvar ::tablelist::ns${win}::data data if {[lsearch -exact $data(arrowColList) $col] >= 0} { configCanvas $win $col } } -activebackground - -activeforeground - -disabledforeground - -cursor { $w configure $opt $val foreach l [getSublabels $w] { $l configure $opt $val } } -background - -foreground - -font { if {[string compare $val ""] == 0 && [string compare [winfo class $w] "TLabel"] == 0} { variable themeDefaults set val $themeDefaults(-label[string range $opt 1 end]) } $w configure $opt $val foreach l [getSublabels $w] { $l configure $opt $val } } -padx { if {[string compare [winfo class $w] "TLabel"] == 0} { set padding [$w cget -padding] $w configure -padding \ [list $val [lindex $padding 1] $val [lindex $padding 3]] } else { $w configure $opt $val } } -pady { if {[string compare [winfo class $w] "TLabel"] == 0} { set val [winfo pixels $w $val] set padding [$w cget -padding] $w configure -padding \ [list [lindex $padding 0] $val [lindex $padding 2] $val] } else { $w configure $opt $val } } -pressed { if {[string compare [winfo class $w] "TLabel"] == 0} { set state [expr {$val ? "pressed" : "!pressed"}] $w state $state variable themeDefaults if {$val} { set bg $themeDefaults(-labelpressedBg) } else { set bg $themeDefaults(-labelactiveBg) } foreach l [getSublabels $w] { $l configure -background $bg } parseLabelPath $w win col upvar ::tablelist::ns${win}::data data if {[lsearch -exact $data(arrowColList) $col] >= 0} { configCanvas $win $col } } } -state { $w configure $opt $val if {[string compare [winfo class $w] "TLabel"] == 0} { if {[string compare $val "disabled"] == 0} { variable themeDefaults set bg $themeDefaults(-labeldisabledBg) } else { set bg [$w cget -background] } foreach l [getSublabels $w] { $l configure -background $bg } } else { foreach l [getSublabels $w] { $l configure $opt $val } } } default { if {[string compare $val [$w cget $opt]] != 0} { $w configure $opt $val } } } } } #------------------------------------------------------------------------------ # tablelist::createArrows # # Creates two arrows in the canvas w. #------------------------------------------------------------------------------ proc tablelist::createArrows {w width height relief} { if {$height < 6} { set wHeight 6 set y 1 } else { set wHeight $height set y 0 } $w configure -width $width -height $wHeight # # Delete any existing arrow image items from # the canvas and the corresponding images # foreach shape {triangleUp darkLineUp lightLineUp triangleDn darkLineDn lightLineDn} { $w delete $shape catch {image delete $shape$w} } # # Create the arrow images and canvas image items # corresponding to the procedure's arguments # $relief${width}x${height}Arrows $w foreach shape {triangleUp darkLineUp lightLineUp triangleDn darkLineDn lightLineDn} { catch {$w create image 0 $y -anchor nw -image $shape$w -tags $shape} } # # Create the sort rank image item # $w delete sortRank set x [expr {$width + 2}] set y [expr {$wHeight - 6}] $w create image $x $y -anchor nw -tags sortRank } #------------------------------------------------------------------------------ # tablelist::configCanvas # # Sets the background color of the canvas displaying an up- or down-arrow for # the given column, and fills the two arrows contained in the canvas. #------------------------------------------------------------------------------ proc tablelist::configCanvas {win col} { upvar ::tablelist::ns${win}::data data set w $data(hdrTxtFrLbl)$col set labelBg [$w cget -background] set labelFg [$w cget -foreground] if {[string compare [winfo class $w] "TLabel"] == 0} { variable themeDefaults foreach state {disabled active pressed} { $w instate $state { set labelBg $themeDefaults(-label${state}Bg) set labelFg $themeDefaults(-label${state}Fg) } } } else { catch { set state [$w cget -state] variable winSys if {[string compare $state "disabled"] == 0} { set labelFg [$w cget -disabledforeground] } elseif {[string compare $state "active"] == 0 && [string compare $winSys "classic"] != 0 && [string compare $winSys "aqua"] != 0} { set labelBg [$w cget -activebackground] set labelFg [$w cget -activeforeground] } } } set w $data(hdrTxtFrCanv)$col $w configure -background $labelBg sortRank$data($col-sortRank)$win configure -foreground $labelFg if {$data(isDisabled)} { fillArrows $w $data(-arrowdisabledcolor) $data(-arrowstyle) } else { fillArrows $w $data(-arrowcolor) $data(-arrowstyle) } } #------------------------------------------------------------------------------ # tablelist::fillArrows # # Fills the two arrows contained in the canvas w with the given color, or with # the background color of the canvas if color is an empty string. Also fills # the arrow's borders (if any) with the corresponding 3-D shadow colors. #------------------------------------------------------------------------------ proc tablelist::fillArrows {w color arrowStyle} { set bgColor [$w cget -background] if {[string compare $color ""] == 0} { set color $bgColor } getShadows $w $color darkColor lightColor foreach dir {Up Dn} { triangle$dir$w configure -foreground $color -background $bgColor if {[string match "sunken*" $arrowStyle]} { darkLine$dir$w configure -foreground $darkColor lightLine$dir$w configure -foreground $lightColor } } } #------------------------------------------------------------------------------ # tablelist::getShadows # # Computes the shadow colors for a 3-D border from a given (background) color. # This is the Tcl-counterpart of the function TkpGetShadows() in the Tk # distribution file unix/tkUnix3d.c. #------------------------------------------------------------------------------ proc tablelist::getShadows {w color darkColorName lightColorName} { upvar $darkColorName darkColor $lightColorName lightColor set rgb [winfo rgb $w $color] foreach {r g b} $rgb {} set maxIntens [lindex [winfo rgb $w white] 0] # # Compute the dark shadow color # if {[string compare $::tk_patchLevel "8.3.1"] >= 0 && $r*0.5*$r + $g*1.0*$g + $b*0.28*$b < $maxIntens*0.05*$maxIntens} { # # The background is already very dark: make the dark # color a little lighter than the background by increasing # each color component 1/4th of the way to $maxIntens # foreach comp $rgb { lappend darkRGB [expr {($maxIntens + 3*$comp)/4}] } } else { # # Compute the dark color by cutting 40% from # each of the background color components. # foreach comp $rgb { lappend darkRGB [expr {60*$comp/100}] } } set darkColor [eval format "#%04x%04x%04x" $darkRGB] # # Compute the light shadow color # if {[string compare $::tk_patchLevel "8.3.1"] >= 0 && $g > $maxIntens*0.95} { # # The background is already very bright: make the # light color a little darker than the background # by reducing each color component by 10% # foreach comp $rgb { lappend lightRGB [expr {90*$comp/100}] } } else { # # Compute the light color by boosting each background # color component by 40% or half-way to white, whichever # is greater (the first approach works better for # unsaturated colors, the second for saturated ones) # foreach comp $rgb { set comp1 [expr {140*$comp/100}] if {$comp1 > $maxIntens} { set comp1 $maxIntens } set comp2 [expr {($maxIntens + $comp)/2}] lappend lightRGB [expr {($comp1 > $comp2) ? $comp1 : $comp2}] } } set lightColor [eval format "#%04x%04x%04x" $lightRGB] } #------------------------------------------------------------------------------ # tablelist::raiseArrow # # Raises one of the two arrows contained in the canvas associated with the # given column of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::raiseArrow {win col} { upvar ::tablelist::ns${win}::data data set w $data(hdrTxtFrCanv)$col variable directions set dir $directions($data(-incrarrowtype),$data($col-sortOrder)) $w raise triangle$dir $w raise darkLine$dir $w raise lightLine$dir } #------------------------------------------------------------------------------ # tablelist::isHdrTxtFrXPosVisible # # Checks whether the given x position in the header text child of the tablelist # widget win is visible. #------------------------------------------------------------------------------ proc tablelist::isHdrTxtFrXPosVisible {win x} { upvar ::tablelist::ns${win}::data data foreach {fraction1 fraction2} [$data(hdrTxt) xview] {} return [expr {$x >= $fraction1 * $data(hdrPixels) && $x < $fraction2 * $data(hdrPixels)}] } #------------------------------------------------------------------------------ # tablelist::getScrlContentWidth # # Returns the total width of the non-hidden scrollable columns of the tablelist # widget win, in the specified range. #------------------------------------------------------------------------------ proc tablelist::getScrlContentWidth {win scrlColOffset lastCol} { upvar ::tablelist::ns${win}::data data set scrlContentWidth 0 set nonHiddenCount 0 for {set col $data(-titlecolumns)} {$col <= $lastCol} {incr col} { if {!$data($col-hide) && [incr nonHiddenCount] > $scrlColOffset} { incr scrlContentWidth [colWidth $win $col -total] } } return $scrlContentWidth } #------------------------------------------------------------------------------ # tablelist::getScrlWindowWidth # # Returns the number of pixels obtained by subtracting the widths of the non- # hidden title columns from the width of the header frame of the tablelist # widget win. #------------------------------------------------------------------------------ proc tablelist::getScrlWindowWidth win { upvar ::tablelist::ns${win}::data data set scrlWindowWidth [winfo width $data(hdr)] for {set col 0} {$col < $data(-titlecolumns) && $col < $data(colCount)} \ {incr col} { if {!$data($col-hide)} { incr scrlWindowWidth -[colWidth $win $col -total] } } return $scrlWindowWidth } #------------------------------------------------------------------------------ # tablelist::getMaxScrlColOffset # # Returns the max. scrolled column offset of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::getMaxScrlColOffset win { # # Get the number of non-hidden scrollable columns # upvar ::tablelist::ns${win}::data data set maxScrlColOffset 0 for {set col $data(-titlecolumns)} {$col < $data(colCount)} {incr col} { if {!$data($col-hide)} { incr maxScrlColOffset } } # # Decrement maxScrlColOffset while the total width of the # non-hidden scrollable columns starting with this offset # is less than the width of the window's scrollable part # set scrlWindowWidth [getScrlWindowWidth $win] if {$scrlWindowWidth > 0} { while {$maxScrlColOffset > 0} { incr maxScrlColOffset -1 set scrlContentWidth \ [getScrlContentWidth $win $maxScrlColOffset $data(lastCol)] if {$scrlContentWidth == $scrlWindowWidth} { break } elseif {$scrlContentWidth > $scrlWindowWidth} { incr maxScrlColOffset break } } } return $maxScrlColOffset } #------------------------------------------------------------------------------ # tablelist::changeScrlColOffset # # Changes the scrolled column offset of the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::changeScrlColOffset {win scrlColOffset} { # # Make sure the offset is non-negative and no # greater than the max. scrolled column offset # if {$scrlColOffset < 0} { set scrlColOffset 0 } else { set maxScrlColOffset [getMaxScrlColOffset $win] if {$scrlColOffset > $maxScrlColOffset} { set scrlColOffset $maxScrlColOffset } } # # Update data(scrlColOffset) and adjust the # elided text in the tablelist's body if necessary # upvar ::tablelist::ns${win}::data data if {$scrlColOffset != $data(scrlColOffset)} { set data(scrlColOffset) $scrlColOffset adjustElidedText $win } } #------------------------------------------------------------------------------ # tablelist::scrlXOffsetToColOffset # # Returns the scrolled column offset of the tablelist widget win, corresponding # to the desired x offset. #------------------------------------------------------------------------------ proc tablelist::scrlXOffsetToColOffset {win scrlXOffset} { upvar ::tablelist::ns${win}::data data set scrlColOffset 0 set scrlContentWidth 0 for {set col $data(-titlecolumns)} {$col < $data(colCount)} {incr col} { if {$data($col-hide)} { continue } incr scrlContentWidth [colWidth $win $col -total] if {$scrlContentWidth > $scrlXOffset} { break } else { incr scrlColOffset } } return $scrlColOffset } #------------------------------------------------------------------------------ # tablelist::scrlColOffsetToXOffset # # Returns the x offset corresponding to the specified scrolled column offset of # the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::scrlColOffsetToXOffset {win scrlColOffset} { upvar ::tablelist::ns${win}::data data set scrlXOffset 0 set nonHiddenCount 0 for {set col $data(-titlecolumns)} {$col < $data(colCount)} {incr col} { if {$data($col-hide)} { continue } if {[incr nonHiddenCount] > $scrlColOffset} { break } else { incr scrlXOffset [colWidth $win $col -total] } } return $scrlXOffset } #------------------------------------------------------------------------------ # tablelist::getNonHiddenRowCount # # Returns the number of non-hidden rows of the tablelist widget win in the # specified range. #------------------------------------------------------------------------------ proc tablelist::getNonHiddenRowCount {win first last} { upvar ::tablelist::ns${win}::data data if {$data(hiddenRowCount) == 0} { return [expr {$last - $first + 1}] } else { set count 0 for {set row $first} {$row <= $last} {incr row} { set key [lindex [lindex $data(itemList) $row] end] if {![info exists data($key-hide)]} { incr count } } } return $count } #------------------------------------------------------------------------------ # tablelist::nonHiddenRowOffsetToRowIndex # # Returns the row index corresponding to the given non-hidden row offset in the # tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::nonHiddenRowOffsetToRowIndex {win offset} { upvar ::tablelist::ns${win}::data data if {$data(hiddenRowCount) == 0} { return $offset } else { # # Rebuild the list data(nonHiddenRowList) of the row # indices indicating the non-hidden rows if needed # if {[lindex $data(nonHiddenRowList) 0] == -1} { set data(nonHiddenRowList) {} for {set row 0} {$row < $data(itemCount)} {incr row} { set key [lindex [lindex $data(itemList) $row] end] if {![info exists data($key-hide)]} { lappend data(nonHiddenRowList) $row } } } set nonHiddenCount [llength $data(nonHiddenRowList)] if {$nonHiddenCount == 0} { return 0 } else { if {$offset >= $nonHiddenCount} { set offset [expr {$nonHiddenCount - 1}] } if {$offset < 0} { set offset 0 } return [lindex $data(nonHiddenRowList) $offset] } } } kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistEdit.tcl0000644000175000017500000022307511070725164024270 0ustar domibeldomibel#============================================================================== # Contains the implementation of interactive cell editing in tablelist widgets. # # Structure of the module: # - Namespace initialization # - Public procedures related to interactive cell editing # - Private procedures implementing the interactive cell editing # - Private procedures used in bindings related to interactive cell editing # # Copyright (c) 2003-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== # # Namespace initialization # ======================== # namespace eval tablelist { # # Register the Tk core widgets entry, text, checkbutton, # and spinbox for interactive cell editing # proc addTkCoreWidgets {} { set name entry array set ::tablelist::editWin [list \ $name-creationCmd "$name %W -width 0" \ $name-putValueCmd "%W delete 0 end; %W insert 0 %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W delete 0 end; %W insert 0 %T" \ $name-getTextCmd "%W get" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 0 \ $name-isEntryLike 1 \ $name-focusWin %W \ $name-reservedKeys {Left Right} \ ] set name text array set ::tablelist::editWin [list \ $name-creationCmd "$name %W -padx 2 -pady 2 -wrap none" \ $name-putValueCmd "%W delete 1.0 end; %W insert 1.0 %T" \ $name-getValueCmd "%W get 1.0 end-1c" \ $name-putTextCmd "%W delete 1.0 end; %W insert 1.0 %T" \ $name-getTextCmd "%W get 1.0 end-1c" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 0 \ $name-isEntryLike 1 \ $name-focusWin %W \ $name-reservedKeys {Left Right Up Down Prior Next Control-Home Control-End Meta-b Meta-f Control-p Control-n Meta-less Meta-greater} \ ] set name checkbutton array set ::tablelist::editWin [list \ $name-creationCmd "createCheckbutton %W" \ $name-putValueCmd {set [%W cget -variable] %T} \ $name-getValueCmd {set [%W cget -variable]} \ $name-putTextCmd {set [%W cget -variable] %T} \ $name-getTextCmd {set [%W cget -variable]} \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "%W invoke" \ $name-fontOpt "" \ $name-useFormat 0 \ $name-useReqWidth 1 \ $name-usePadX 0 \ $name-isEntryLike 0 \ $name-focusWin %W \ $name-reservedKeys {} \ ] if {$::tk_version < 8.4} { return "" } set name spinbox array set ::tablelist::editWin [list \ $name-creationCmd "$name %W -width 0" \ $name-putValueCmd "%W delete 0 end; %W insert 0 %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W delete 0 end; %W insert 0 %T" \ $name-getTextCmd "%W get" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin %W \ $name-reservedKeys {Left Right Up Down} \ ] } addTkCoreWidgets # # Register the tile widgets ttk::entry, ttk::combobox, # and ttk::checkbutton for interactive cell editing # proc addTileWidgets {} { set name ttk::entry array set ::tablelist::editWin [list \ $name-creationCmd "createTileEntry %W" \ $name-putValueCmd "%W delete 0 end; %W insert 0 %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W delete 0 end; %W insert 0 %T" \ $name-getTextCmd "%W get" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 0 \ $name-isEntryLike 1 \ $name-focusWin %W \ $name-reservedKeys {Left Right} \ ] set name ttk::combobox array set ::tablelist::editWin [list \ $name-creationCmd "createTileCombobox %W" \ $name-putValueCmd "%W set %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W set %T" \ $name-getTextCmd "%W get" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "event generate %W " \ $name-fontOpt -font \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin %W \ $name-reservedKeys {Left Right Up Down} \ ] set name ttk::checkbutton array set ::tablelist::editWin [list \ $name-creationCmd "createTileCheckbutton %W" \ $name-putValueCmd {set [%W cget -variable] %T} \ $name-getValueCmd {set [%W cget -variable]} \ $name-putTextCmd {set [%W cget -variable] %T} \ $name-getTextCmd {set [%W cget -variable]} \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd {%W instate !pressed {%W invoke}} \ $name-fontOpt "" \ $name-useFormat 0 \ $name-useReqWidth 1 \ $name-usePadX 0 \ $name-isEntryLike 0 \ $name-focusWin %W \ $name-reservedKeys {} \ ] } if {$::tk_version >= 8.4 && [llength [package versions tile]] > 0} { addTileWidgets } } # # Public procedures related to interactive cell editing # ===================================================== # #------------------------------------------------------------------------------ # tablelist::addBWidgetEntry # # Registers the Entry widget from the BWidget package for interactive cell # editing. #------------------------------------------------------------------------------ proc tablelist::addBWidgetEntry {{name Entry}} { checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "Entry %W -width 0" \ $name-putValueCmd "%W delete 0 end; %W insert 0 %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W delete 0 end; %W insert 0 %T" \ $name-getTextCmd "%W get" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 0 \ $name-isEntryLike 1 \ $name-focusWin %W \ $name-reservedKeys {Left Right} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addBWidgetSpinBox # # Registers the SpinBox widget from the BWidget package for interactive cell # editing. #------------------------------------------------------------------------------ proc tablelist::addBWidgetSpinBox {{name SpinBox}} { checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "SpinBox %W -editable 1 -width 0" \ $name-putValueCmd "%W configure -text %T" \ $name-getValueCmd "%W cget -text" \ $name-putTextCmd "%W configure -text %T" \ $name-getTextCmd "%W cget -text" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin %W.e \ $name-reservedKeys {Left Right Up Down Prior Next} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addBWidgetComboBox # # Registers the ComboBox widget from the BWidget package for interactive cell # editing. #------------------------------------------------------------------------------ proc tablelist::addBWidgetComboBox {{name ComboBox}} { checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "ComboBox %W -editable 1 -width 0" \ $name-putValueCmd "%W configure -text %T" \ $name-getValueCmd "%W cget -text" \ $name-putTextCmd "%W configure -text %T" \ $name-getTextCmd "%W cget -text" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "%W.a invoke" \ $name-fontOpt -font \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin %W.e \ $name-reservedKeys {Left Right Up Down} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addIncrEntryfield # # Registers the entryfield widget from the Iwidgets package for interactive # cell editing. #------------------------------------------------------------------------------ proc tablelist::addIncrEntryfield {{name entryfield}} { checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "iwidgets::entryfield %W -width 0" \ $name-putValueCmd "%W clear; %W insert 0 %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W clear; %W insert 0 %T" \ $name-getTextCmd "%W get" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -textfont \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 0 \ $name-isEntryLike 1 \ $name-focusWin {[%W component entry]} \ $name-reservedKeys {Left Right} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addIncrDateTimeWidget # # Registers the datefield, dateentry, timefield, or timeentry widget from the # Iwidgets package, with or without the -clicks option for its get subcommand, # for interactive cell editing. #------------------------------------------------------------------------------ proc tablelist::addIncrDateTimeWidget {widgetType args} { if {![regexp {^(datefield|dateentry|timefield|timeentry)$} $widgetType]} { return -code error \ "bad widget type \"$widgetType\": must be\ datefield, dateentry, timefield, or timeentry" } switch [llength $args] { 0 { set useClicks 0 set name $widgetType } 1 { set arg [lindex $args 0] if {[string compare $arg "-seconds"] == 0} { set useClicks 1 set name $widgetType } else { set useClicks 0 set name $arg } } 2 { set arg0 [lindex $args 0] if {[string compare $arg0 "-seconds"] != 0} { return -code error "bad option \"$arg0\": must be -seconds" } set useClicks 1 set name [lindex $args 1] } default { mwutil::wrongNumArgs "addIncrDateTimeWidget\ datefield|dateentry|timefield|timeentry\ ?-seconds? ?name?" } } checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "iwidgets::$widgetType %W" \ $name-putValueCmd "%W show %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W show %T" \ $name-getTextCmd "%W get" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -textfont \ $name-useReqWidth 1 \ $name-usePadX [string match "*entry" $widgetType] \ $name-useFormat 1 \ $name-isEntryLike 1 \ $name-reservedKeys {Left Right Up Down} \ ] if {$useClicks} { lappend ::tablelist::editWin($name-getValueCmd) -clicks set ::tablelist::editWin($name-useFormat) 0 } if {[string match "date*" $widgetType]} { set ::tablelist::editWin($name-focusWin) {[%W component date]} } else { set ::tablelist::editWin($name-focusWin) {[%W component time]} } return $name } #------------------------------------------------------------------------------ # tablelist::addIncrSpinner # # Registers the spinner widget from the Iwidgets package for interactive cell # editing. #------------------------------------------------------------------------------ proc tablelist::addIncrSpinner {{name spinner}} { checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "iwidgets::spinner %W -width 0" \ $name-putValueCmd "%W clear; %W insert 0 %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W clear; %W insert 0 %T" \ $name-getTextCmd "%W get" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -textfont \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin {[%W component entry]} \ $name-reservedKeys {Left Right} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addIncrSpinint # # Registers the spinint widget from the Iwidgets package for interactive cell # editing. #------------------------------------------------------------------------------ proc tablelist::addIncrSpinint {{name spinint}} { checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "iwidgets::spinint %W -width 0" \ $name-putValueCmd "%W clear; %W insert 0 %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W clear; %W insert 0 %T" \ $name-getTextCmd "%W get" \ $name-putListCmd "" \ $name-getListCmd "" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -textfont \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin {[%W component entry]} \ $name-reservedKeys {Left Right} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addIncrCombobox # # Registers the combobox widget from the Iwidgets package for interactive cell # editing. #------------------------------------------------------------------------------ proc tablelist::addIncrCombobox {{name combobox}} { checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "createIncrCombobox %W" \ $name-putValueCmd "%W clear entry; %W insert entry 0 %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W clear entry; %W insert entry 0 %T" \ $name-getTextCmd "%W get" \ $name-putListCmd {eval [list %W insert list end] %L} \ $name-getListCmd "%W component list get 0 end" \ $name-selectCmd "%W selection set %I" \ $name-invokeCmd "%W invoke" \ $name-fontOpt -textfont \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin {[%W component entry]} \ $name-reservedKeys {Left Right Up Down Control-p Control-n} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addOakleyCombobox # # Registers Bryan Oakley's combobox widget for interactive cell editing. #------------------------------------------------------------------------------ proc tablelist::addOakleyCombobox {{name combobox}} { checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "createOakleyCombobox %W" \ $name-putValueCmd "%W delete 0 end; %W insert 0 %T" \ $name-getValueCmd "%W get" \ $name-putTextCmd "%W delete 0 end; %W insert 0 %T" \ $name-getTextCmd "%W get" \ $name-putListCmd {eval [list %W list insert end] %L} \ $name-getListCmd "%W list get 0 end" \ $name-selectCmd "%W select %I" \ $name-invokeCmd "%W open" \ $name-fontOpt -font \ $name-useFormat 1 \ $name-useReqWidth 0 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin %W.entry \ $name-reservedKeys {Left Right Up Down Prior Next} \ ] # # Patch the ::combobox::UpdateVisualAttributes procedure to make sure it # won't change the background and trough colors of the vertical scrollbar # catch {combobox::combobox} ;# enforces the evaluation of "combobox.tcl" if {[catch {rename ::combobox::UpdateVisualAttributes \ ::combobox::_UpdateVisualAttributes}] == 0} { proc ::combobox::UpdateVisualAttributes w { set vsbBackground [$w.top.vsb cget -background] set vsbTroughColor [$w.top.vsb cget -troughcolor] ::combobox::_UpdateVisualAttributes $w $w.top.vsb configure -background $vsbBackground $w.top.vsb configure -troughcolor $vsbTroughColor } } return $name } #------------------------------------------------------------------------------ # tablelist::addDateMentry # # Registers the widget created by the mentry::dateMentry command from the # Mentry package, with a given format and separator and with or without the # "-gmt 1" option for the mentry::putClockVal and mentry::getClockVal commands, # for interactive cell editing. #------------------------------------------------------------------------------ proc tablelist::addDateMentry {fmt sep args} { # # Parse the fmt argument # if {![regexp {^([dmyY])([dmyY])([dmyY])$} $fmt dummy \ fields(0) fields(1) fields(2)]} { return -code error \ "bad format \"$fmt\": must be a string of length 3,\ consisting of the letters d, m, and y or Y" } # # Check whether all the three date components are represented in fmt # for {set n 0} {$n < 3} {incr n} { set lfields($n) [string tolower $fields($n)] } if {[string compare $lfields(0) $lfields(1)] == 0 || [string compare $lfields(0) $lfields(2)] == 0 || [string compare $lfields(1) $lfields(2)] == 0} { return -code error \ "bad format \"$fmt\": must have unique components for the\ day, month, and year" } # # Parse the remaining arguments (if any) # switch [llength $args] { 0 { set useGMT 0 set name dateMentry } 1 { set arg [lindex $args 0] if {[string compare $arg "-gmt"] == 0} { set useGMT 1 set name dateMentry } else { set useGMT 0 set name $arg } } 2 { set arg0 [lindex $args 0] if {[string compare $arg0 "-gmt"] != 0} { return -code error "bad option \"$arg0\": must be -gmt" } set useGMT 1 set name [lindex $args 1] } default { mwutil::wrongNumArgs "addDateMentry format separator ?-gmt? ?name?" } } checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd [list mentry::dateMentry %W $fmt $sep] \ $name-putValueCmd "mentry::putClockVal %T %W -gmt $useGMT" \ $name-getValueCmd "mentry::getClockVal %W -gmt $useGMT" \ $name-putTextCmd "" \ $name-getTextCmd "%W getstring" \ $name-putListCmd {eval [list %W put 0] %L} \ $name-getListCmd "%W getlist" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 0 \ $name-useReqWidth 1 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin "" \ $name-reservedKeys {Left Right Up Down Prior Next} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addTimeMentry # # Registers the widget created by the mentry::timeMentry command from the # Mentry package, with a given format and separator and with or without the # "-gmt 1" option for the mentry::putClockVal and mentry::getClockVal commands, # for interactive cell editing. #------------------------------------------------------------------------------ proc tablelist::addTimeMentry {fmt sep args} { # # Parse the fmt argument # if {![regexp {^(H|I)(M)(S?)$} $fmt dummy fields(0) fields(1) fields(2)]} { return -code error \ "bad format \"$fmt\": must be a string of length 2 or 3\ starting with H or I, followed by M and optionally by S" } # # Parse the remaining arguments (if any) # switch [llength $args] { 0 { set useGMT 0 set name timeMentry } 1 { set arg [lindex $args 0] if {[string compare $arg "-gmt"] == 0} { set useGMT 1 set name timeMentry } else { set useGMT 0 set name $arg } } 2 { set arg0 [lindex $args 0] if {[string compare $arg0 "-gmt"] != 0} { return -code error "bad option \"$arg0\": must be -gmt" } set useGMT 1 set name [lindex $args 1] } default { mwutil::wrongNumArgs "addTimeMentry format separator ?-gmt? ?name?" } } checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd [list mentry::timeMentry %W $fmt $sep] \ $name-putValueCmd "mentry::putClockVal %T %W -gmt $useGMT" \ $name-getValueCmd "mentry::getClockVal %W -gmt $useGMT" \ $name-putTextCmd "" \ $name-getTextCmd "%W getstring" \ $name-putListCmd {eval [list %W put 0] %L} \ $name-getListCmd "%W getlist" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 0 \ $name-useReqWidth 1 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin "" \ $name-reservedKeys {Left Right Up Down Prior Next} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addDateTimeMentry # # Registers the widget created by the mentry::dateTimeMentry command from the # Mentry package, with a given format and given separators and with or without # the "-gmt 1" option for the mentry::putClockVal and mentry::getClockVal # commands, for interactive cell editing. #------------------------------------------------------------------------------ proc tablelist::addDateTimeMentry {fmt dateSep timeSep args} { # # Parse the fmt argument # if {![regexp {^([dmyY])([dmyY])([dmyY])(H|I)(M)(S?)$} $fmt dummy \ fields(0) fields(1) fields(2) fields(3) fields(4) fields(5)]} { return -code error \ "bad format \"$fmt\": must be a string of length 5 or 6,\ with the first 3 characters consisting of the letters d, m,\ and y or Y, followed by H or I, then M, and optionally by S" } # # Check whether all the three date components are represented in fmt # for {set n 0} {$n < 3} {incr n} { set lfields($n) [string tolower $fields($n)] } if {[string compare $lfields(0) $lfields(1)] == 0 || [string compare $lfields(0) $lfields(2)] == 0 || [string compare $lfields(1) $lfields(2)] == 0} { return -code error \ "bad format \"$fmt\": must have unique components for the\ day, month, and year" } # # Parse the remaining arguments (if any) # switch [llength $args] { 0 { set useGMT 0 set name dateTimeMentry } 1 { set arg [lindex $args 0] if {[string compare $arg "-gmt"] == 0} { set useGMT 1 set name dateTimeMentry } else { set useGMT 0 set name $arg } } 2 { set arg0 [lindex $args 0] if {[string compare $arg0 "-gmt"] != 0} { return -code error "bad option \"$arg0\": must be -gmt" } set useGMT 1 set name [lindex $args 1] } default { mwutil::wrongNumArgs "addDateTimeMentry format dateSeparator\ timeSeparator ?-gmt? ?name?" } } checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd [list mentry::dateTimeMentry %W $fmt \ $dateSep $timeSep] \ $name-putValueCmd "mentry::putClockVal %T %W -gmt $useGMT" \ $name-getValueCmd "mentry::getClockVal %W -gmt $useGMT" \ $name-putTextCmd "" \ $name-getTextCmd "%W getstring" \ $name-putListCmd {eval [list %W put 0] %L} \ $name-getListCmd "%W getlist" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 0 \ $name-useReqWidth 1 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin "" \ $name-reservedKeys {Left Right Up Down Prior Next} \ ] return $name } #------------------------------------------------------------------------------ # tablelist::addFixedPointMentry # # Registers the widget created by the mentry::fixedPointMentry command from the # Mentry package, with a given number of characters before and a given number # of digits after the decimal point, with or without the -comma option, for # interactive cell editing. #------------------------------------------------------------------------------ proc tablelist::addFixedPointMentry {cnt1 cnt2 args} { # # Check the arguments cnt1 and cnt2 # if {[catch {format %d $cnt1}] != 0 || $cnt1 <= 0} { return -code error "expected positive integer but got \"$cnt1\"" } if {[catch {format %d $cnt2}] != 0 || $cnt2 <= 0} { return -code error "expected positive integer but got \"$cnt2\"" } # # Parse the remaining arguments (if any) # switch [llength $args] { 0 { set useComma 0 set name fixedPointMentry_$cnt1.$cnt2 } 1 { set arg [lindex $args 0] if {[string compare $arg "-comma"] == 0} { set useComma 1 set name fixedPointMentry_$cnt1,$cnt2 } else { set useComma 0 set name $arg } } 2 { set arg0 [lindex $args 0] if {[string compare $arg0 "-comma"] != 0} { return -code error "bad option \"$arg0\": must be -comma" } set useComma 1 set name [lindex $args 1] } default { mwutil::wrongNumArgs "addFixedPointMentry count1 count2\ ?-comma? ?name?" } } checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd [list mentry::fixedPointMentry %W $cnt1 $cnt2] \ $name-putValueCmd "mentry::putReal %T %W" \ $name-getValueCmd "mentry::getReal %W" \ $name-putTextCmd "" \ $name-getTextCmd "%W getstring" \ $name-putListCmd {eval [list %W put 0] %L} \ $name-getListCmd "%W getlist" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 0 \ $name-useReqWidth 1 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin "" \ $name-reservedKeys {Left Right} \ ] if {$useComma} { lappend ::tablelist::editWin($name-creationCmd) -comma } return $name } #------------------------------------------------------------------------------ # tablelist::addIPAddrMentry # # Registers the widget created by the mentry::ipAddrMentry command from the # Mentry package for interactive cell editing. #------------------------------------------------------------------------------ proc tablelist::addIPAddrMentry {{name ipAddrMentry}} { checkEditWinName $name array set ::tablelist::editWin [list \ $name-creationCmd "mentry::ipAddrMentry %W" \ $name-putValueCmd "mentry::putIPAddr %T %W" \ $name-getValueCmd "mentry::getIPAddr %W" \ $name-putTextCmd "" \ $name-getTextCmd "%W getstring" \ $name-putListCmd {eval [list %W put 0] %L} \ $name-getListCmd "%W getlist" \ $name-selectCmd "" \ $name-invokeCmd "" \ $name-fontOpt -font \ $name-useFormat 0 \ $name-useReqWidth 1 \ $name-usePadX 1 \ $name-isEntryLike 1 \ $name-focusWin "" \ $name-reservedKeys {Left Right Up Down Prior Next} \ ] return $name } # # Private procedures implementing the interactive cell editing # ============================================================ # #------------------------------------------------------------------------------ # tablelist::checkEditWinName # # Generates an error if the given edit window name is one of "entry", "text", # "spinbox", "checkbutton", "ttk::entry", "ttk::combobox", or # "ttk::checkbutton". #------------------------------------------------------------------------------ proc tablelist::checkEditWinName name { if {[regexp {^(entry|text|spinbox|checkbutton)$} $name]} { return -code error \ "edit window name \"$name\" is reserved for Tk $name widgets" } if {[regexp {^ttk::(entry|combobox|checkbutton)$} $name dummy name]} { return -code error \ "edit window name \"$name\" is reserved for tile $name widgets" } } #------------------------------------------------------------------------------ # tablelist::createCheckbutton # # Creates a checkbutton widget with the given path name for interactive cell # editing in a tablelist widget. #------------------------------------------------------------------------------ proc tablelist::createCheckbutton {w args} { variable winSys switch $winSys { x11 { variable checkedImg variable uncheckedImg if {![info exists checkedImg]} { createCheckbuttonImgs } checkbutton $w -borderwidth 2 -indicatoron 0 -image $uncheckedImg \ -selectimage $checkedImg -selectcolor "" if {$::tk_version >= 8.4} { $w configure -offrelief sunken } pack $w } win32 { checkbutton $w -borderwidth 0 -font {"MS Sans Serif" 8} \ -padx 0 -pady 0 [winfo parent $w] configure -width 13 -height 13 place $w -x -1 -y -1 } classic { checkbutton $w -borderwidth 0 -font "system" -padx 0 -pady 0 [winfo parent $w] configure -width 16 -height 14 place $w -x 0 -y -1 } aqua { checkbutton $w -borderwidth 0 -font "system" -padx 0 -pady 0 [winfo parent $w] configure -width 16 -height 17 place $w -x -3 -y -1 } } foreach {opt val} $args { switch -- $opt { -font {} -state { $w configure $opt $val } } } set win [getTablelistPath $w] $w configure -variable ::tablelist::ns${win}::data(editText) } #------------------------------------------------------------------------------ # tablelist::createTileEntry # # Creates a tile entry widget with the given path name for interactive cell # editing in a tablelist widget. #------------------------------------------------------------------------------ proc tablelist::createTileEntry {w args} { if {$::tk_version < 8.5 || [regexp {^8\.5a[1-5]$} $::tk_patchLevel]} { package require tile 0.6 } createTileAliases # # The style of the tile entry widget should have -borderwidth # 2 and -padding 1. For those themes that don't honor the # -borderwidth 2 setting, set the padding to another value. # set win [getTablelistPath $w] switch [getCurrentTheme] { aqua { set padding {0 0 0 -1} } tileqt { set padding 3 } xpnative { switch [winfo rgb . SystemButtonFace] { "60652 59881 55512" - "57568 57311 58339" { set padding 2 } default { set padding 1 } } } default { set padding 1 } } styleConfig Tablelist.TEntry -borderwidth 2 -highlightthickness 0 \ -padding $padding ttk::entry $w -style Tablelist.TEntry foreach {opt val} $args { $w configure $opt $val } } #------------------------------------------------------------------------------ # tablelist::createTileCombobox # # Creates a tile combobox widget with the given path name for interactive cell # editing in a tablelist widget. #------------------------------------------------------------------------------ proc tablelist::createTileCombobox {w args} { if {$::tk_version < 8.5 || [regexp {^8\.5a[1-5]$} $::tk_patchLevel]} { package require tile 0.6 } createTileAliases set win [getTablelistPath $w] if {[string compare [getCurrentTheme] "aqua"] == 0} { styleConfig Tablelist.TCombobox -borderwidth 2 -padding {0 0 0 -1} } else { styleConfig Tablelist.TCombobox -borderwidth 2 -padding 1 } ttk::combobox $w -style Tablelist.TCombobox foreach {opt val} $args { $w configure $opt $val } } #------------------------------------------------------------------------------ # tablelist::createTileCheckbutton # # Creates a tile checkbutton widget with the given path name for interactive # cell editing in a tablelist widget. #------------------------------------------------------------------------------ proc tablelist::createTileCheckbutton {w args} { if {$::tk_version < 8.5 || [regexp {^8\.5a[1-5]$} $::tk_patchLevel]} { package require tile 0.6 } createTileAliases # # Define the checkbutton layout; use catch to suppress # the error message in case the layout already exists # set currentTheme [getCurrentTheme] if {[string compare $currentTheme "aqua"] == 0} { catch { style layout Tablelist.TCheckbutton { Checkbutton.button } } } else { catch { style layout Tablelist.TCheckbutton { Checkbutton.indicator } } styleConfig Tablelist.TCheckbutton -indicatormargin 0 } set win [getTablelistPath $w] ttk::checkbutton $w -style Tablelist.TCheckbutton \ -variable ::tablelist::ns${win}::data(editText) foreach {opt val} $args { switch -- $opt { -font {} -state { $w configure $opt $val } } } # # Adjust the dimensions of the tile checkbutton's parent # and manage the checkbutton, depending on the current theme # switch $currentTheme { aqua { [winfo parent $w] configure -width 16 -height 17 place $w -x -3 -y -2 } Aquativo { [winfo parent $w] configure -width 14 -height 14 place $w -x -1 -y -1 } blue - winxpblue { set height [winfo reqheight $w] [winfo parent $w] configure -width $height -height $height place $w -x 0 } keramik { [winfo parent $w] configure -width 16 -height 16 place $w -x -1 -y -1 } sriv - srivlg { [winfo parent $w] configure -width 15 -height 16 place $w -x -1 } tileqt { switch -- [string tolower [tileqt_currentThemeName]] { acqua { [winfo parent $w] configure -width 17 -height 18 place $w -x -1 -y -2 } kde_xp { [winfo parent $w] configure -width 13 -height 13 place $w -x 0 } keramik - thinkeramik { [winfo parent $w] configure -width 16 -height 16 place $w -x 0 } default { set height [winfo reqheight $w] [winfo parent $w] configure -width $height -height $height place $w -x 0 } } } winnative { set height [winfo reqheight $w] [winfo parent $w] configure -width $height -height $height place $w -x -2 } xpnative { set height [winfo reqheight $w] [winfo parent $w] configure -width $height -height $height if {[info exists tile::patchlevel] && [string compare $tile::patchlevel "0.8.0"] < 0} { place $w -x -2 } else { place $w -x 0 } } default { pack $w } } } #------------------------------------------------------------------------------ # tablelist::createIncrCombobox # # Creates an [incr Widgets] combobox with the given path name for interactive # cell editing in a tablelist widget. #------------------------------------------------------------------------------ proc tablelist::createIncrCombobox {w args} { eval [list iwidgets::combobox $w -dropdown 1 -editable 1 -width 0] $args # # Make sure that the entry component will receive the input focus # whenever the list component (a scrolledlistbox widget) gets unmapped # bind [$w component list] +[list focus [$w component entry]] } #------------------------------------------------------------------------------ # tablelist::createOakleyCombobox # # Creates an Oakley combobox widget with the given path name for interactive # cell editing in a tablelist widget. #------------------------------------------------------------------------------ proc tablelist::createOakleyCombobox {w args} { eval [list combobox::combobox $w -editable 1 -width 0] $args # # Repack the widget's components, to make sure that the # button will remain visible when shrinking the combobox. # This patch is needed for combobox versions earlier than 2.3. # pack forget $w.entry $w.button pack $w.button -side right -fill y -expand 0 pack $w.entry -side left -fill both -expand 1 } #------------------------------------------------------------------------------ # tablelist::doEditCell # # Processes the tablelist editcell subcommand. cmd may be an empty string, # condChangeSelection, or changeSelection. charPos stands for the character # position component of the index in the body text widget of the character # underneath the mouse cursor if this command was invoked by clicking mouse # button 1 in the body of the tablelist widget. #------------------------------------------------------------------------------ proc tablelist::doEditCell {win row col restore {cmd ""} {charPos -1}} { upvar ::tablelist::ns${win}::data data if {$data(isDisabled) || [doRowCget $row $win -hide] || $data($col-hide) || ![isCellEditable $win $row $col]} { return "" } if {$data(editRow) == $row && $data(editCol) == $col} { return "" } if {$data(editRow) >= 0 && ![doFinishEditing $win]} { return "" } # # Create a frame to be embedded into the tablelist's body, together with # a child of column-specific type; replace the binding tag Frame with # $data(editwinTag) and TablelistEdit in the frame's list of binding tags # seeCell $win $row $col set netRowHeight [lindex [bboxSubCmd $win $row] 3] set frameHeight [expr {$netRowHeight + 6}] ;# + 6 because of -pady -3 below set f $data(bodyFr) tk::frame $f -borderwidth 0 -container 0 -height $frameHeight \ -highlightthickness 0 -relief flat -takefocus 0 catch {$f configure -padx 0 -pady 0} bindtags $f [lreplace [bindtags $f] 1 1 $data(editwinTag) TablelistEdit] bind $f { array set tablelist::ns[winfo parent [winfo parent %W]]::data \ {editRow -1 editCol -1} if {[catch {tk::CancelRepeat}] != 0} { tkCancelRepeat } if {[catch {ttk::CancelRepeat}] != 0} { catch {tile::CancelRepeat} } } set name [getEditWindow $win $row $col] variable editWin set creationCmd [strMap {"%W" "$w"} $editWin($name-creationCmd)] set item [lindex $data(itemList) $row] set key [lindex $item end] append creationCmd { $editWin($name-fontOpt) [getCellFont $win $key $col]} \ { -state normal} set w $data(bodyFrEd) if {[catch {eval $creationCmd} result] != 0} { destroy $f return -code error $result } catch {$w configure -relief ridge} catch {$w configure -highlightthickness 0} clearTakefocusOpt $w set class [winfo class $w] set isCheckbtn [string match "*Checkbutton" $class] set isText [expr {[string compare $class "Text"] == 0}] set isMentry [expr {[string compare $class "Mentry"] == 0}] if {!$isCheckbtn} { catch {$w configure -borderwidth 2} } if {$isText && $data($col-wrap) && $::tk_version >= 8.5} { $w configure -wrap word } set alignment [lindex $data(colList) [expr {2*$col + 1}]] if {!$isText && !$isMentry} { catch {$w configure -justify $alignment} } # # Replace the cell's contents between the two tabs with the above frame # array set data [list editKey $key editRow $row editCol $col] findTabs $win [expr {$row + 1}] $col $col tabIdx1 tabIdx2 set b $data(body) if {$isCheckbtn} { set editIdx [$b index $tabIdx1+1c] $b delete $editIdx $tabIdx2 } else { getAuxData $win $data(editKey) $data(editCol) auxType auxWidth if {$auxType == 0} { ;# no image or window set editIdx [$b index $tabIdx1+1c] $b delete $editIdx $tabIdx2 } elseif {[string compare $alignment "right"] == 0} { $b mark set editAuxMark $tabIdx2-1c set editIdx [$b index $tabIdx1+1c] $b delete $editIdx $tabIdx2-1c } else { $b mark set editAuxMark $tabIdx1+1c set editIdx [$b index $tabIdx1+2c] $b delete $editIdx $tabIdx2 } } $b window create $editIdx -padx -3 -pady -3 -window $f $b mark set editMark $editIdx # # Insert the binding tags $data(editwinTag) and TablelistEdit # into the list of binding tags of some components # of w, just before the respective path names # if {$isMentry} { set compList [$w entries] } else { set comp [subst [strMap {"%W" "$w"} $editWin($name-focusWin)]] set compList [list $comp] set data(editFocus) $comp } foreach comp $compList { set bindTags [bindtags $comp] set idx [lsearch -exact $bindTags $comp] bindtags $comp [linsert $bindTags $idx $data(editwinTag) TablelistEdit] } # # Restore or initialize some of the edit window's data # if {$restore} { restoreEditData $win } else { # # Put the cell's contents to the edit window # set data(canceled) 0 set data(invoked) 0 set text [lindex $item $col] if {$editWin($name-useFormat) && [lindex $data(fmtCmdFlagList) $col]} { set text [formatElem $win $key $row $col $text] } catch { eval [strMap {"%W" "$w" "%T" "$text"} $editWin($name-putValueCmd)] } if {[string compare $data(-editstartcommand) ""] != 0} { set text [uplevel #0 $data(-editstartcommand) \ [list $win $row $col $text]] if {$data(canceled)} { return "" } catch { eval [strMap {"%W" "$w" "%T" "$text"} \ $editWin($name-putValueCmd)] } } # # Save the edit window's text # set data(origEditText) \ [eval [strMap {"%W" "$w"} $editWin($name-getTextCmd)]] set data(rejected) 0 if {[string compare $editWin($name-getListCmd) ""] != 0 && [string compare $editWin($name-selectCmd) ""] != 0} { # # Select the edit window's item corresponding to text # set itemList [eval [strMap {"%W" "$w"} $editWin($name-getListCmd)]] if {[set idx [lsearch -exact $itemList $text]] >= 0} { eval [strMap {"%W" "$w" "%I" "$idx"} $editWin($name-selectCmd)] } } # # Evaluate the optional command passed as argument # if {[string compare $cmd ""] != 0} { eval [list $cmd $win $row $col] } # # Set the focus and the insertion cursor # if {$charPos >= 0} { if {$isText || !$editWin($name-isEntryLike)} { focus $w } else { set hasAuxObject [expr { [info exists data($key,$col-image)] || [info exists data($key,$col-window)]}] if {[string compare $alignment "right"] == 0} { scan $tabIdx2 "%d.%d" line tabCharIdx2 if {$isMentry} { set len [string length [$w getstring]] } else { set len [$comp index end] } set number [expr {$len - $tabCharIdx2 + $charPos}] if {$hasAuxObject} { incr number 2 } } else { scan $tabIdx1 "%d.%d" line tabCharIdx1 set number [expr {$charPos - $tabCharIdx1 - 1}] if {$hasAuxObject} { incr number -2 } } if {$isMentry} { setMentryCursor $w $number } else { focus $comp $comp icursor $number } } } else { if {$isText || $isMentry || !$editWin($name-isEntryLike)} { focus $w } else { focus $comp $comp icursor end $comp selection range 0 end } } } if {$isText} { # # Adjust the edit window's height # if {[string compare [$w cget -wrap] "none"] == 0 || $::tk_version < 8.5} { scan [$w index end-1c] "%d" numLines $w configure -height $numLines } else { bind $w { %W configure -height [%W count -displaylines 1.0 end] [winfo parent %W] configure -height [winfo reqheight %W] } } if {[info exists ::wcb::version]} { wcb::cbappend $w after insert tablelist::adjustTextHeight wcb::cbappend $w after delete tablelist::adjustTextHeight } } # # Adjust the frame's dimensions and paddings # update idletasks if {![winfo exists $win]} { ;# because of update idletasks return "" } if {!$isCheckbtn} { $f configure -height [winfo reqheight $w] place $w -relwidth 1.0 -relheight 1.0 set pixels [lindex $data(colList) [expr {2*$col}]] if {$pixels == 0} { ;# convention: dynamic width set pixels $data($col-reqPixels) if {$data($col-maxPixels) > 0} { if {$pixels > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } } incr pixels $data($col-delta) adjustEditWindow $win $pixels update idletasks if {![winfo exists $win]} { ;# because of update idletasks return "" } } adjustElidedTextWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win return "" } #------------------------------------------------------------------------------ # tablelist::doCancelEditing # # Processes the tablelist cancelediting subcommand. Aborts the interactive # cell editing and restores the cell's contents after destroying the edit # window. #------------------------------------------------------------------------------ proc tablelist::doCancelEditing win { upvar ::tablelist::ns${win}::data data if {[set row $data(editRow)] < 0} { return "" } set col $data(editCol) # # Invoke the command specified by the -editendcommand option if needed # if {$data(-forceeditendcommand) && [string compare $data(-editendcommand) ""] != 0} { uplevel #0 $data(-editendcommand) \ [list $win $row $col $data(origEditText)] } if {[winfo exists $data(bodyFr)]} { destroy $data(bodyFr) set item [lindex $data(itemList) $row] set key [lindex $item end] foreach opt {-window -image} { if {[info exists data($key,$col$opt)]} { doCellConfig $row $col $win $opt $data($key,$col$opt) break } } doCellConfig $row $col $win -text [lindex $item $col] } focus $data(body) set data(canceled) 1 event generate $win <> adjustElidedTextWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win return "" } #------------------------------------------------------------------------------ # tablelist::doFinishEditing # # Processes the tablelist finishediting subcommand. Invokes the command # specified by the -editendcommand option if needed, and updates the element # just edited after destroying the edit window if the latter's content was not # rejected. Returns 1 on normal termination and 0 otherwise. #------------------------------------------------------------------------------ proc tablelist::doFinishEditing win { upvar ::tablelist::ns${win}::data data if {[set row $data(editRow)] < 0} { return 1 } set col $data(editCol) # # Get the edit window's text, and invoke the command # specified by the -editendcommand option if needed # set w $data(bodyFrEd) set name [getEditWindow $win $row $col] variable editWin set text [eval [strMap {"%W" "$w"} $editWin($name-getTextCmd)]] set item [lindex $data(itemList) $row] if {!$data(-forceeditendcommand) && [string compare $text $data(origEditText)] == 0} { set text [lindex $item $col] } else { if {[catch { eval [strMap {"%W" "$w"} $editWin($name-getValueCmd)] } text] != 0} { set data(rejected) 1 } if {[string compare $data(-editendcommand) ""] != 0} { set text \ [uplevel #0 $data(-editendcommand) [list $win $row $col $text]] } } # # Check whether the input was rejected (by the above "set data(rejected) 1" # statement or within the command specified by the -editendcommand option) # if {$data(rejected)} { if {[winfo exists $data(bodyFr)]} { seeCell $win $row $col if {[string compare [winfo class $w] "Mentry"] != 0} { focus $data(editFocus) } } else { focus $data(body) } set data(rejected) 0 set result 0 } else { if {[winfo exists $data(bodyFr)]} { destroy $data(bodyFr) set key [lindex $item end] foreach opt {-window -image} { if {[info exists data($key,$col$opt)]} { doCellConfig $row $col $win $opt $data($key,$col$opt) break } } doCellConfig $row $col $win -text $text set result 1 } else { set result 0 } focus $data(body) event generate $win <> } adjustElidedTextWhenIdle $win updateColorsWhenIdle $win adjustSepsWhenIdle $win return $result } #------------------------------------------------------------------------------ # tablelist::clearTakefocusOpt # # Sets the -takefocus option of all members of the widget hierarchy starting # with w to 0. #------------------------------------------------------------------------------ proc tablelist::clearTakefocusOpt w { catch {$w configure -takefocus 0} foreach c [winfo children $w] { clearTakefocusOpt $c } } #------------------------------------------------------------------------------ # tablelist::adjustTextHeight # # This procedure is an after-insert and after-delete callback asociated with a # text widget used for interactive cell editing. It sets the height of the # edit window to the number of lines currently contained in it. #------------------------------------------------------------------------------ proc tablelist::adjustTextHeight {w args} { if {$::tk_version < 8.5} { # # We can only count the logical lines (irrespective of wrapping) # scan [$w index end-1c] "%d" numLines } else { # # Count the display lines (taking into account the line wraps) # set numLines [$w count -displaylines 1.0 end] } $w configure -height $numLines set path [wcb::pathname $w] [winfo parent $path] configure -height [winfo reqheight $path] } #------------------------------------------------------------------------------ # tablelist::setMentryCursor # # Sets the focus to the entry child of the mentry widget w that contains the # global character position specified by number, and sets the insertion cursor # in that entry to the relative character position corresponding to number. If # that entry is not enabled then the procedure sets the focus to the last # enabled entry child preceding the found one and sets the insertion cursor to # its end. #------------------------------------------------------------------------------ proc tablelist::setMentryCursor {w number} { # # Find the entry child containing the given character # position; if the latter is contained in a label child # then take the entry immediately preceding that label # set entryIdx -1 set childIdx 0 set childCount [llength [$w cget -body]] foreach c [winfo children $w] { set class [winfo class $c] switch $class { Entry { set str [$c get] set entry $c incr entryIdx } Frame { set str [$c.e get] set entry $c.e incr entryIdx } Label { set str [$c cget -text] } } set len [string length $str] if {$number < $len} { break } elseif {$childIdx < $childCount - 1} { incr number -$len } incr childIdx } # # If the entry's state is normal then set the focus to this entry and # the insertion cursor to the relative character position corresponding # to number; otherwise set the focus to the last enabled entry child # preceding the found one and set the insertion cursor to its end # switch $class { Entry - Frame { set relIdx $number } Label { set relIdx end } } if {[string compare [$entry cget -state] "normal"] == 0} { focus $entry $entry icursor $relIdx } else { for {incr entryIdx -1} {$entryIdx >= 0} {incr entryIdx -1} { set entry [$w entrypath $entryIdx] if {[string compare [$entry cget -state] "normal"] == 0} { focus $entry $entry icursor end return "" } } } } #------------------------------------------------------------------------------ # tablelist::adjustEditWindow # # Adjusts the width and the horizontal padding of the frame containing the edit # window associated with the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::adjustEditWindow {win pixels} { # # Adjust the width of the auxiliary object (if any) # upvar ::tablelist::ns${win}::data data set aux [getAuxData $win $data(editKey) $data(editCol) auxType auxWidth] if {$auxType != 0} { ;# image or window if {$auxWidth + 4 <= $pixels} { incr auxWidth 4 incr pixels -$auxWidth } elseif {$auxWidth <= $pixels} { set pixels 0 } else { set auxWidth $pixels set pixels 0 } if {$auxType == 1} { ;# image setImgLabelWidth $data(body) editAuxMark $auxWidth } else { ;# window if {[winfo exists $aux] && [$aux cget -width] != $auxWidth} { $aux configure -width $auxWidth } } } # # Compute an appropriate width and horizontal # padding for the frame containing the edit window # set name [getEditWindow $win $data(editRow) $data(editCol)] variable editWin if {$editWin($name-useReqWidth) && [set reqWidth [winfo reqwidth $data(bodyFrEd)]] <= $pixels + 2*$data(charWidth)} { set width $reqWidth set padX [expr {$reqWidth <= $pixels ? -3 : ($pixels - $reqWidth) / 2}] } else { if {$editWin($name-usePadX)} { set amount $data(charWidth) } else { switch -- $name { text { set amount 4 } ttk::entry { if {[string compare [getCurrentTheme] "aqua"] == 0} { set amount 5 } else { set amount 3 } } default { set amount 3 } } } set width [expr {$pixels + 2*$amount}] set padX -$amount } $data(bodyFr) configure -width $width $data(body) window configure editMark -padx $padX } #------------------------------------------------------------------------------ # tablelist::setEditWinFont # # Sets the font of the edit window associated with the tablelist widget win to # that of the cell currently being edited. #------------------------------------------------------------------------------ proc tablelist::setEditWinFont win { upvar ::tablelist::ns${win}::data data set name [getEditWindow $win $data(editRow) $data(editCol)] variable editWin if {[string compare $editWin($name-fontOpt) ""] == 0} { return "" } set key [lindex [lindex $data(itemList) $data(editRow)] end] set cellFont [getCellFont $win $key $data(editCol)] $data(bodyFrEd) configure $editWin($name-fontOpt) $cellFont $data(bodyFr) configure -height [winfo reqheight $data(bodyFrEd)] } #------------------------------------------------------------------------------ # tablelist::saveEditData # # Saves some data of the edit window associated with the tablelist widget win. #------------------------------------------------------------------------------ proc tablelist::saveEditData win { upvar ::tablelist::ns${win}::data data set w $data(bodyFrEd) set entry $data(editFocus) set class [winfo class $w] set isText [expr {[string compare $class "Text"] == 0}] set isMentry [expr {[string compare $class "Mentry"] == 0}] # # Miscellaneous data # set name [getEditWindow $win $data(editRow) $data(editCol)] variable editWin set data(editText) [eval [strMap {"%W" "$w"} $editWin($name-getTextCmd)]] if {[string compare $editWin($name-getListCmd) ""] != 0} { set data(editList) \ [eval [strMap {"%W" "$w"} $editWin($name-getListCmd)]] } if {$isText} { set data(editPos) [$w index insert] set data(textSelRanges) [$w tag ranges sel] } elseif {$editWin($name-isEntryLike)} { set data(editPos) [$entry index insert] if {[set data(entryHadSel) [$entry selection present]]} { set data(entrySelFrom) [$entry index sel.first] set data(entrySelTo) [$entry index sel.last] } } set data(editHadFocus) \ [expr {[string compare [focus -lastfor $entry] $entry] == 0}] # # Configuration options and widget callbacks # saveEditConfigOpts $w if {[info exists ::wcb::version] && $editWin($name-isEntryLike) && !$isMentry} { foreach when {before after} { foreach opt {insert delete motion} { set data(entryCb-$when-$opt) \ [::wcb::callback $entry $when $opt] } } } } #------------------------------------------------------------------------------ # tablelist::saveEditConfigOpts # # Saves the non-default values of the configuration options of the edit window # w associated with a tablelist widget, as well as those of its descendants. #------------------------------------------------------------------------------ proc tablelist::saveEditConfigOpts w { regexp {^(.+)\.body\.f\.(e.*)$} $w dummy win tail upvar ::tablelist::ns${win}::data data foreach configSet [$w configure] { if {[llength $configSet] != 2} { set default [lindex $configSet 3] set current [lindex $configSet 4] if {[string compare $default $current] != 0} { set opt [lindex $configSet 0] set data($tail$opt) $current } } } foreach c [winfo children $w] { saveEditConfigOpts $c } } #------------------------------------------------------------------------------ # tablelist::restoreEditData # # Restores some data of the edit window associated with the tablelist widget # win. #------------------------------------------------------------------------------ proc tablelist::restoreEditData win { upvar ::tablelist::ns${win}::data data set w $data(bodyFrEd) set entry $data(editFocus) set class [winfo class $w] set isText [expr {[string compare $class "Text"] == 0}] set isMentry [expr {[string compare $class "Mentry"] == 0}] set isIncrDateTimeWidget [regexp {^(Date.+|Time.+)$} $class] # # Miscellaneous data # set name [getEditWindow $win $data(editRow) $data(editCol)] variable editWin if {[string compare $editWin($name-putTextCmd) ""] != 0} { eval [strMap {"%W" "$w" "%T" "$data(editText)"} \ $editWin($name-putTextCmd)] } if {[string compare $editWin($name-putListCmd) ""] != 0 && [string compare $data(editList) ""] != 0} { eval [strMap {"%W" "$w" "%L" "$data(editList)"} \ $editWin($name-putListCmd)] } if {[string compare $editWin($name-selectCmd) ""] != 0 && [set idx [lsearch -exact $data(editList) $data(editText)]] >= 0} { eval [strMap {"%W" "$w" "%I" "$idx"} $editWin($name-selectCmd)] } if {$isText} { $w mark set insert $data(editPos) if {[llength $data(textSelRanges)] != 0} { eval [list $w tag add sel] $data(textSelRanges) } } elseif {$editWin($name-isEntryLike)} { $entry icursor $data(editPos) if {$data(entryHadSel)} { $entry selection range $data(entrySelFrom) $data(entrySelTo) } } if {$data(editHadFocus)} { focus $entry } # # Configuration options and widget callbacks # restoreEditConfigOpts $w if {[info exists ::wcb::version] && $editWin($name-isEntryLike) && !$isMentry} { foreach when {before after} { foreach opt {insert delete motion} { eval [list ::wcb::callback $entry $when $opt] \ $data(entryCb-$when-$opt) } } } # # If the edit window is a datefield, dateentry, timefield, or timeentry # widget then restore its text here, because otherwise it would be # overridden when the above invocation of restoreEditConfigOpts sets # the widget's -format option. Note that this is a special case; in # general we must restore the text BEFORE the configuration options. # if {$isIncrDateTimeWidget} { eval [strMap {"%W" "$w" "%T" "$data(editText)"} \ $editWin($name-putTextCmd)] } } #------------------------------------------------------------------------------ # tablelist::restoreEditConfigOpts # # Restores the non-default values of the configuration options of the edit # window w associated with a tablelist widget, as well as those of its # descendants. #------------------------------------------------------------------------------ proc tablelist::restoreEditConfigOpts w { regexp {^(.+)\.body\.f\.(e.*)$} $w dummy win tail upvar ::tablelist::ns${win}::data data set isMentry [expr {[string compare [winfo class $w] "Mentry"] == 0}] foreach name [array names data $tail-*] { set opt [string range $name [string last "-" $name] end] if {!$isMentry || [string compare $opt "-body"] != 0} { $w configure $opt $data($name) } unset data($name) } foreach c [winfo children $w] { restoreEditConfigOpts $c } } # # Private procedures used in bindings related to interactive cell editing # ======================================================================= # #------------------------------------------------------------------------------ # tablelist::defineTablelistEdit # # Defines the bindings for the binding tag TablelistEdit. #------------------------------------------------------------------------------ proc tablelist::defineTablelistEdit {} { # # Get the supported modifier keys in the set {Alt, Meta, Command} on # the current windowing system ("x11", "win32", "classic", or "aqua") # variable winSys switch $winSys { x11 { set modList {Alt Meta} } win32 { set modList {Alt} } classic - aqua { set modList {Command} } } # # Define some bindings for the binding tag TablelistEdit # bind TablelistEdit { set tablelist::priv(clicked) 1 set tablelist::priv(clickedInEditWin) 1 focus %W } bind TablelistEdit { if {%t != 0} { ;# i.e., no generated event foreach {tablelist::W tablelist::x tablelist::y} \ [tablelist::convEventFields %W %x %y] {} set tablelist::priv(x) "" set tablelist::priv(y) "" set tablelist::priv(clicked) 0 after cancel $tablelist::priv(afterId) set tablelist::priv(afterId) "" set tablelist::priv(releasedInEditWin) 1 if {%t - $tablelist::priv(clickTime) < 300} { tablelist::moveOrActivate $tablelist::W \ $tablelist::priv(row) $tablelist::priv(col) } else { tablelist::moveOrActivate $tablelist::W \ [$tablelist::W nearest $tablelist::y] \ [$tablelist::W nearestcolumn $tablelist::x] } tablelist::condEvalInvokeCmd $tablelist::W } } bind TablelistEdit { tablelist::insertChar %W "\t" } bind TablelistEdit { tablelist::insertChar %W "\n" } bind TablelistEdit { tablelist::cancelEditing %W } foreach key {Return KP_Enter} { bind TablelistEdit <$key> { if {[string compare [winfo class %W] "Text"] == 0} { tablelist::insertChar %W "\n" } else { tablelist::finishEditing %W } } bind TablelistEdit { tablelist::finishEditing %W } } bind TablelistEdit { tablelist::goToNextPrevCell %W 1 } bind TablelistEdit { tablelist::goToNextPrevCell %W -1 } bind TablelistEdit <> { tablelist::goToNextPrevCell %W -1 } foreach modifier $modList { bind TablelistEdit <$modifier-Left> { tablelist::goLeftRight %W -1 } bind TablelistEdit <$modifier-Right> { tablelist::goLeftRight %W 1 } bind TablelistEdit <$modifier-Up> { tablelist::goUpDown %W -1 } bind TablelistEdit <$modifier-Down> { tablelist::goUpDown %W 1 } bind TablelistEdit <$modifier-Prior> { tablelist::goToPriorNextPage %W -1 } bind TablelistEdit <$modifier-Next> { tablelist::goToPriorNextPage %W 1 } bind TablelistEdit <$modifier-Home> { tablelist::goToNextPrevCell %W 1 0 -1 } bind TablelistEdit <$modifier-End> { tablelist::goToNextPrevCell %W -1 0 0 } } foreach direction {Left Right} amount {-1 1} { bind TablelistEdit <$direction> [format { if {![tablelist::isKeyReserved %%W %%K]} { tablelist::goLeftRight %%W %d } } $amount] } foreach direction {Up Down} amount {-1 1} { bind TablelistEdit <$direction> [format { if {![tablelist::isKeyReserved %%W %%K]} { tablelist::goUpDown %%W %d } } $amount] } foreach page {Prior Next} amount {-1 1} { bind TablelistEdit <$page> [format { if {![tablelist::isKeyReserved %%W %%K]} { tablelist::goToPriorNextPage %%W %d } } $amount] } bind TablelistEdit { if {![tablelist::isKeyReserved %W Control-Home]} { tablelist::goToNextPrevCell %W 1 0 -1 } } bind TablelistEdit { if {![tablelist::isKeyReserved %W Control-End]} { tablelist::goToNextPrevCell %W -1 0 0 } } foreach pattern {Tab Shift-Tab ISO_Left_Tab hpBackTab} { catch { foreach modifier {Control Meta} { bind TablelistEdit <$modifier-$pattern> [format { mwutil::processTraversal %%W Tablelist <%s> } $pattern] } } } bind TablelistEdit { set tablelist::W [tablelist::getTablelistPath %W] set tablelist::ns${tablelist::W}::data(editFocus) %W } # # Define some emacs-like key bindings for the binding tag TablelistEdit # foreach pattern {Meta-b Meta-f} amount {-1 1} { bind TablelistEdit <$pattern> [format { if {!$tk_strictMotif && ![tablelist::isKeyReserved %%W %s]} { tablelist::goLeftRight %%W %d } } $pattern $amount] } foreach pattern {Control-p Control-n} amount {-1 1} { bind TablelistEdit <$pattern> [format { if {!$tk_strictMotif && ![tablelist::isKeyReserved %%W %s]} { tablelist::goUpDown %%W %d } } $pattern $amount] } bind TablelistEdit { if {!$tk_strictMotif && ![tablelist::isKeyReserved %W Meta-less]} { tablelist::goToNextPrevCell %W 1 0 -1 } } bind TablelistEdit { if {!$tk_strictMotif && ![tablelist::isKeyReserved %W Meta-greater]} { tablelist::goToNextPrevCell %W -1 0 0 } } # # Define some bindings for the binding tag TablelistEdit that # propagate the mousewheel events to the tablelist's body # catch { bind TablelistEdit { if {![tablelist::hasMouseWheelBindings %W] && ![tablelist::isComboTopMapped %W]} { tablelist::genMouseWheelEvent \ [[tablelist::getTablelistPath %W] bodypath] %D } } bind TablelistEdit { if {![tablelist::hasMouseWheelBindings %W] && ![tablelist::isComboTopMapped %W]} { tablelist::genOptionMouseWheelEvent \ [[tablelist::getTablelistPath %W] bodypath] %D } } } foreach detail {4 5} { bind TablelistEdit [format { if {![tablelist::hasMouseWheelBindings %%W] && ![tablelist::isComboTopMapped %%W]} { event generate \ [[tablelist::getTablelistPath %%W] bodypath] } } $detail] } } #------------------------------------------------------------------------------ # tablelist::insertChar # # Inserts the string str ("\t" or "\n") into the entry-like widget w at the # point of the insertion cursor. #------------------------------------------------------------------------------ proc tablelist::insertChar {w str} { set class [winfo class $w] if {[string compare $class "Text"] == 0} { if {[string compare $str "\n"] == 0} { eval [strMap {"%W" "$w"} [bind Text ]] } else { eval [strMap {"%W" "$w"} [bind Text ]] } return -code break "" } elseif {[regexp {^(T?Entry|TCombobox|Spinbox)$} $class]} { if {[string match "T*" $class]} { if {[string compare [info procs "::ttk::entry::Insert"] ""] != 0} { ttk::entry::Insert $w $str } else { tile::entry::Insert $w $str } } elseif {[string compare [info procs "::tk::EntryInsert"] ""] != 0} { tk::EntryInsert $w $str } else { tkEntryInsert $w $str } return -code break "" } } #------------------------------------------------------------------------------ # tablelist::cancelEditing # # Invokes the doCancelEditing procedure. #------------------------------------------------------------------------------ proc tablelist::cancelEditing w { if {[isComboTopMapped $w]} { return "" } set win [getTablelistPath $w] upvar ::tablelist::ns${win}::data data if {[info exists data(sourceRow)]} { ;# move operation in progress return "" } doCancelEditing $win return -code break "" } #------------------------------------------------------------------------------ # tablelist::finishEditing # # Invokes the doFinishEditing procedure. #------------------------------------------------------------------------------ proc tablelist::finishEditing w { if {[isComboTopMapped $w]} { return "" } doFinishEditing [getTablelistPath $w] return -code break "" } #------------------------------------------------------------------------------ # tablelist::goToNextPrevCell # # Moves the edit window into the next or previous editable cell different from # the one indicated by the given row and column, if there is such a cell. #------------------------------------------------------------------------------ proc tablelist::goToNextPrevCell {w amount args} { if {[isComboTopMapped $w]} { return "" } set win [getTablelistPath $w] upvar ::tablelist::ns${win}::data data if {[llength $args] == 0} { set row $data(editRow) set col $data(editCol) set cmd condChangeSelection } else { foreach {row col} $args {} set cmd changeSelection } set oldRow $row set oldCol $col while 1 { incr col $amount if {$col < 0} { incr row $amount if {$row < 0} { set row $data(lastRow) } set col $data(lastCol) } elseif {$col > $data(lastCol)} { incr row $amount if {$row > $data(lastRow)} { set row 0 } set col 0 } if {$row == $oldRow && $col == $oldCol} { return -code break "" } elseif {![doRowCget $row $win -hide] && !$data($col-hide) && [isCellEditable $win $row $col]} { doEditCell $win $row $col 0 $cmd return -code break "" } } } #------------------------------------------------------------------------------ # tablelist::goLeftRight # # Moves the edit window into the previous or next editable cell of the current # row if the cell being edited is not the first/last editable one within that # row. #------------------------------------------------------------------------------ proc tablelist::goLeftRight {w amount} { if {[isComboTopMapped $w]} { return "" } set win [getTablelistPath $w] upvar ::tablelist::ns${win}::data data set row $data(editRow) set col $data(editCol) while 1 { incr col $amount if {$col < 0 || $col > $data(lastCol)} { return -code break "" } elseif {!$data($col-hide) && [isCellEditable $win $row $col]} { doEditCell $win $row $col 0 condChangeSelection return -code break "" } } } #------------------------------------------------------------------------------ # tablelist::goUpDown # # Invokes the goToPrevNextLine procedure. #------------------------------------------------------------------------------ proc tablelist::goUpDown {w amount} { if {[isComboTopMapped $w]} { return "" } set win [getTablelistPath $w] upvar ::tablelist::ns${win}::data data goToPrevNextLine $w $amount $data(editRow) $data(editCol) \ condChangeSelection return -code break "" } #------------------------------------------------------------------------------ # tablelist::goToPrevNextLine # # Moves the edit window into the last or first editable cell that is located in # the specified column and has a row index less/greater than the given one, if # there is such a cell. #------------------------------------------------------------------------------ proc tablelist::goToPrevNextLine {w amount row col cmd} { set win [getTablelistPath $w] upvar ::tablelist::ns${win}::data data while 1 { incr row $amount if {$row < 0 || $row > $data(lastRow)} { return 0 } elseif {![doRowCget $row $win -hide] && [isCellEditable $win $row $col]} { doEditCell $win $row $col 0 $cmd return 1 } } } #------------------------------------------------------------------------------ # tablelist::goToPriorNextPage # # Moves the edit window up or down by one page within the current column if the # cell being edited is not the first/last editable one within that column. #------------------------------------------------------------------------------ proc tablelist::goToPriorNextPage {w amount} { if {[isComboTopMapped $w]} { return "" } set win [getTablelistPath $w] upvar ::tablelist::ns${win}::data data # # Check whether there is any non-hidden editable cell # above/below the current one, in the same column # set row $data(editRow) set col $data(editCol) while 1 { incr row $amount if {$row < 0 || $row > $data(lastRow)} { return -code break "" } elseif {![doRowCget $row $win -hide] && [isCellEditable $win $row $col]} { break } } # # Scroll up/down the view by one page and get the corresponding row index # set row $data(editRow) seeRow $win $row set bbox [bboxSubCmd $win $row] yviewSubCmd $win [list scroll $amount pages] set newRow [rowIndex $win @0,[lindex $bbox 1] 0] if {$amount < 0} { if {$newRow < $row} { if {![goToPrevNextLine $w -1 [expr {$newRow + 1}] $col \ changeSelection]} { goToPrevNextLine $w 1 $newRow $col changeSelection } } else { goToPrevNextLine $w 1 -1 $col changeSelection } } else { if {$newRow > $row} { if {![goToPrevNextLine $w 1 [expr {$newRow - 1}] $col \ changeSelection]} { goToPrevNextLine $w -1 $newRow $col changeSelection } } else { goToPrevNextLine $w -1 $data(itemCount) $col changeSelection } } return -code break "" } #------------------------------------------------------------------------------ # tablelist::genMouseWheelEvent # # Generates a event with the given delta on the widget w. #------------------------------------------------------------------------------ proc tablelist::genMouseWheelEvent {w delta} { set focus [focus -displayof $w] focus $w event generate $w -delta $delta focus $focus } #------------------------------------------------------------------------------ # tablelist::genOptionMouseWheelEvent # # Generates an event with the given delta on the widget w. #------------------------------------------------------------------------------ proc tablelist::genOptionMouseWheelEvent {w delta} { set focus [focus -displayof $w] focus $w event generate $w -delta $delta focus $focus } #------------------------------------------------------------------------------ # tablelist::isKeyReserved # # Checks whether the given keysym is used in the standard binding scripts # associated with the widget w, which is assumed to be the edit window or one # of its descendants. #------------------------------------------------------------------------------ proc tablelist::isKeyReserved {w keySym} { set win [getTablelistPath $w] upvar ::tablelist::ns${win}::data data set name [getEditWindow $win $data(editRow) $data(editCol)] variable editWin return [expr {[lsearch -exact $editWin($name-reservedKeys) $keySym] >= 0}] } #------------------------------------------------------------------------------ # tablelist::hasMouseWheelBindings # # Checks whether the given widget, which is assumed to be the edit window or # one of its descendants, has mouse wheel bindings. #------------------------------------------------------------------------------ proc tablelist::hasMouseWheelBindings w { if {[string compare [winfo class $w] "TCombobox"] == 0} { return 1 } else { set bindTags [bindtags $w] return [expr {([lsearch -exact $bindTags "MentryDateTime"] >= 0 || [lsearch -exact $bindTags "MentryMeridian"] >= 0 || [lsearch -exact $bindTags "MentryIPAddr"] >= 0) && ($mentry::version >= 3.2)}] } } #------------------------------------------------------------------------------ # tablelist::isComboTopMapped # # Checks whether the given widget is a component of an Oakley combobox having # its toplevel child mapped. This is needed in our binding scripts to make # sure that the interactive cell editing won't be terminated prematurely, # because Bryan Oakley's combobox keeps the focus on its entry child even if # its toplevel component is mapped. #------------------------------------------------------------------------------ proc tablelist::isComboTopMapped w { set par [winfo parent $w] if {[string compare [winfo class $par] "Combobox"] == 0 && [winfo exists $par.top] && [winfo ismapped $par.top]} { return 1 } else { return 0 } } kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistPublic.tcl0000644000175000017500000000451211070725164024612 0ustar domibeldomibel#============================================================================== # Main Tablelist and Tablelist_tile package module. # # Copyright (c) 2000-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== namespace eval ::tablelist { # # Public variables: # variable version 4.10 variable library [file dirname [info script]] # # Creates a new tablelist widget: # namespace export tablelist # # Sort the items of a tablelist widget by one or more of its columns: # namespace export sortByColumn addToSortColumns # # Helper procedures used in binding scripts: # namespace export getTablelistPath convEventFields # # Register various widgets for interactive cell editing: # namespace export addBWidgetEntry addBWidgetSpinBox addBWidgetComboBox namespace export addIncrEntryfield addIncrDateTimeWidget \ addIncrSpinner addIncrSpinint addIncrCombobox namespace export addOakleyCombobox namespace export addDateMentry addTimeMentry addDateTimeMentry \ addFixedPointMentry addIPAddrMentry } package provide tablelist::common $::tablelist::version # # The following procedure, invoked in "tablelist.tcl" and "tablelist_tile.tcl", # sets the variable ::tablelist::usingTile to the given value and sets a trace # on this variable. # proc ::tablelist::useTile {bool} { variable usingTile $bool trace variable usingTile wu [list ::tablelist::restoreUsingTile $bool] } # # The following trace procedure is executed whenever the variable # ::tablelist::usingTile is written or unset. It restores the variable to its # original value, given by the first argument. # proc ::tablelist::restoreUsingTile {origVal varName index op} { variable usingTile $origVal switch $op { w { return -code error "it is not allowed to use both Tablelist and\ Tablelist_tile in the same application" } u { trace variable usingTile wu \ [list ::tablelist::restoreUsingTile $origVal] } } } interp alias {} ::tk::frame {} ::frame interp alias {} ::tk::label {} ::label # # Everything else needed is lazily loaded on demand, via the dispatcher # set up in the subdirectory "scripts" (see the file "tclIndex"). # lappend auto_path [file join $::tablelist::library scripts] kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistSort.tcl0000644000175000017500000003604411043435206024323 0ustar domibeldomibel#============================================================================== # Contains the implementation of the tablelist::sortByColumn and # tablelist::addToSortColumns commands, as well as of the tablelist sort, # sortbycolumn, and sortbycolumnlist subcommands. # # Structure of the module: # - Public procedures related to sorting # - Private procedure implementing the sorting # # Copyright (c) 2000-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== # # Public procedures related to sorting # ==================================== # #------------------------------------------------------------------------------ # tablelist::sortByColumn # # Sorts the contents of the tablelist widget win by its col'th column. Returns # the sort order (increasing or decreasing). #------------------------------------------------------------------------------ proc tablelist::sortByColumn {win col} { # # Check the arguments # if {![winfo exists $win]} { return -code error "bad window path name \"$win\"" } if {[string compare [winfo class $win] "Tablelist"] != 0} { return -code error "window \"$win\" is not a tablelist widget" } if {[catch {::$win columnindex $col} result] != 0} { return -code error $result } if {$result < 0 || $result >= [::$win columncount]} { return -code error "column index \"$col\" out of range" } set col $result if {[::$win columncget $col -showlinenumbers]} { return "" } # # Determine the sort order # if {[set idx [lsearch -exact [::$win sortcolumnlist] $col]] >= 0 && [string compare [lindex [::$win sortorderlist] $idx] "increasing"] == 0} { set sortOrder decreasing } else { set sortOrder increasing } # # Sort the widget's contents based on the given column # if {[catch {::$win sortbycolumn $col -$sortOrder} result] == 0} { event generate $win <> return $sortOrder } else { return -code error $result } } #------------------------------------------------------------------------------ # tablelist::addToSortColumns # # Adds the col'th column of the tablelist widget win to the latter's list of # sort columns and sorts the contents of the widget by the modified column # list. Returns the specified column's sort order (increasing or decreasing). #------------------------------------------------------------------------------ proc tablelist::addToSortColumns {win col} { # # Check the arguments # if {![winfo exists $win]} { return -code error "bad window path name \"$win\"" } if {[string compare [winfo class $win] "Tablelist"] != 0} { return -code error "window \"$win\" is not a tablelist widget" } if {[catch {::$win columnindex $col} result] != 0} { return -code error $result } if {$result < 0 || $result >= [::$win columncount]} { return -code error "column index \"$col\" out of range" } set col $result if {[::$win columncget $col -showlinenumbers]} { return "" } # # Update the lists of sort columns and orders # set sortColList [::$win sortcolumnlist] set sortOrderList [::$win sortorderlist] if {[set idx [lsearch -exact $sortColList $col]] >= 0} { if {[string compare [lindex $sortOrderList $idx] "increasing"] == 0} { set sortOrder decreasing } else { set sortOrder increasing } set sortOrderList [lreplace $sortOrderList $idx $idx $sortOrder] } else { lappend sortColList $col lappend sortOrderList increasing set sortOrder increasing } # # Sort the widget's contents according to the # modified lists of sort columns and orders # if {[catch {::$win sortbycolumnlist $sortColList $sortOrderList} result] == 0} { event generate $win <> return $sortOrder } else { return -code error $result } } # # Private procedure implementing the sorting # ========================================== # #------------------------------------------------------------------------------ # tablelist::sortItems # # Processes the tablelist sort, sortbycolumn, and sortbycolumnlist subcommands. #------------------------------------------------------------------------------ proc tablelist::sortItems {win sortColList sortOrderList} { variable canElide variable snipSides upvar ::tablelist::ns${win}::data data # # Make sure sortOrderList has the same length as sortColList # set sortColCount [llength $sortColList] set sortOrderCount [llength $sortOrderList] if {$sortOrderCount < $sortColCount} { for {set n $sortOrderCount} {$n < $sortColCount} {incr n} { lappend sortOrderList increasing } } else { set sortOrderList [lrange $sortOrderList 0 [expr {$sortColCount - 1}]] } # # Save the keys corresponding to anchorRow and activeRow, # as well as the indices of the selected cells # foreach type {anchor active} { set ${type}Key [lindex [lindex $data(itemList) $data(${type}Row)] end] } set selCells [curCellSelection $win 1] # # Save some data of the edit window if present # if {[set editCol $data(editCol)] >= 0} { set editKey $data(editKey) saveEditData $win } # # Update the sort info and sort the item list # if {[llength $sortColList] == 1 && [lindex $sortColList 0] == -1} { if {[string compare $data(-sortcommand) ""] == 0} { return -code error "value of the -sortcommand option is empty" } # # Update the sort info # for {set col 0} {$col < $data(colCount)} {incr col} { set data($col-sortRank) 0 set data($col-sortOrder) "" } set data(sortColList) {} set data(arrowColList) {} set order [lindex $sortOrderList 0] set data(sortOrder) $order # # Sort the item list # set data(itemList) \ [lsort -$order -command $data(-sortcommand) $data(itemList)] } else { ;# sorting by a column (list) # # Check the specified column indices # set sortColCount2 $sortColCount foreach col $sortColList { if {$data($col-showlinenumbers)} { incr sortColCount2 -1 } } if {$sortColCount2 == 0} { return "" } # # Update the sort info # for {set col 0} {$col < $data(colCount)} {incr col} { set data($col-sortRank) 0 set data($col-sortOrder) "" } set rank 1 foreach col $sortColList order $sortOrderList { if {$data($col-showlinenumbers)} { continue } set data($col-sortRank) $rank set data($col-sortOrder) $order incr rank } makeSortAndArrowColLists $win # # Sort the item list based on the specified columns # for {set idx [expr {$sortColCount - 1}]} {$idx >= 0} {incr idx -1} { set col [lindex $sortColList $idx] if {$data($col-showlinenumbers)} { continue } set order $data($col-sortOrder) if {[string compare $data($col-sortmode) "command"] == 0} { if {![info exists data($col-sortcommand)]} { return -code error "value of the -sortcommand option for\ column $col is missing or empty" } set data(itemList) [lsort -$order -index $col \ -command $data($col-sortcommand) $data(itemList)] } else { set data(itemList) [lsort -$order -index $col \ -$data($col-sortmode) $data(itemList)] } } } # # Update the line numbers (if any) # for {set col 0} {$col < $data(colCount)} {incr col} { if {!$data($col-showlinenumbers)} { continue } set newItemList {} set line 1 foreach item $data(itemList) { set item [lreplace $item $col $col $line] lappend newItemList $item set key [lindex $item end] if {![info exists data($key-hide)]} { incr line } } set data(itemList) $newItemList } # # Replace the contents of the list variable if present # condUpdateListVar $win # # Update anchorRow and activeRow # foreach type {anchor active} { upvar 0 ${type}Key key2 if {[string compare $key2 ""] != 0} { set data(${type}Row) [lsearch $data(itemList) "* $key2"] } } # # Cancel the execution of all delayed redisplay and redisplayCol commands # foreach name [array names data *redispId] { after cancel $data($name) unset data($name) } set canvasWidth $data(arrowWidth) if {[llength $data(arrowColList)] > 1} { incr canvasWidth 6 } foreach col $data(arrowColList) { # # Make sure the arrow will fit into the column # set idx [expr {2*$col}] set pixels [lindex $data(colList) $idx] if {$pixels == 0 && $data($col-maxPixels) > 0 && $data($col-reqPixels) > $data($col-maxPixels) && $data($col-maxPixels) < $canvasWidth} { set data($col-maxPixels) $canvasWidth set data($col-maxwidth) -$canvasWidth } if {$pixels != 0 && $pixels < $canvasWidth} { set data(colList) [lreplace $data(colList) $idx $idx $canvasWidth] set idx [expr {3*$col}] set data(-columns) \ [lreplace $data(-columns) $idx $idx -$canvasWidth] } } # # Adjust the columns; this will also place the # canvas widgets into the corresponding labels # adjustColumns $win allLabels 1 # # Delete the items from the body text widget and insert the sorted ones. # Interestingly, for a large number of items it is much more efficient # to empty each line individually than to invoke a global delete command. # set w $data(body) $w tag remove hiddenRow 1.0 end for {set line 1} {$line <= $data(itemCount)} {incr line} { $w delete $line.0 $line.end } set snipStr $data(-snipstring) set rowTagRefCount $data(rowTagRefCount) set cellTagRefCount $data(cellTagRefCount) set isSimple [expr {$data(imgCount) == 0 && $data(winCount) == 0}] set padY [expr {[$w cget -spacing1] == 0}] set row 0 set line 1 foreach item $data(itemList) { set key [lindex $item end] set dispItem [lrange $item 0 $data(lastCol)] if {$data(hasFmtCmds)} { set dispItem [formatItem $win $key $row $dispItem] } # # Clip the elements if necessary and # insert them with the corresponding tags # if {$rowTagRefCount == 0} { set hasRowFont 0 } else { set hasRowFont [info exists data($key-font)] } set col 0 if {$isSimple} { set insertArgs {} set multilineData {} foreach text [strToDispStr $dispItem] \ colFont $data(colFontList) \ colTags $data(colTagsList) \ {pixels alignment} $data(colList) { if {$data($col-hide) && !$canElide} { incr col continue } # # Build the list of tags to be applied to the cell # if {$hasRowFont} { set cellFont $data($key-font) } else { set cellFont $colFont } set cellTags $colTags if {$cellTagRefCount != 0} { if {[info exists data($key,$col-font)]} { set cellFont $data($key,$col-font) lappend cellTags cell-font-$data($key,$col-font) } foreach opt {-background -foreground} { if {[info exists data($key,$col$opt)]} { lappend cellTags cell$opt-$data($key,$col$opt) } } } # # Clip the element if necessary # set multiline [string match "*\n*" $text] if {$pixels == 0} { ;# convention: dynamic width if {$data($col-maxPixels) > 0} { if {$data($col-reqPixels) > $data($col-maxPixels)} { set pixels $data($col-maxPixels) } } } if {$pixels != 0} { incr pixels $data($col-delta) if {$data($col-wrap) && !$multiline} { if {[font measure $cellFont -displayof $win $text] > $pixels} { set multiline 1 } } set snipSide \ $snipSides($alignment,$data($col-changesnipside)) if {$multiline} { set list [split $text "\n"] if {$data($col-wrap)} { set snipSide "" } set text [joinList $win $list $cellFont \ $pixels $snipSide $snipStr] } else { set text [strRange $win $text $cellFont \ $pixels $snipSide $snipStr] } } if {$multiline} { lappend insertArgs "\t\t" $cellTags lappend multilineData $col $text $colFont $pixels $alignment } else { lappend insertArgs "\t$text\t" $cellTags } incr col } # # Insert the item into the body text widget # if {[llength $insertArgs] != 0} { eval [list $w insert $line.0] $insertArgs } # # Embed the message widgets displaying multiline elements # foreach {col text font pixels alignment} $multilineData { findTabs $win $line $col $col tabIdx1 tabIdx2 set msgScript [list ::tablelist::displayText $win $key \ $col $text $font $pixels $alignment] $w window create $tabIdx2 -pady $padY -create $msgScript } } else { foreach text [strToDispStr $dispItem] \ colFont $data(colFontList) \ colTags $data(colTagsList) \ {pixels alignment} $data(colList) { if {$data($col-hide) && !$canElide} { incr col continue } # # Build the list of tags to be applied to the cell # if {$hasRowFont} { set cellFont $data($key-font) } else { set cellFont $colFont } set cellTags $colTags if {$cellTagRefCount != 0} { if {[info exists data($key,$col-font)]} { set cellFont $data($key,$col-font) lappend cellTags cell-font-$data($key,$col-font) } foreach opt {-background -foreground} { if {[info exists data($key,$col$opt)]} { lappend cellTags cell$opt-$data($key,$col$opt) } } } # # Insert the text and the label or window # (if any) into the body text widget # appendComplexElem $win $key $row $col $text $pixels \ $alignment $snipStr $cellFont $cellTags $line incr col } } if {$rowTagRefCount != 0} { foreach opt {-background -foreground -font} { if {[info exists data($key$opt)]} { $w tag add row$opt-$data($key$opt) $line.0 $line.end } } } if {[info exists data($key-hide)]} { $w tag add hiddenRow $line.0 $line.end+1c } set row $line incr line } # # Invalidate the list of the row indices indicating the non-hidden rows # set data(nonHiddenRowList) {-1} # # Select the cells that were selected before # foreach {key col} $selCells { set row [lsearch $data(itemList) "* $key"] cellSelection $win set $row $col $row $col } # # Disable the body text widget if it was disabled before # if {$data(isDisabled)} { $w tag add disabled 1.0 end $w tag configure select -borderwidth 0 } # # Bring the "most important" row into view # if {$editCol >= 0} { set editRow [lsearch $data(itemList) "* $editKey"] seeRow $win $editRow } else { set selRows [curSelection $win] if {[llength $selRows] == 1} { seeRow $win $selRows } elseif {[string compare [focus -lastfor $w] $w] == 0} { seeRow $win $data(activeRow) } } # # Adjust the elided text and restore the stripes in the body text widget # adjustElidedText $win makeStripes $win # # Restore the edit window if it was present before # if {$editCol >= 0} { doEditCell $win $editRow $editCol 1 } # # Work around a Tk bug on Mac OS X Aqua # variable winSys if {[string compare $winSys "aqua"] == 0} { foreach col $data(arrowColList) { set canvas [list $data(hdrTxtFrCanv)$col] after idle "lower $canvas; raise $canvas" } } return "" } kwwidgets-1.0.0~cvs20100930/Utilities/Tablelist/tablelistBind.tcl0000644000175000017500000023026711070725164024260 0ustar domibeldomibel#============================================================================== # Contains public and private procedures used in tablelist bindings. # # Structure of the module: # - Public helper procedures # - Binding tag Tablelist # - Binding tag TablelistWindow # - Binding tag TablelistBody # - Binding tags TablelistLabel, TablelistSubLabel, and TablelistArrow # # Copyright (c) 2000-2008 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de) #============================================================================== # # Public helper procedures # ======================== # #------------------------------------------------------------------------------ # tablelist::getTablelistPath # # Gets the path name of the tablelist widget from the path name w of one of its # descendants. It is assumed that all of the ancestors of w exist (but w # itself needn't exist). #------------------------------------------------------------------------------ proc tablelist::getTablelistPath w { return [mwutil::getAncestorByClass $w Tablelist] } #------------------------------------------------------------------------------ # tablelist::convEventFields # # Gets the path name of the tablelist widget and the x and y coordinates # relative to the latter from the path name w of one of its descendants and # from the x and y coordinates relative to the latter. #------------------------------------------------------------------------------ proc tablelist::convEventFields {w x y} { return [mwutil::convEventFields $w $x $y Tablelist] } # # Binding tag Tablelist # ===================== # #------------------------------------------------------------------------------ # tablelist::addActiveTag # # This procedure is invoked when the tablelist widget win gains the keyboard # focus. It adds the "active" tag to the line or cell that displays the active # item or element of the widget in its body text child. #------------------------------------------------------------------------------ proc tablelist::addActiveTag win { upvar ::tablelist::ns${win}::data data set line [expr {$data(activeRow) + 1}] set col $data(activeCol) if {[string compare $data(-selecttype) "row"] == 0} { $data(body) tag add active $line.0 $line.end } elseif {$data(itemCount) > 0 && $data(colCount) > 0 && $line > 0 && !$data($col-hide)} { findTabs $win $line $col $col tabIdx1 tabIdx2 $data(body) tag add active $tabIdx1 $tabIdx2+1c } set data(ownsFocus) 1 } #------------------------------------------------------------------------------ # tablelist::removeActiveTag # # This procedure is invoked when the tablelist widget win loses the keyboard # focus. It removes the "active" tag from the body text child of the widget. #------------------------------------------------------------------------------ proc tablelist::removeActiveTag win { upvar ::tablelist::ns${win}::data data $data(body) tag remove active 1.0 end set data(ownsFocus) 0 } #------------------------------------------------------------------------------ # tablelist::cleanup # # This procedure is invoked when the tablelist widget win is destroyed. It # executes some cleanup operations. #------------------------------------------------------------------------------ proc tablelist::cleanup win { # # Cancel the execution of all delayed adjustSeps, # makeStripes, showLineNumbers, stretchColumns, updateColors, # updateScrlColOffset, updateHScrlbar, updateVScrlbar, # adjustElidedText, synchronize, displayItems, horizAutoScan, # doCellConfig, redisplay, and redisplayCol commands # upvar ::tablelist::ns${win}::data data foreach id {sepsId stripesId lineNumsId stretchId colorId offsetId \ hScrlbarId vScrlbarId elidedId syncId dispId afterId reconfigId} { if {[info exists data($id)]} { after cancel $data($id) } } foreach name [array names data *redispId] { after cancel $data($name) } # # If there is a list variable associated with the # widget then remove the trace set on this variable # if {$data(hasListVar) && [info exists $data(-listvariable)]} { upvar #0 $data(-listvariable) var trace vdelete var wu $data(listVarTraceCmd) } # # Destroy any existing bindings for data(bodyTag) and data(editwinTag) # foreach event [bind $data(bodyTag)] { bind $data(bodyTag) $event "" } foreach event [bind $data(editwinTag)] { bind $data(editwinTag) $event "" } namespace delete ::tablelist::ns$win catch {rename ::$win ""} } #------------------------------------------------------------------------------ # tablelist::updateConfigSpecs # # This procedure handles the virtual event <> by updating the # theme-specific default values of some tablelist configuration options. #------------------------------------------------------------------------------ proc tablelist::updateConfigSpecs win { # # This might be an "after idle" callback; check whether the window exists # if {![winfo exists $win]} { return "" } set currentTheme [getCurrentTheme] upvar ::tablelist::ns${win}::data data if {[string compare $currentTheme $data(currentTheme)] == 0} { if {[string compare $currentTheme "tileqt"] == 0} { set widgetStyle [tileqt_currentThemeName] set colorScheme [getKdeConfigVal "KDE" "colorScheme"] if {[string compare $widgetStyle $data(widgetStyle)] == 0 && [string compare $colorScheme $data(colorScheme)] == 0} { return "" } } else { return "" } } # # Populate the array tmp with values corresponding to the old theme # and the array themeDefaults with values corresponding to the new one # array set tmp $data(themeDefaults) setThemeDefaults # # Set those configuration options whose values equal the old # theme-specific defaults to the new theme-specific ones # variable themeDefaults foreach opt {-background -foreground -disabledforeground -stripebackground -selectbackground -selectforeground -selectborderwidth -font -labelbackground -labelforeground -labelfont -labelborderwidth -labelpady -arrowcolor -arrowdisabledcolor -arrowstyle} { if {[string compare $data($opt) $tmp($opt)] == 0} { doConfig $win $opt $themeDefaults($opt) } } foreach opt {-background -foreground} { doConfig $win $opt $data($opt) ;# sets the bg color of the separators } # # Destroy and recreate the edit window if present # if {[set editCol $data(editCol)] >= 0} { set editRow $data(editRow) saveEditData $win destroy $data(bodyFr) doEditCell $win $editRow $editCol 1 } # # Destroy and recreate the embedded windows # if {$data(winCount) != 0} { for {set row 0} {$row < $data(itemCount)} {incr row} { for {set col 0} {$col < $data(colCount)} {incr col} { set key [lindex [lindex $data(itemList) $row] end] if {[info exists data($key,$col-window)]} { set val $data($key,$col-window) doCellConfig $row $col $win -window "" doCellConfig $row $col $win -window $val } } } } set data(currentTheme) $currentTheme set data(themeDefaults) [array get themeDefaults] if {[string compare $currentTheme "tileqt"] == 0} { set data(widgetStyle) [tileqt_currentThemeName] set data(colorScheme) [getKdeConfigVal "KDE" "colorScheme"] } else { set data(widgetStyle) "" set data(colorScheme) "" } } # # Binding tag TablelistWindow # =========================== # #------------------------------------------------------------------------------ # tablelist::cleanupWindow # # This procedure is invoked when a window aux embedded into a tablelist widget # is destroyed. It invokes the cleanup script associated with the cell # containing the window, if any. #------------------------------------------------------------------------------ proc tablelist::cleanupWindow aux { regexp {^(.+)\.body\.f(k[0-9]+),([0-9]+)$} $aux dummy win key col upvar ::tablelist::ns${win}::data data if {[info exists data($key,$col-windowdestroy)]} { set row [lsearch $data(itemList) "* $key"] uplevel #0 $data($key,$col-windowdestroy) [list $win $row $col $aux.w] } } # # Binding tag TablelistBody # ========================= # #------------------------------------------------------------------------------ # tablelist::defineTablelistBody # # Defines the bindings for the binding tag TablelistBody. #------------------------------------------------------------------------------ proc tablelist::defineTablelistBody {} { variable priv array set priv { x "" y "" afterId "" prevRow "" prevCol "" selection {} clicked 0 clickTime 0 clickedInEditWin 0 } foreach event { } { bind TablelistBody $event { foreach {tablelist::W tablelist::x tablelist::y} \ [tablelist::convEventFields %W %x %y] {} tablelist::showOrHideTooltip $tablelist::W \ $tablelist::x $tablelist::y %X %Y } } bind TablelistBody { if {[winfo exists %W]} { foreach {tablelist::W tablelist::x tablelist::y} \ [tablelist::convEventFields %W %x %y] {} set tablelist::priv(x) $tablelist::x set tablelist::priv(y) $tablelist::y set tablelist::priv(row) [$tablelist::W nearest $tablelist::y] set tablelist::priv(col) [$tablelist::W nearestcolumn $tablelist::x] set tablelist::priv(clicked) 1 set tablelist::priv(clickTime) %t set tablelist::priv(clickedInEditWin) 0 if {[$tablelist::W cget -setfocus] && [string compare [$tablelist::W cget -state] "normal"] == 0} { focus [$tablelist::W bodypath] } tablelist::condBeginMove $tablelist::W $tablelist::priv(row) tablelist::beginSelect $tablelist::W \ $tablelist::priv(row) $tablelist::priv(col) } } bind TablelistBody { if {[winfo exists %W]} { foreach {tablelist::W tablelist::x tablelist::y} \ [tablelist::convEventFields %W %x %y] {} set tablelist::priv(x) $tablelist::x set tablelist::priv(y) $tablelist::y set tablelist::priv(row) [$tablelist::W nearest $tablelist::y] set tablelist::priv(col) [$tablelist::W nearestcolumn $tablelist::x] set tablelist::priv(clicked) 1 set tablelist::priv(clickTime) %t set tablelist::priv(clickedInEditWin) 0 if {[$tablelist::W cget -setfocus] && [string compare [$tablelist::W cget -state] "normal"] == 0} { focus [$tablelist::W bodypath] } tablelist::condEditContainingCell $tablelist::W \ $tablelist::x $tablelist::y } } bind TablelistBody { if {$tablelist::priv(clicked) && %t - $tablelist::priv(clickTime) < 300} { continue } foreach {tablelist::W tablelist::x tablelist::y} \ [tablelist::convEventFields %W %x %y] {} if {[string compare $tablelist::priv(x) ""] == 0 || [string compare $tablelist::priv(y) ""] == 0} { set tablelist::priv(x) $tablelist::x set tablelist::priv(y) $tablelist::y } set tablelist::priv(prevX) $tablelist::priv(x) set tablelist::priv(prevY) $tablelist::priv(y) set tablelist::priv(x) $tablelist::x set tablelist::priv(y) $tablelist::y tablelist::condAutoScan $tablelist::W tablelist::motion $tablelist::W \ [$tablelist::W nearest $tablelist::y] \ [$tablelist::W nearestcolumn $tablelist::x] tablelist::condShowTarget $tablelist::W $tablelist::y } bind TablelistBody { foreach {tablelist::W tablelist::x tablelist::y} \ [tablelist::convEventFields %W %x %y] {} set tablelist::priv(x) "" set tablelist::priv(y) "" set tablelist::priv(clicked) 0 after cancel $tablelist::priv(afterId) set tablelist::priv(afterId) "" set tablelist::priv(releasedInEditWin) 0 if {$tablelist::priv(clicked) && %t - $tablelist::priv(clickTime) < 300} { tablelist::moveOrActivate $tablelist::W \ $tablelist::priv(row) $tablelist::priv(col) } else { tablelist::moveOrActivate $tablelist::W \ [$tablelist::W nearest $tablelist::y] \ [$tablelist::W nearestcolumn $tablelist::x] } tablelist::condEvalInvokeCmd $tablelist::W } bind TablelistBody { foreach {tablelist::W tablelist::x tablelist::y} \ [tablelist::convEventFields %W %x %y] {} tablelist::beginExtend $tablelist::W \ [$tablelist::W nearest $tablelist::y] \ [$tablelist::W nearestcolumn $tablelist::x] } bind TablelistBody { foreach {tablelist::W tablelist::x tablelist::y} \ [tablelist::convEventFields %W %x %y] {} tablelist::beginToggle $tablelist::W \ [$tablelist::W nearest $tablelist::y] \ [$tablelist::W nearestcolumn $tablelist::x] } bind TablelistBody { tablelist::condEditActiveCell [tablelist::getTablelistPath %W] } bind TablelistBody { tablelist::condEditActiveCell [tablelist::getTablelistPath %W] } bind TablelistBody { tablelist::nextPrevCell [tablelist::getTablelistPath %W] 1 } bind TablelistBody { tablelist::nextPrevCell [tablelist::getTablelistPath %W] -1 } bind TablelistBody <> { tablelist::nextPrevCell [tablelist::getTablelistPath %W] -1 } bind TablelistBody { tablelist::upDown [tablelist::getTablelistPath %W] -1 } bind TablelistBody { tablelist::upDown [tablelist::getTablelistPath %W] 1 } bind TablelistBody { tablelist::leftRight [tablelist::getTablelistPath %W] -1 } bind TablelistBody { tablelist::leftRight [tablelist::getTablelistPath %W] 1 } bind TablelistBody { tablelist::priorNext [tablelist::getTablelistPath %W] -1 } bind TablelistBody { tablelist::priorNext [tablelist::getTablelistPath %W] 1 } bind TablelistBody { tablelist::homeEnd [tablelist::getTablelistPath %W] Home } bind TablelistBody { tablelist::homeEnd [tablelist::getTablelistPath %W] End } bind TablelistBody { tablelist::firstLast [tablelist::getTablelistPath %W] first } bind TablelistBody { tablelist::firstLast [tablelist::getTablelistPath %W] last } bind TablelistBody { tablelist::extendUpDown [tablelist::getTablelistPath %W] -1 } bind TablelistBody { tablelist::extendUpDown [tablelist::getTablelistPath %W] 1 } bind TablelistBody { tablelist::extendLeftRight [tablelist::getTablelistPath %W] -1 } bind TablelistBody { tablelist::extendLeftRight [tablelist::getTablelistPath %W] 1 } bind TablelistBody { tablelist::extendToHomeEnd [tablelist::getTablelistPath %W] Home } bind TablelistBody { tablelist::extendToHomeEnd [tablelist::getTablelistPath %W] End } bind TablelistBody { tablelist::extendToFirstLast [tablelist::getTablelistPath %W] first } bind TablelistBody { tablelist::extendToFirstLast [tablelist::getTablelistPath %W] last } bind TablelistBody { set tablelist::W [tablelist::getTablelistPath %W] tablelist::beginSelect $tablelist::W \ [$tablelist::W index active] [$tablelist::W columnindex active] } bind TablelistBody