浏览代码

Playing around with mojox.

Mark Sibly 9 年之前
父节点
当前提交
9ac0db994f

+ 26 - 0
modules/mojox/assets/themes/default.json

@@ -263,6 +263,19 @@
 		"TreeViewContent":{
 			"padding":[2]
 		},
+
+		"TreeViewNode":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
 		
 		"ListView":{
 			"backgroundColor":"content"
@@ -272,6 +285,19 @@
 			"padding":[2]
 		},
 		
+		"ListViewItem":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
+		
 		"FileBrowser":{
 			"extends":"TreeView"
 		},

+ 143 - 17
modules/mojox/listview.monkey2

@@ -11,6 +11,10 @@ Class ListView Extends ScrollableView
 	#end
 	Field ItemDoubleClicked:Void( item:Item )
 
+	#rem monkeydoc Invoked when an item is right clicked.
+	#end
+	Field ItemRightClicked:Void( item:Item )
+
 	Class Item Extends ViewCell
 	
 		Method New( text:String,icon:Image,list:ListView )
@@ -30,6 +34,21 @@ Class ListView Extends ScrollableView
 	Method New()	
 		Style=GetStyle( "ListView" )
 		ContentView.Style=GetStyle( "ListViewContent" )
+		_itemStyle=GetStyle( "ListViewItem" )
+	End
+
+	#rem monkeydoc Currently selected item.
+	#end	
+	Property Selected:Item()
+	
+		Return _selected
+	
+	Setter( selected:Item )
+		If selected=_selected Return
+	
+		_selected=selected
+		
+		RequestRender()
 	End
 
 	#rem monkeydoc Adds an item to the list view.
@@ -54,10 +73,8 @@ Class ListView Extends ScrollableView
 	#rem monkeydoc Removes an item from the list view.
 	#end
 	Method RemoveItem( index:Int )
-		
-		_items.Erase( index )
-		
-		RequestRender()
+	
+		RemoveItems( index,index+1 )
 	End
 	
 	#rem monkeydoc Removes an item from the list view.
@@ -71,6 +88,12 @@ Class ListView Extends ScrollableView
 	#end	
 	Method RemoveItems( index1:Int,index2:Int )
 	
+		For Local i:=index1 Until index2
+			If _items[i]<>_selected Continue
+			Selected=Null
+			Exit
+		Next
+	
 		_items.Erase( index1,index2 )
 		
 		RequestRender()
@@ -82,6 +105,10 @@ Class ListView Extends ScrollableView
 	
 		_items.Clear()
 		
+		_selected=Null
+		
+		_hover=null
+		
 		RequestRender()
 	End
 	
@@ -99,12 +126,14 @@ Class ListView Extends ScrollableView
 	#rem monkeydoc Returns the item at a point in the list view.
 	#end
 	Method ItemAtPoint:Item( point:Vec2i )
-
-		For Local item:=Eachin _items
-			If item._rect.Contains( point ) Return item
-		Next
+	
+		Local i:=IndexOfItemAtPoint( point )
+		If i=-1 Return null
+		
+		Local item:=_items[i]
+		If Not item._rect.Contains( point ) Return Null
 		
-		Return Null
+		Return item
 	End
 	
 	Protected
@@ -117,7 +146,9 @@ Class ListView Extends ScrollableView
 		
 		For Local item:=Eachin _items
 		
-			Local size:=item.Measure( RenderStyle )
+			Local style:=ItemStyle( item )
+		
+			Local size:=item.Measure( style )
 			
 			item._rect=New Recti( 0,h,size.x,h+size.y )
 			
@@ -133,30 +164,125 @@ Class ListView Extends ScrollableView
 	#end
 	Method OnRenderContent( canvas:Canvas ) Override
 	
-		Local x:=0,y:=0
+		If _items.Empty Return
 	
-		For Local item:=Eachin _items
+		Local clip:=VisibleRect
+		
+		Local first:=IndexOfItemAtPoint( New Vec2i( 0,clip.Top ) ) 
+		If first=-1 first=0
+		
+		Local last:=IndexOfItemAtPoint( New Vec2i( 0,clip.Bottom-1 ) )+1
+		If Not last last=_items.Length
+		
+		For Local i:=first Until last
+		
+			Local item:=_items[i]
+		
+			Local style:=ItemStyle( item )
+		
+			item.Render( canvas,item._rect,style,New Vec2f( 0,.5 ) )
+		Next
 		
