Browse Source

Merge pull request #1630 from JimMarlowe/JM-MULTI_LIST

Add Multicolumn List Widget
JoshEngebretson 8 years ago
parent
commit
2c5e7a5d7d

+ 1 - 1
Script/Packages/Atomic/UI.json

@@ -11,7 +11,7 @@
 								"UIContainer", "UISection", "UIInlineSelect", "UITextureWidget", "UIColorWidget", "UIColorWheel",
 								"UIScrollContainer", "UISeparator", "UIDimmer", "UISelectDropdown", "UISlider", "UIBargraph",
 								"UIPromptWindow", "UIFinderWindow", "UIPulldownMenu", "UIRadioButton", "UIScrollBar", "UIDockWindow",
-								"UIButtonGrid"],
+								"UIButtonGrid", "UIMultiItem", "UIMultiItemSource" ],
 	"overloads" : {
 	},
 	"typescript_decl" : {

+ 160 - 0
Source/Atomic/UI/UIMultiItem.cpp

@@ -0,0 +1,160 @@
+//
+// Copyright (c) 2014-2017, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "UIMultiItem.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UIMultiItem::UIMultiItem(Context* context, const String &colid, const String &widgettype, const String &str, int colwidth, int colheight )
+ : UISelectItem(context, str, colid)
+{
+    SetID(colid);
+    AddColumn ( widgettype, str, colwidth );
+    colHeight_ = colheight; 
+}
+
+UIMultiItem::~UIMultiItem()
+{
+}
+
+void UIMultiItem::SetID(const String& id)
+{
+    id_ = TBID(id.CString());
+}
+
+void UIMultiItem::AddColumn ( const String& widgettype, const String& str, int cwidth ) 
+{
+    colStr_.Push(str);
+    colWidget_.Push(widgettype);
+    colWidth_.Push(cwidth);
+}
+
+const String& UIMultiItem::GetColumnStr( int col )
+{
+    if ( col > -1 )
+        return colStr_[col];
+    return ( String::EMPTY );
+}
+
+const String& UIMultiItem::GetColumnWidget( int col ) 
+{
+    if ( col > -1 )
+    return colWidget_[col];
+    return ( String::EMPTY );
+}
+
+int UIMultiItem::GetColumnWidth( int col ) 
+{
+    if ( col > -1 )
+        return colWidth_[col];
+    return 0;
+}
+
+int UIMultiItem::GetNumColumns()
+{
+    return colStr_.Size();
+}
+
+tb::MultiItem* UIMultiItem::GetTBItem()
+{
+    tb::MultiItem* item = NULL;
+
+    int col = 0;
+    int numcols = GetNumColumns();
+    String strx = GetColumnStr(col);
+    String widx = GetColumnWidget(col);
+    int wix = GetColumnWidth(col);
+    item = new tb::MultiItem(id_, widx.CString(), strx.CString(), wix, colHeight_ );
+    for ( col = 1; col<numcols; col++)
+    {
+        strx = GetColumnStr(col);
+        widx = GetColumnWidget(col);
+        wix = GetColumnWidth(col);
+        item->AddColumn( widx.CString(), strx.CString(), wix );
+    }
+    return item;
+}
+
+// UIMultiItemSource 
+
+UIMultiItemSource::UIMultiItemSource(Context* context) :  UISelectItemSource(context)
+{
+
+}
+
+UIMultiItemSource::~UIMultiItemSource()
+{
+
+}
+
+void UIMultiItemSource::RemoveItemWithId(const String& id)
+{
+    tb::TBID test = TBID(id.CString());
+    for (List<SharedPtr<UIMultiItem> >::Iterator itr = items_.Begin(); itr != items_.End(); itr++)
+    {
+        if ((*itr)->GetID() == test) {
+            items_.Erase(itr);
+            break;
+        }
+    }
+}
+
+void UIMultiItemSource::RemoveItemWithStr(const String& str)
+{
+    for (List<SharedPtr<UIMultiItem> >::Iterator itr = items_.Begin(); itr != items_.End(); itr++)
+    {
+        if ((*itr)->GetColumnStr(0) == str) {
+            items_.Erase(itr);
+            break;
+        }
+    }
+}
+
+const String& UIMultiItemSource::GetItemStr(int index)
+{
+    int nn = 0;
+    for (List<SharedPtr<UIMultiItem> >::Iterator itr = items_.Begin(); itr != items_.End(); itr++)
+    {
+        if ( nn == index) return (*itr)->GetColumnStr(0);
+        nn++;
+    }
+    return ( String::EMPTY );
+}
+
+MultiItemSource *UIMultiItemSource::GetTBItemSource()
+{
+    // caller's responsibility to clean up
+    MultiItemSource* src = new MultiItemSource();
+
+    for (List<SharedPtr<UIMultiItem> >::Iterator itr = items_.Begin(); itr != items_.End(); itr++)
+    {
+        tb::MultiItem* tbitem = (*itr)->GetTBItem();
+        src->AddItem(tbitem);
+    }
+
+    return src;
+}
+
+}

