TabbedView  an array of CompositeViews (or ScrollViews) with tabs for switching 


by Jost Muxfeldt,   Oct 09, 2012 version 1.29

Change history at bottom.

  

Class Methods


*new(parent,bounds,labels,colors,name,scroll) returns a TabbedView object

  parent a parent view. if nil, then a new window is created

  bounds Rect .  if nil then the parent Rect is used

  labels an array of strings. determines how many tabs there are. default ["tab1", "tab2", "tab3"]

  colors an array of colors. if the array is smaller than the amount of labels, the color series repeats.

For convenience, a color scheme is automatically created using these colors. 

You cannot use gradients here, because the tabs are drawn with Pen.

Gradients only work with background_;

Custom color schemes and shapes can be controlled with instance variables

or with the *new variations below.

  name a name for the window if a new window is created (view==nil) -- default " "

  scroll boolean defaults to false. It substitutes the CompositeView with a ScrollView.

 Convenience method variations on *new for quick styling :

 

*newBasic

*newColor

*newColorLabels

*newFlat

*newTall

*newTransparent

*newPacked

     

   

Methods/Variables:


  view  returns the container for all the views

  views  returns  an array of Composite/Scroll Views


  add ( label )  string adds a tab with label ; returns the Composite/Scroll View

  insert ( index , label )  int, string inserts a tab  at index with label string ; returns the Composite/Scroll View

  removeAt( index )  int remove tab at Index.

   

  focus ( index )  int selects one of the tabs

  activeTab   returns the index of  the focused tab 

   

  focusActions_(array)    an Array  of user onFocus functions.

  unfocusActions_ (array)  an Array of user onUnfocus functions.

   

  tabPosition_ ( symbol )  \left, \top, \right, or \bottom.

  followEdges_ ( bool )  default true. Set tabs parallel or perpendicular to container edges.

  resize_ ( val )  int sets the resize flag (1-9 ).   default 1. ;

   

  labelColors_ ( colorarray ) Array of Colors for the tabs.

  unfocusedColors_ (colorarray ) Array of  Colors for the unfocused tabs

  focusFrameColor_(color ) Color of the focus frame of the tabs. Cocoa only.

  unfocusTabs_(boolean ) Unfocuses the UserView which draws the tabs after a tab is clicked. 

  Defaut on Cocoa is false, otherwise true. (because Swing can't hide focus frames);

 

  backgrounds_ (colorarray ) Array of Colors for the CompositeViews 

  stringColor_ ( color ) a Color

  stringFocusedColor_ ( col ) a Color

   

  labelPadding_ ( int )   if autosizing is on, then this determines left and right padding from th label text

  tabWidth_ (int )  int or  \auto ;  a fixed tab width, or "auto" for automatic tab width (default "auto", unless using themes)

  tabHeight_ ( int )  int or  \auto ;  a fixed tab height, or "auto" for automatic tab height (default "auto", unless using themes)

  tabCurve_ ( int )   ; the radius in pixels of the rounded tab corners

   

  swingFactor_( point )  Point ;  a multiplication factor for a string/tab width for GUI.swing only. default Point(0.52146,1.25)

   

Usage:


use CompositeView style GUI


(

t=TabbedView(name:"** this is a mock preferences pane **");


ActionButton(t.views[0],"go to next tab ",{t.focus(1)}).bounds_(Rect(50,50,200,100));

)


use FlowView style GUI


(

t=TabbedView(); // use Flow Style


t.views[0].flow({|w| 

GUI.button.new(w,Rect(50,50,250,50))

.states_([["control the tab with method 'focus' -->"]]).action_({t.focus(1)})

});

t.views[1].flow({|w| 

GUI.button.new(w,Rect(50,50,200,100))

.states_([["go to last tab"]]).action_({t.focus(2)})

});

)




quick styling with variations on  *new:

(There are some color differences for swing)


TabbedView.newBasic


TabbedView.newColor


TabbedView.newColorLabels


TabbedView.newFlat


TabbedView.newTall


TabbedView.newTransparent


TabbedView.newPacked(nil,nil,Array.fill(20,{|i| i.asString})); //very good for tons of tabs :



set tabPosition and followEdges:

live switching adjusts positions of contents if you use  .flow  .



(

v=TabbedView.newColorLabels(nil,nil,Array.fill(5,{arg i; var q="aa"; i.do{q=q++"a"}; q })); //default

v.views[0].flow({arg w;

ActionButton(w,"tabs top",{v.tabPosition_(\top)},300,50);

w.startRow;

ActionButton(w,"tabs left",{v.tabPosition_(\left)},148,50);

ActionButton(w,"tabs right",{v.tabPosition_(\right)},148,50);

w.startRow;

ActionButton(w,"tabs bottom",{v.tabPosition_(\bottom)},300,50);

GUI.button.new(w,300@50)

.states_([["set followEdges=false",Color.black,Color.red.alpha_(0.2)],

["set followEdges=true",Color.black,Color.green.alpha_(0.2)]])

.action_({arg b;(b.value==1).if{v.followEdges_(false)}{v.followEdges_(true)};});

});


)


TabbedView.newColorLabels(nil,nil,Array.fill(25,{|i| "tab"++i.asString})).tabPosition_(\right).followEdges_(false);


TabbedView.newTall(nil,nil,Array.fill(5,{|i| "tab"++i.asString})).tabPosition_(\left);


TabbedView.newTall(nil,Rect(100,500,400,100),Array.fill(5,{|i| "tab"++i.asString})).tabPosition_(\bottom);



Drag objects from one tab to another (under cocoa and qt only at the moment):


(

v=TabbedView.newColorLabels;

n = GUI.dragSource.new(v.views[0], Rect(50, 50, 140, 24));

n.object = "Drag me to Tab2";

 GUI.textView.new (v.views[1], Rect(50, 50, 140, 80));

)


add, removeAt, insert  tabs


defaults on *new, but other thems use fixedwidths:


v=TabbedView.newColor


v.add("I am last")


v.insert(2,"squeeze me in")


v.removeAt(2)


resize_()


( 

w=GUI.window.new.front;

v=TabbedView.newColorLabels(w,Rect(40,40,280,280),Array.fill(12,{|i| "tab"++i.asString})).tabPosition_(\right).followEdges_(false);

v.resize_(5);

GUI.slider.new(v.views[0],Rect(10,80,200,30)).resize_(2);

) 


nest TabbedViews & use scrolling


uses  scroll:true in the inner tab


(

v=TabbedView.newPacked(nil,Rect(200,200,600,400).insetBy(20,20),["1","2","3"])

.tabHeight_(40).tabPosition_(\right).followEdges_(false);


q=TabbedView.newColorLabels(v.views[0],nil,["tab1.1","tab1.2","tab1.3"], scroll: true)

.tabPosition_(\right).resize_(5).followEdges_(false);

q.views[0].flow({ arg w;

78.do({ arg i;

b = Button(w, Rect(rrand(20,300),rrand(20,300), 75, 24));

b.states = [["Start "++i, Color.black, Color.rand],

["Stop "++i, Color.white, Color.red]];

});

});

GUI.slider.new(q.views[1],q.views[1].bounds.insetBy(50,50));

)




user functions:   focus and unfocus


 turn on/off scopes , e.g. 

     

( 

v=TabbedView.new();

v.focusActions[1]={"tab2 is focused".postln};

v.unfocusActions[1]={"tab2 just unfocused".postln};

)


focusFrameColor_(color) and unfocusTabs_(bool)

The tabs are drawn with user view which have a clear focus frame on Cocoa. On Swing, the frame cannot be made clear, so by default the tabs are unfocused after clicking. You can change this if it interferes with your tabbing scheme.

     

( 

v=TabbedView.new();


v.unfocusTabs_(false);  // default is false on Cocoa, true otherwise;

v.focusFrameColor_(Color.red); //cocoa only


)



default autosizing tabs


defaults to auto on *new, but other themes use fixedwidths:


(

TabbedView.new(nil,Rect(150,100,400,500),["1","two","threeeeeeeeeeee","four","5"]); 

)


(

v=TabbedView.newFlat(nil,Rect(150,100,400,300),["1","two","threeeeeeeeeee","four","5"]); 

v.tabWidth_(\auto);

)



fixed tab sizes


(

TabbedView(nil,nil,["1","two","three","four","5"]).tabWidth_(70);  

)


set font 


Swing fonts only work within certain limits for now. use swingFactor_   to adjust the conversion.


(

v=TabbedView.newBasic.font_(GUI.font.new("Monaco",9)).tabHeight_(18);


)

(

v=TabbedView.newBasic.font_(GUI.font.new("Monaco",36));


)


(

v=TabbedView.newBasic.font_(GUI.font.new("Helvetica",14)).tabHeight_(\auto);


)


(

v=TabbedView.newTall.font_(GUI.font.new("Helvetica",18)).tabPosition_(\left);


)

(

v=TabbedView.newTall.font_(GUI.font.new("Helvetica",36)).tabHeight_(\auto).tabWidth_(\auto);


)



set colors with an argument to .new


Colors can wrap around if there are less than there are labels.

   Unfocused colors are calculated automatically.

   

(

v=TabbedView(nil,nil,Array.fill(8,{|i| i.asString}),

[Color.rand,Color.rand,Color.rand]);

//Colors can wrap around 

)



set colors very specifically to your own taste using set methods


 

(

v=TabbedView.new(nil,nil,["one","two","three"]); 

//Colors can wrap around 

v.labelColors_([Color.rand,Color.rand,Color.rand]);

)


(

v=TabbedView.new(nil,nil,["one","two","three"]); 

v.labelColors_([Color.red,Color.blue,Color.yellow]);

v.unfocusedColors_([Color.red.alpha_(0.1),Color.blue.alpha_(0.1),Color.yellow.alpha_(0.1)]);

v.backgrounds_([Color.red.alpha_(0.1),Color.blue.alpha_(0.1),Color.yellow.alpha_(0.1)]);

)



adjust padding and curves for small autowidth


labelPadding  only has an effect on autowidth


(

v=TabbedView(nil,nil,Array.fill(20,{|i| i.asString}));

v.labelPadding_(8);  //tighter padding

v.tabCurve_(3);   //sharper curves

v.stringColor_(Color.black);

v.backgrounds_([Color.white.alpha_(0.3)]);

)


or simply use *newPacked:


(

v=TabbedView.newPacked(nil,nil,Array.fill(20,{|i| i.asString}));

)


adjust tab height and curves


super flat and elegant


(

v=TabbedView(nil,nil,["1","two","three","four","5"]).tabWidth_(70).tabHeight_(13).tabCurve_(3); 

)


super tall and clear


(

TabbedView(nil,nil,["1","two","three","four","5"]).tabWidth_(70).tabHeight_(30).tabCurve_(3); 

)




Change History:

Aug 27, 2007 :  code optimized; instanceVar tabPosition. Version 1.0;

Aug 24, 2007 :  small code optimizations Version 1.01;

Aug 23, 2007 :  fixed small bug when bounds=nil  Version 1.02;

Aug 30, 2007 :  added scroll option. Convenience new methods can now  take arguments of form arg:value  Version 1.03;

Sep   2, 2007 :  FlowView contents will now reposition in real time if tab  position is changed. tabPosition getter. Version 1.04;

Tabs can switch during drags(cocoa only); 

Feb 12, 2008 :  relativeOrigin variable added to adjust to new SCCompositeView behavior. Swing compatibility. Version 1.10;


Feb 16, 2008 :  Version 1.11;  Swing themes adjusted to use no transparency.  

deprecated: newRGB and newRGBLabels ;

use new methods: newColor and newColorLabels instead.

swingFactor defaults to 7 (integers work better than floats,

Feb 19, 2008 :  Version 1.12;  

focus_() deprecated;   use  focus(index) instead. 

focused added.

Feb 19, 2008 :  Version 1.13;  

focused removed and changed to activeTab.

All variables that had a double s in "focussed", changed to singel s;

Feb 20, 2008 :  Version 1.14;  Fixed returned tab on add and insert methods  


Feb 20, 2008 :  Version 1.15;  added font variable. other bug fixes  


Feb  26, 2008 :  Version 1.20;  added followEdges option.  

July 09, 2008 :    Version 1.21;  updates for SC3.21 

Dec 15, 2008 :  Version 1.22;   changed  swing font calculation 

Dec 19, 2008 :  Version 1.23;   changed  swing font calculation

Jan  28, 2008 :  Version 1.24;   fixed loop bug (thanks Fredrik Olofsson) . relativeOrigin deprecated (always use r/o)

Jun  11, 2009 :  Version 1.25;   removed all calls to relativeOrigin. focusFrameColor_(color) and unfocusTabs_(bool).  

arg w changed to parent

July 15, 2009: Version 1.26; GUI context change  bug fixed (thanks to sciss).  Font calculations put in an AppClock.

July 26, 2009: Version 1.27; removed AppClock and returned to factored font calculation for swing. AppClock causes 

flow layout problems

Aug 01, 2009: Version 1.28;  small fix to Help file

Oct 09, 2012: Version 1.29; Removed deprecated methods. QT support. SCDoc Support.