-			item.Render( canvas,item._rect,RenderStyle,New Vec2f( 0,.5 ) )
-		Next			
 	End
 	
 	#rem monkeydoc @hidden
 	#end
-	Method OnMouseEvent( event:MouseEvent ) Override
+	Method OnContentMouseEvent( event:MouseEvent ) Override
 	
 		Select event.Type
+		
+		Case EventType.MouseDown,EventType.MouseWheel
+		
+			Return
+
 		Case EventType.MouseClick
+		
+			Local item:=ItemAtPoint( event.Location )
+			If item
+				Selected=item
+				ItemClicked( item )
+			Endif
+			
+		Case EventType.MouseRightClick
+		
 			Local item:=ItemAtPoint( event.Location )
-			If item ItemClicked( item )
+			If item
+				Selected=item
+				ItemRightClicked( item )
+			Endif
+			
 		Case EventType.MouseDoubleClick
+		
 			Local item:=ItemAtPoint( event.Location )
 			If item ItemDoubleClicked( item )
+			
+		Case EventType.MouseMove,EventType.MouseMove
+		
+			Local item:=ItemAtPoint( event.Location )
+			If item<>_hover
+				_hover=item
+				RequestRender()
+			Endif
+			
+		Case EventType.MouseLeave
+		
+			If _hover
+				_hover=Null
+				RequestRender()
+			Endif
+
 		End
+		
+		event.Eat()
+	End
+	
+	Protected
 	
+	Method OnValidateStyle() Override
+		_hoverStyle=_itemStyle.GetState( "hover" )
+		_selectedStyle=_itemStyle.GetState( "selected" )
 	End
-
+	
 	Private
 	
 	Field _items:=New Stack<Item>
+	
+	Field _itemStyle:Style
+	Field _hoverStyle:Style
+	Field _selectedStyle:Style
+	
+	Field _hover:Item
+	Field _selected:Item
+	
+	Field _dirty:Bool
+
+	Method ItemStyle:Style( item:Item )
+	
+		If item=_selected Return _selectedStyle
+		
+		If item=_hover Return _hoverStyle
+		
+		Return _itemStyle
+	End
+	
+	Method IndexOfItemAtPoint:Int( p:Vec2i )
+
+		If _items.Empty Or p.y<_items[0]._rect.Top Or p.y>=_items.Top._rect.Bottom Return -1
+		
+		Local min:=0,max:=_items.Length-1
+		
+		Repeat
+			Local i:=(min+max)/2
+			If p.y>=_items[i]._rect.Bottom
+				min=i+1
+			Else If max-min>1
+				max=i
+			Else
+				Return i
+			Endif
+		Forever
+		
+		Return -1
+	End
+	
 End

二进制
modules/mojox/tests/assets/monkey2.png


+ 20 - 18
modules/mojox/tests/listview_test.monkey2

@@ -3,6 +3,8 @@
 #Import "<mojo>"
 #Import "<mojox>"
 
+#Import "assets/monkey2.png"
+
 Using std..
 Using mojo..
 Using mojox..
@@ -12,26 +14,26 @@ Class MyWindow Extends Window
 	Method New()
 		Super.New( "Simple Mojo Gui App",640,480,WindowFlags.Resizable )
 		
-		Local icon:=Image.Load( DesktopDir()+"monkey2.png" )
+		Local icon:=Image.Load( "asset::monkey2.png" )
 		
 		Local list:=New ListView
-		list.AddItem( "Hello there!~nThis is a wide listview!",icon )
-		list.AddItem( "there" )
-		list.AddItem( "this" )
-		list.AddItem( "is" )
-		list.AddItem( "listview" )
-		list.AddItem( "Hello there this is a wide listview!" )
-		list.AddItem( "there" )
-		list.AddItem( "this" )
-		list.AddItem( "is" )
-		list.AddItem( "listview" )
-		list.AddItem( "Hello there this is a wide listview!" )
-		list.AddItem( "there" )
-		list.AddItem( "this" )
-		list.AddItem( "is" )
-		list.AddItem( "listview" )
-		
-		list.InsertItem( 0,"Insert item at top" )
+		For Local i:=0 until 100
+			list.AddItem( "Hello there!~nThis is a wide listview!~nWith an icon!",icon )
+			list.AddItem( "there" )
+			list.AddItem( "this" )
+			list.AddItem( "is" )
+			list.AddItem( "listview" )
+			list.AddItem( "Hello there this is a wide listview!" )
+			list.AddItem( "there" )
+			list.AddItem( "this" )
+			list.AddItem( "is" )
+			list.AddItem( "listview" )
+			list.AddItem( "Hello there this is a wide listview!" )
+			list.AddItem( "there" )
+			list.AddItem( "this" )
+			list.AddItem( "is" )
+			list.AddItem( "listview" )
+		Next
 		
 		list.ItemClicked+=Lambda( item:ListView.Item )
 			Local index:=list.IndexOfItem( item )