+ 97 - 0
Source/Atomic/UI/UIMultiItem.h

@@ -0,0 +1,97 @@
+//
+// Copyright (c) 2014-2017, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include <TurboBadger/tb_widgets.h>
+#include <TurboBadger/tb_select_item.h>
+#include <TurboBadger/tb_atomic_widgets.h>
+
+#include "../Core/Object.h"
+#include "../Container/List.h"
+#include "../IO/Log.h"
+
+#include "UISelectItem.h"
+
+namespace Atomic
+{
+
+class UIMultiItemSource;
+
+class ATOMIC_API UIMultiItem : public  UISelectItem
+{
+    ATOMIC_OBJECT(UIMultiItem, UISelectItem )
+
+public:
+
+    UIMultiItem(Context* context, const String& colid,const String& widgettype, const String& str, int colwidth, int colheight );
+    virtual ~UIMultiItem();
+
+    void SetID(const String& id);
+    tb::TBID GetID() { return id_; }
+
+    void AddColumn ( const String& widgettype, const String& str, int colwidth );
+    const String& GetColumnStr( int col );
+    const String& GetColumnWidget( int col );
+    int GetColumnWidth( int col );
+    int GetNumColumns();
+
+    virtual tb::MultiItem * GetTBItem();
+
+protected:
+
+    tb::TBID id_;    // TBID
+    Vector <String> colStr_;
+    Vector <String> colWidget_; 
+    Vector <int>  colWidth_;
+    int colHeight_; 
+};
+
+class ATOMIC_API UIMultiItemSource : public UISelectItemSource
+{
+    ATOMIC_OBJECT(UIMultiItemSource, UISelectItemSource )
+
+public:
+
+    UIMultiItemSource(Context* context);
+    virtual ~UIMultiItemSource();
+
+    void AddItem(UIMultiItem* item) { items_.Push(SharedPtr<UIMultiItem>(item)); }
+    void RemoveItemWithId(const String& id);
+    void RemoveItemWithStr(const String& str);
+    int GetItemCount() { return items_.Size(); }
+
+    void Clear() { items_.Clear(); }
+
+    /// Returns item string for the index. Returns empty string for invalid indexes.
+    const String& GetItemStr(int index);
+
+    // caller's responsibility to clean up
+    virtual tb::MultiItemSource* GetTBItemSource();
+
+protected:
+
+    List<SharedPtr<UIMultiItem>> items_;
+
+};
+
+}

+ 165 - 0
Source/ThirdParty/TurboBadger/tb_atomic_widgets.cpp

@@ -33,6 +33,7 @@
 #include "tb_menu_window.h"
 #include "tb_select.h"
 #include "tb_tab_container.h"
+#include "image/tb_image_widget.h"
 
 #include <math.h>
 
@@ -929,4 +930,168 @@ void TBDockWindow::OnResized(int old_w, int old_h)
 }
 
 
