About Monkey 2 › Forums › Monkey 2 Development › mojox – experimental widget
Tagged: mojox, progress bar
This topic contains 2 replies, has 2 voices, and was last updated by 
 degac 2 years, 8 months ago.
- 
		AuthorPosts
 - 
		
			
				
August 21, 2016 at 8:58 am #3319
Ok, this is my first attempt to create a ‘new’ widget in mojox. Probably (…sure!) there are dozens of way to make it better, but even if the code is BAD and UGLY (I know :P) I post here – maybe someone else could be inspired!
the widget is a ‘real’ progress bar… I suppose I don’t need to explain!
On my system I hacked/added to mojox folder my ‘class’ PBar and changed mojox.monkey2 to import this one.
The ‘base’ is the Label.monkey2 class – there are many other things not needed (icon & text informations etc) – and events are not implemented (I’m still thinking if this widget should or not be interactive with the user)
I still have no clear how to ‘render well’ a widget – it seems to depend on View & Style class, I have no intention to ‘break’ too much!
BPar class
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159Namespace mojox#rem monkeydoc The PBar class.#endClass PBar Extends View#rem monkeydoc Invoked when the label is clicked.#endField Clicked:Void()#rem monkeydoc Invoked when the label is right clicked.#endField RightClicked:Void()#rem monkeydoc Invoked when the label is double clicked.#endField DoubleClicked:Void()#rem monkeydoc Creates a new label.#endMethod New( value:Float=0.0)Style=GetStyle( "Button" )_value=valueLayout="fill-x"Gravity=New Vec2f( 0,.5 )EndMethod Update:Void(v:Float=0.0)_value=vIf _value<0 _value=0If _value>1 _value=1RequestRender()End#rem monkeydoc Adds a view to the right of the label.#endMethod AddView( view:View )AddChildView( view )_views.Push( view )End#rem monkeydoc Removes a view from the label.#endMethod RemoveView( view:View )RemoveChildView( view )_views.Remove( view )EndProtectedMethod OnMeasure:Vec2i() Override_viewsSize=New Vec2i( 0,0 )Local w:=0,h:=0w=100h=20For Local view:=Eachin _views_viewsSize.x+=view.LayoutSize.x_viewsSize.y=Max( _viewsSize.y,view.LayoutSize.y )Nextw+=_viewsSize.xh=Max( h,_viewsSize.y )Return New Vec2i( w,h )EndMethod OnLayout() OverrideLocal iy:=(Height-_iconSize.y)/2_iconRect=New Recti( 0,iy,_iconSize.x,iy+_iconSize.y )Local tx:=_iconSize.x,ty:=0Local tw:=_textSize.x,th:=Height_textRect=New Recti( tx,ty,tx+tw,ty+th )_textRect=New Recti(0,0,100,20)'the default size (for now!)Local x1:=WidthFor Local view:=Eachin _views.Backwards()Local x0:=Max( x1-view.LayoutSize.x,_textRect.Right )view.Frame=New Recti( x0,0,x1,Height )x1=x0NextReturnLocal x0:=_textRect.RightFor Local view:=Eachin _viewsLocal x1:=Min( x0+view.LayoutSize.x,Width )view.Frame=New Recti( x0,0,x1,Height )x0=x1NextEndMethod OnRender( canvas:Canvas ) OverrideLocal s:=Self.FrameLocal pp:Floatpp=Float(100)*_valuecanvas.Color=Color.Greycanvas.DrawRect(s.X,s.Y,s.X+102,s.Y+15)canvas.Color=Color.Redcanvas.DrawRect(s.X+1,s.Y+1,s.X+pp,s.Y+12)EndMethod OnMouseEvent( event:MouseEvent ) OverrideSelect event.TypeCase EventType.MouseDown,EventType.MouseWheelReturnCase EventType.MouseClickClicked()Case EventType.MouseRightClickRightClicked()Case EventType.MouseDoubleClickDoubleClicked()Endevent.Eat()EndPrivateField _value:floatField _views:=New Stack<View>Field _iconSize:Vec2iField _iconRect:RectiField _textSize:Vec2iField _textRect:RectiField _viewsSize:Vec2iEndPBar example
Monkey12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455#import "<std>"#import "<mojo>"#import "<mojox>"Using std..Using mojo..Using mojox..Class MyWindow Extends WindowGlobal pb:PBar,label:LabelGlobal timer:TimerGlobal counter:IntGlobal bvalue:Float=0.1Method New()Super.New( "Pbar Demo",640,480,WindowFlags.Resizable )label=New Label( "Idle" )label.Gravity=New Vec2f( .5,0 )pb=New PBar(bvalue)pb.Layout="stretch"timer=New Timer(2,OnUpdate)Local dockingView:=New DockingViewdockingView.AddView( label,"top" )dockingView.AddView( pb,"top" )ContentView=dockingViewEndMethod OnUpdate()counter+=1Print "Tick: "+counterbvalue=bvalue+.1pb.Update(bvalue)label.Text="Value "+bvalueEndEndFunction Main()New AppInstanceNew MyWindowApp.Run()EndCheers!
August 21, 2016 at 8:56 pm #3343Nice first attempt!
It’s a bit overcomplicated, probably because you based it on Label which actually does quite a bit these days! I’ve attached a simplified version below, with the text and event stuff ripped out for clarity. If you do want text/events on your PBar, it’s probably best to just extend Label…in which case you can ditch OnMeasure and just call Super.OnRender at the end of OnRender.
Some notes:
It’s a good idea to set preferred Layout, TextGravity (now fixed!) etc for a view in it’s ctor to increase the chances of it working as expected by users!
I’d recommend ‘fill-x’ layout for view’s like this – ‘stretch’ will cause rendering to be scaled which can look wonky/ugly and distorts borders, skins etc. Also, by using ‘fill-x’ you don’t have to worry about the width returned by OnMeasure, as it will be effectively thrown away. So in the code below, I just return (16,16) from OnMeasure, of which only the height is actually used. However, it’s always a good idea to return something non-0 in OnMeasure just in case the user sets some weird Layout mode. For example, setting my PBar’s Layout to “float” means it will end up being 16 x 16, which wont look ideal but at least it will work. In this case, the user will probably have to use MinSize etc to make it look any good, but that’s OK, you’re not pyschic and can’t be expected to know how wide they want their floating PBars!
A view’s Frame rect is in ‘parent’ coords (parents use it to layout children) so it’s not really much use to children and you don’t want to use it inside OnRender. Unless you’re writing a layout view, you can probably ignore frame altogether. Instead, just use Rect, Width and Height inside OnRender (just like a game). Rect.X and Rect.Y are always (0,0) so Rect discribes the view’s local coordinate system. This makes my PBar’s OnRender very simple!
I’ve also added a custome style to the PBar that adds a dark grey border, just to show how it’s done. Styles can actually be stored in a theme ‘.json’ file, but more on that later. Note that adding/changing a view’s style doesn’t affect anything in terms of OnMeasure/OnRender – this is automatically handled for you by the system.
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104#import "<std>"#import "<mojo>"#import "<mojox>"Using std..Using mojo..Using mojox..Class PBar Extends ViewMethod New( value:Float=0 )Layout="fill-x"Style=New Style( Style )Style.Border=New Recti( -4,-4,4,4 )Style.BorderColor=Color.DarkGreyValue=valueEndProperty Value:Float()Return _valueSetter( value:Float )value=Clamp( value,0.0,1.0 )If value=_value Return_value=valueRequestRender()EndProtectedMethod OnMeasure:Vec2i() OverrideReturn New Vec2i( 16,16 )EndMethod OnRender( canvas:Canvas ) OverrideLocal t:=Int( Width*_value )canvas.Color=Color.Greycanvas.DrawRect( 0,0,t,Height )canvas.Color=Color.Redcanvas.DrawRect( t,0,Width-t,Height )EndPrivateField _value:FloatEndClass MyWindow Extends WindowGlobal pb:PBar,label:LabelGlobal timer:TimerGlobal counter:IntGlobal bvalue:Float=0.1Method New()Super.New( "Pbar Demo",640,480,WindowFlags.Resizable )label=New Label( "Idle" )label.Gravity=New Vec2f( .5,0 )pb=New PBar(bvalue)timer=New Timer(2,OnUpdate)Local dockingView:=New DockingViewdockingView.AddView( label,"top" )dockingView.AddView( pb,"top" )ContentView=dockingViewEndMethod OnUpdate()counter+=1Print "Tick: "+counterbvalue=bvalue+.1pb.Value=bvaluelabel.Text="Value "+bvalueEndEndFunction Main()New AppInstanceNew MyWindowApp.Run()EndAugust 21, 2016 at 9:27 pm #3346Wow, very clean & much more readable!
I’m not used to Property/Setter … same result but in a more ‘human logic’ way!
And I discovered Clamp() too!I have something new to study now (Style)!
 - 
		AuthorPosts
 
You must be logged in to reply to this topic.