+ 62 - 38
modules/mojox/treeview.monkey2

@@ -36,20 +36,15 @@ Class TreeView Extends ScrollableView
 			Text=text
 		End
 		
-		#rem monkeydoc Node style.
-		
-		If null, the node uses the tree view's style.
-		
+		#rem monkeydoc True if node is selected.
 		#end
-		Property Style:Style()
+		Property Selected:Bool()
 		
-			Return _style
+			Return _selected
 		
-		Setter( style:Style )
+		Setter( selected:Bool )
 		
-			_style=style
-			
-			Dirty()
+			_selected=selected
 		End
 
 		#rem monkeydoc Node parent.
@@ -217,8 +212,8 @@ Class TreeView Extends ScrollableView
 		
 		Field _parent:Node
 		Field _children:=New Stack<Node>	'should make on demand...
-		Field _style:Style
 		Field _expanded:Bool
+		Field _selected:Bool
 		Field _bounds:Recti
 		Field _rect:Recti
 		Field _dirty:Bool
@@ -238,6 +233,7 @@ Class TreeView Extends ScrollableView
 	Method New()
 		Style=GetStyle( "TreeView" )
 		ContentView.Style=GetStyle( "TreeViewContent" )
+		_nodeStyle=GetStyle( "TreeViewNode" )
 		
 		Layout="fill"
 		
@@ -283,20 +279,19 @@ Class TreeView Extends ScrollableView
 	
 	Protected
 	
-	Method OnThemeChanged() Override
-	
-		_rootNode.Dirty()
-	End
-	
 	Method OnValidateStyle() Override
 	
-		Local style:=RenderStyle
+		_hoverStyle=_nodeStyle.GetState( "hover" )
+		_selectedStyle=_nodeStyle.GetState( "selected" )
 	
+		Local style:=RenderStyle
+		
 		_nodeSize=style.Font.Height
-		_spcWidth=style.Font.TextWidth( " " )
 		
 		_collapsedIcon=style.Icons[0]
 		_expandedIcon=style.Icons[1]
+		
+		_rootNode.Dirty()
 	End
 	
 	Method OnMeasureContent:Vec2i() Override
@@ -322,9 +317,9 @@ Class TreeView Extends ScrollableView
 	Method OnContentMouseEvent( event:MouseEvent ) Override
 	
 		Local p:=event.Location
-	
+		
 		Select event.Type
-		Case EventType.MouseDown
+		Case EventType.MouseDown,EventType.MouseWheel
 		
 			Return
 			
@@ -334,13 +329,15 @@ Class TreeView Extends ScrollableView
 
 			If node
 			
-				p-=node._rect.Origin
+				If p.x>=node._rect.min.x+_nodeSize
 				
-				If p.x<_nodeSize And p.y<node.Rect.Height
+					NodeClicked( node )
+				
+				Else
 				
 					node.Expanded=Not node.Expanded
 					
-					App.RequestRender()
+					RequestRender()
 					
 					If node.Expanded
 						NodeExpanded( node )
@@ -348,14 +345,10 @@ Class TreeView Extends ScrollableView
 						NodeCollapsed( node )
 					Endif
 					
-				Else
-				
-					NodeClicked( node )
-					
 				Endif
 				
 			Endif
-		
+			
 		Case EventType.MouseRightClick
 		
 			Local node:=FindNodeAtPoint( _rootNode,p )
@@ -368,9 +361,27 @@ Class TreeView Extends ScrollableView
 			
 			If node NodeDoubleClicked( node )
 			