+// == MultiList Support  ==========================================
+
+
+void MultiItem::AddColumn (TBStr widgettype, TBStr string, int width )
+{
+    TBValue *new_str = colStr_.GetArray()->AddValue();
+    new_str->SetString(string.CStr(), TBValue::SET_NEW_COPY );
+    TBValue *new_widget = colWidget_.GetArray()->AddValue();
+    new_widget->SetString( widgettype.CStr(), TBValue::SET_NEW_COPY );
+    TBValue *new_width = colWidth_.GetArray()->AddValue();
+    new_width->SetInt(width); 
+}
+
+const char* MultiItem::GetColumnStr( int col ) 
+{
+    const char* strx = colStr_.GetArray()->GetValue(col)->GetString();
+    return strx;
+}
+
+const char* MultiItem::GetColumnWidget( int col )
+{
+    const char* strx = colWidget_.GetArray()->GetValue(col)->GetString();
+    return strx;
+}
+
+int MultiItem::GetColumnWidth( int col )
+{
+   return colWidth_.GetArray()->GetValue(col)->GetInt();
+}
+
+int MultiItem::GetColumnHeight()
+{
+   return colHeight_;
+}
+
+int MultiItem::GetNumColumns()
+{
+    return colStr_.GetArrayLength();
+}
+
+
+bool MultiItemSource::Filter(int index, const char *filter)
+{
+    // Override this method so we can return hits for our extra data too.
+
+    if (TBSelectItemSource::Filter(index, filter))
+        return true;
+
+    // do this on ALL of the columns?
+    return false;
+}
+
+TBWidget *MultiItemSource::CreateItemWidget(int index, TBSelectItemViewer *viewer)
+{
+    if (TBLayout *layout = new MultiItemWidget( GetItem(index), this, viewer, index))
+        return layout;
+    return NULL;
+}
+
+MultiItemWidget::MultiItemWidget(MultiItem *item, MultiItemSource *source, TBSelectItemViewer *source_viewer, int index)
+{
+    SetSkinBg(TBIDC("TBSelectItem"));
+    SetLayoutDistribution(LAYOUT_DISTRIBUTION_GRAVITY);
+    SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP);
+    SetPaintOverflowFadeout(false);
+
+    if (item) // unpack the MultiItem recipe.
+    {
+        int col = 0;
+        int numcols = item->GetNumColumns();
+        int prefheight = item->GetColumnHeight();
+        for ( col = 0; col < numcols; col++ )
+        {
+            TBStr widget;
+            const char *widgetx = item->GetColumnWidget(col); // what are we making?
+            if (widgetx) widget = TBStr(widgetx); // lets not deal with char *s
+            if ( widget.Equals("TEXTC") )  // TextField center justified text
+            {
+                TBTextField *tfc = new TBTextField();
+                tfc->SetTextAlign(TB_TEXT_ALIGN::TB_TEXT_ALIGN_CENTER);
+                tfc->SetSqueezable(true);
+                tfc->SetIgnoreInput(true);
+                tfc->SetText( item->GetColumnStr(col));
+                LayoutParams *lpx = new LayoutParams();
+                lpx->SetWidth(item->GetColumnWidth(col));
+                if ( prefheight > 0) lpx->SetHeight( prefheight);
+                tfc->SetLayoutParams(*lpx);
+                AddChild (tfc);
+            }
+            else if ( widget.Equals("TEXTR") )  // TextField right justified text
+            {
+                TBTextField *tfr = new TBTextField();
+                tfr->SetTextAlign(TB_TEXT_ALIGN::TB_TEXT_ALIGN_RIGHT);
+                tfr->SetSqueezable(true);
+                tfr->SetIgnoreInput(true);
+                tfr->SetText( item->GetColumnStr(col));
+                LayoutParams *lpx = new LayoutParams();
+                lpx->SetWidth(item->GetColumnWidth(col));
+                if ( prefheight > 0) lpx->SetHeight( prefheight);
+                tfr->SetLayoutParams(*lpx);
+                AddChild (tfr);
+            }
+            else if ( widget.Equals("IMAGE") )  // ImageWidget + filename
+            {
+                TBImageWidget *ti = new TBImageWidget();
+                ti->SetImage(item->GetColumnStr(col));
+                ti->SetIgnoreInput(true);
+                LayoutParams *lpx = new LayoutParams();
+                lpx->SetWidth(item->GetColumnWidth(col));
+                if ( prefheight > 0) lpx->SetHeight( prefheight);
+                ti->SetLayoutParams(*lpx);
+                AddChild (ti);
+            }
+            else if ( widget.Equals("COLOR") )  // ColorWidget
+            {
+                TBColorWidget *cw = new TBColorWidget();
+                cw->SetColor(item->GetColumnStr(col));
+                cw->SetIgnoreInput(true);
+                cw->SetGravity(WIDGET_GRAVITY_ALL);
+                LayoutParams *lpx = new LayoutParams();
+                lpx->SetWidth(item->GetColumnWidth(col));
+                if ( prefheight > 0) lpx->SetHeight( prefheight);
+                cw->SetLayoutParams(*lpx);
+                AddChild(cw);
+            }
+            else if ( widget.Equals("ICON") )   // SkinImage + skinname
+            {
+                const char *skin = item->GetColumnStr(col);
+                if (skin)
+                {
+                    TBID skinn = TBID(skin);
+                    TBSkinImage *si = new TBSkinImage(skinn);
+                    si->SetIgnoreInput(true);
+                    LayoutParams *lpx = new LayoutParams();
+                    lpx->SetWidth(item->GetColumnWidth(col));
+                    if (prefheight > 0) lpx->SetHeight(prefheight);
+                    si->SetLayoutParams(*lpx);
+                    AddChild (si);
+                }
+            }
+            else // the default is TextField, left justified text
+            {
+                TBTextField *tfl = new TBTextField();
+                tfl->SetTextAlign(TB_TEXT_ALIGN::TB_TEXT_ALIGN_LEFT);
+                tfl->SetSqueezable(true);
+                tfl->SetIgnoreInput(true);
+                tfl->SetText( item->GetColumnStr(col));
+                LayoutParams *lpx = new LayoutParams();
+                lpx->SetWidth(item->GetColumnWidth(col));
+                if ( prefheight > 0) lpx->SetHeight(prefheight);
+                tfl->SetLayoutParams(*lpx);
+                AddChild (tfl);
+            }
+        }
+    }
+}
+
+bool MultiItemWidget::OnEvent(const TBWidgetEvent &ev)
+{
+    // if there are active widgets (buttons, checkbox) handle the events here
+    return TBLayout::OnEvent(ev);
+}
+
+
 }; // namespace tb

+ 57 - 0
Source/ThirdParty/TurboBadger/tb_atomic_widgets.h

@@ -297,6 +297,63 @@ protected:
 
 };
 
+/// == MultiList Support  ==========================================
+
+/** MultiItem adds extra info to a string item. */
+class MultiItem : public TBGenericStringItem
+{
+public:
+    MultiItem(const TBID &colid, TBStr widgettype0, TBStr str0, int width0, int colheight=0 )
+        : TBGenericStringItem(str0, colid),
+        colStr_(TBValue::TYPE_ARRAY),
+        colWidget_(TBValue::TYPE_ARRAY),
+        colWidth_(TBValue::TYPE_ARRAY),
+        colHeight_(colheight)
+        {
+            colStr_.SetArray(new tb::TBValueArray(), TBValue::SET_AS_STATIC);
+            colWidget_.SetArray(new tb::TBValueArray(), TBValue::SET_AS_STATIC);
+            colWidth_.SetArray(new tb::TBValueArray(), TBValue::SET_AS_STATIC);
+            
+            AddColumn ( widgettype0, str0, width0);
+        }
+
+    void AddColumn ( TBStr string, TBStr widgettype, int width );
+    const char* GetColumnStr( int col );
+    const char* GetColumnWidget( int col );
+    int GetColumnWidth( int col );
+    int GetColumnHeight();
+    int GetNumColumns();
+
+private:
+    TBValue colStr_;
+    TBValue colWidget_; 
+    TBValue colWidth_;
+    int colHeight_; 
+};
+
+
+/** MultiItemSource provides items of type MultiItem and makes sure
+    the viewer is populated with the customized widget for each item. */
+class MultiItemSource : public TBSelectItemSourceList<MultiItem>
+{
+public:
+    virtual bool Filter(int index, const char *filter);
+    virtual TBWidget *CreateItemWidget(int index, TBSelectItemViewer *viewer);
+};
+
+/** MultiItemWidget is the widget representing a MultiItem.
+    On changes to the item, it calls InvokeItemChanged on the source, so that all
+    viewers of the source are updated to reflect the change. */
+class MultiItemWidget : public TBLayout
+{
+public:
+    MultiItemWidget(MultiItem *item, MultiItemSource *source, TBSelectItemViewer *source_viewer, int index);
+    virtual bool OnEvent(const TBWidgetEvent &ev);
+private:
+    MultiItemSource *m_source;
+    TBSelectItemViewer *m_source_viewer;
+    int m_index;
+};
 
 }; // namespace tb