-		Case EventType.MouseWheel
+		Case EventType.MouseEnter,EventType.MouseMove
+		
+			Local node:=FindNodeAtPoint( _rootNode,p )
+
+			If node And p.x>=node._rect.min.x+_nodeSize
+				If node<>_hover
+					_hover=node
+					RequestRender()
+				Endif
+			Else If _hover
+				_hover=null
+				RequestRender()
+			Endif
+			
+		Case EventType.MouseLeave
+		
+			If _hover
+				_hover=Null
+				RequestRender()
+			Endif
 		
-			Return
 		End
 		
 		event.Eat()
@@ -379,16 +390,19 @@ Class TreeView Extends ScrollableView
 	
 	Private
 	
-	Field _spacing:=2
-	
 	Field _rootNode:Node
 	Field _rootNodeVisible:=True
 	
 	Field _expandedIcon:Image
 	Field _collapsedIcon:Image
 	Field _nodeSize:Int
-	Field _spcWidth:Int
-		
+	
+	Field _nodeStyle:Style
+	Field _hoverStyle:Style
+	Field _selectedStyle:Style
+	
+	Field _hover:Node
+	
 	Method FindNodeAtPoint:Node( node:Node,point:Vec2i )
 	
 		If node._rect.Contains( point ) Return node
@@ -416,13 +430,13 @@ Class TreeView Extends ScrollableView
 		Local size:Vec2i,nodeSize:=0
 		
 		If node<>_rootNode Or _rootNodeVisible
-
-			Local style:=node._style ? node._style Else RenderStyle
+		
+			Local style:=NodeStyle( node )
 		
 			size=node.Measure( style )
 			
 			size.x+=_nodeSize
-			size.y=Max( size.y,_nodeSize )+_spacing
+			size.y=Max( size.y,_nodeSize )
 			
 			nodeSize=_nodeSize
 		Endif
@@ -471,7 +485,7 @@ Class TreeView Extends ScrollableView
 			
 			rect.min.x+=_nodeSize
 			
-			Local style:=node._style ? node._style Else RenderStyle
+			Local style:=NodeStyle( node )
 			
 			node.Render( canvas,rect,style,New Vec2f( 0,.5 ) )
 		Endif
@@ -483,8 +497,18 @@ Class TreeView Extends ScrollableView
 				RenderNode( canvas,child )
 				
 			Next
+
 		Endif
 		
 	End
 	
+	Method NodeStyle:Style( node:Node )
+	
+		If node._selected Return _selectedStyle
+		
+		If node=_hover Return _hoverStyle
+		
+		Return _nodeStyle
+	End
+	
 End

+ 6 - 0
modules/mojox/viewcell.monkey2

@@ -42,11 +42,17 @@ Class ViewCell
 			size.y=Max( size.y,Int( _icon.Height ) )
 		Endif
 		
+		size+=style.Bounds.Size
+		
 		Return size
 	End
 	
 	Method Render( canvas:Canvas,rect:Recti,style:Style,textGravity:Vec2f ) Virtual
 	
+		style.Render( canvas,rect )
+		
+		rect-=style.Bounds
+	
 		If _icon
 			Local y:=(rect.Height-_icon.Height)/2
 			style.DrawIcon( canvas,_icon,rect.min.x,rect.min.y+y )

+ 26 - 4
src/ted2/assets/themes/default.json

@@ -263,6 +263,19 @@
 		"TreeViewContent":{
 			"padding":[2]
 		},
+
+		"TreeViewNode":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
 		
 		"ListView":{
 			"backgroundColor":"content"
@@ -272,6 +285,19 @@
 			"padding":[2]
 		},
 		
+		"ListViewItem":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
+		
 		"FileBrowser":{
 			"extends":"TreeView"
 		},
@@ -318,10 +344,6 @@
 		"HelpTextField":{
 			"extends":"TextField",
 			"skinColor":"panel"
-		},
-		
-		"SelectedNodeStyle":{
-			"textColor":"text-highlight"
 		}
 	}
 }

+ 26 - 4
src/ted2/assets/themes/theme-blitzed.json

@@ -265,6 +265,19 @@
 			"padding":[2]
 		},
 
+		"TreeViewNode":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
+		
 		"ListView":{
 			"backgroundColor":"content"
 		},
@@ -273,6 +286,19 @@
 			"padding":[2]
 		},
 		
+		"ListViewItem":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
+		
 		"FileBrowser":{
 			"extends":"TreeView"
 		},
@@ -319,10 +345,6 @@
 		"HelpTextField":{
 			"extends":"TextField",
 			"skinColor":"panel"
-		},
-		
-		"SelectedNodeStyle":{
-			"textColor":"text-highlight"
 		}
 	}
 }

+ 26 - 4
src/ted2/assets/themes/theme-classic-dark.json

@@ -263,6 +263,19 @@
 		"TreeViewContent":{
 			"padding":[2]
 		},
+
+		"TreeViewNode":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
 		
 		"ListView":{
 			"backgroundColor":"content"
@@ -272,6 +285,19 @@
 			"padding":[2]
 		},
 		
+		"ListViewItem":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
+		
 		"FileBrowser":{
 			"extends":"TreeView"
 		},
@@ -319,10 +345,6 @@
 		"HelpTextField":{
 			"extends":"TextField",
 			"skinColor":"panel"
-		},
-		
-		"SelectedNodeStyle":{
-			"textColor":"text-highlight"
 		}
 	}
 }

+ 26 - 4
src/ted2/assets/themes/theme-monkey1.json

@@ -264,6 +264,19 @@
 		"TreeViewContent":{
 			"padding":[2]
 		},
+
+		"TreeViewNode":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
 		
 		"ListView":{
 			"backgroundColor":"content"
@@ -273,6 +286,19 @@
 			"padding":[2]
 		},
 		
+		"ListViewItem":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
+		
 		"FileBrowser":{
 			"extends":"TreeView"
 		},
@@ -319,10 +345,6 @@
 		"HelpTextField":{
 			"extends":"TextField",
 			"skinColor":"panel"
-		},
-		
-		"SelectedNodeStyle":{
-			"textColor":"text-highlight"
 		}
 	}
 }

+ 26 - 4
src/ted2/assets/themes/theme-overcast.json

@@ -264,6 +264,19 @@
 		"TreeViewContent":{
 			"padding":[2]
 		},
+
+		"TreeViewNode":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
 		
 		"ListView":{
 			"backgroundColor":"content"
@@ -273,6 +286,19 @@
 			"padding":[2]
 		},
 		
+		"ListViewItem":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
+		
 		"FileBrowser":{
 			"extends":"TreeView"
 		},
@@ -319,10 +345,6 @@
 		"HelpTextField":{
 			"extends":"TextField",
 			"skinColor":"panel"
-		},
-		
-		"SelectedNodeStyle":{
-			"textColor":"text-highlight"
 		}
 	}
 }

+ 8 - 11
src/ted2/helptree.monkey2

@@ -161,7 +161,7 @@ Class HelpTree Extends TreeView
 			
 		_matches.Clear()
 			
-		Local highlighted:=New Map<Node,Bool>
+		Local selected:=New Map<Node,Bool>
 			
 		For Local it:=Eachin _index
 			
@@ -171,9 +171,9 @@ Class HelpTree Extends TreeView
 				
 			_matches.Push( node )
 				
-			node.Style=_highlight
+			node.Selected=True
 				
-			highlighted[node]=True
+			selected[node]=True
 				
 			While node
 				node.Expanded=True
@@ -182,12 +182,13 @@ Class HelpTree Extends TreeView
 
 		Next
 						
-		For Local node:=Eachin _highlighted.Keys
+		For Local node:=Eachin _selected.Keys
 			
-			If Not highlighted.Contains( node ) node.Style=Null
+			If Not selected.Contains( node ) node.Selected=False
+
 		Next
 			
-		_highlighted=highlighted
+		_selected=selected
 			
 		RootNode.Expanded=True
 			
@@ -213,8 +214,6 @@ Class HelpTree Extends TreeView
 	
 	Method Init()
 
-		_highlight=GetStyle( "SelectedNodeStyle" )
-	
 		_textField=New TextField
 		_textField.Style=GetStyle( "HelpTextField" )
 		
@@ -248,13 +247,11 @@ Class HelpTree Extends TreeView
 	
 	Field _textField:TextField
 	
-	Field _highlight:Style
-	
 	Field _matchid:Int
 		
 	Field _matches:=New Stack<Node>
 	
-	Field _highlighted:=New Map<Node,Bool>
+	Field _selected:=New Map<Node,Bool>
 	
 	Field _index:=New Map<String,Node>