📄 tree-box.zc
字号:
//[of]:description
//[c]Display a tree view. The widget is based on a model/view scheme:
//[c]there is an observable model to implement.
//[c]
//[c]Classes:
//[c]tree model -- the model object
//[c]tree item -- the nodes of the model
//[c]tree listener -- interface to listen events from the model
//[c]tree box -- the graphical component
//[c]
//[cf]
//[of]:license
//[c]Code Browser - a folding text editor for programmers
//[c]Copyright (C) 2003-07 Marc Kerbiquet
//[c]
//[c]This program is free software; you can redistribute it and/or modify
//[c]it under the terms of the GNU General Public License as published by
//[c]the Free Software Foundation; either version 2 of the License, or
//[c](at your option) any later version.
//[c]
//[c]This program is distributed in the hope that it will be useful,
//[c]but WITHOUT ANY WARRANTY; without even the implied warranty of
//[c]MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//[c]GNU General Public License for more details.
//[c]
//[c]You should have received a copy of the GNU General Public License
//[c]along with this program; if not, write to the Free Software
//[c]Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//[cf]
//[of]:imports
import "base/types"
import "base/memory-allocator"
import "text/vector-of-strings"
import "text/string"
import "text/string-buffer"
//[c]
import "graphics/geometry"
import "graphics/graphics"
import "user/box"
import "user/image-list"
//[c]
import "win32/windows"
import "win32/commctrl"
//[cf]
//[c]
//[of]:tree model
//[of]:type
public struct tree model
class: tree model class
end
public struct tree model class
root: {tree model} tree item
add listener: {tree model, tree listener} void
remove listener: {tree model, tree listener} void
end
//[cf]
//[c]
//[of]:root
public func root (m: tree model)
return root (class (m)) {m}
end
//[cf]
//[of]:add listener (listener)
//[c]
func add listener (m: tree model, listener: tree listener)
add listener (class (m)) {m, listener}
end
//[cf]
//[of]:remove listener (listener)
//[c]
func remove listener (m: tree model, listener: tree listener)
remove listener (class (m)) {m, listener}
end
//[cf]
//[cf]
//[of]:tree item
//[of]:type
public struct tree item
class: tree item class
end
public struct tree item class
append text: {tree item, string buffer} void
parent: {tree item} tree item
first child: {tree item} tree item
next sibling: {tree item} tree item
open: {tree item} void
close: {tree item} void
has children: {tree item} bool
image: {tree item} int
end
//[c]
//[cf]
//[c]
//[of]:append text
public func append text (m: tree item, s: string buffer)
append text (class (m)) {m, s}
end
//[cf]
//[of]:parent
public func parent (m: tree item)
return parent (class (m)) {m}
end
//[cf]
//[of]:first child
public func first child (m: tree item)
return first child (class (m)) {m}
end
//[cf]
//[of]:next sibling
public func next sibling (m: tree item)
return next sibling (class (m)) {m}
end
//[cf]
//[of]:open
public func open (m: tree item)
open (class (m)) {m}
end
//[cf]
//[of]:close
public func close (m: tree item)
close (class (m)) {m}
end
//[cf]
//[of]:has children
//[c]
public func has children (m: tree item)
return has children (class (m)) {m}
end
//[cf]
//[of]:image
//[c]
public func image (m: tree item)
return image (class (m)) {m}
end
//[cf]
//[cf]
//[of]:tree listener
//[of]:definition
//[c]
public struct tree listener
recipient: object
text changed: {object, tree item} void
data changed: {object, tree item} void
has children changed: {object, tree item} void
children replaced: {object, tree replace event} void
end
//[c]
public struct tree replace event
parent: tree item
index: dword
removed: dword
inserted: dword
end
//[c]
public func text changed (m: tree listener, item: tree item)
text changed (m) {recipient (m), item}
end
//[c]
public func data changed (m: tree listener, item: tree item)
data changed (m) {recipient (m), item}
end
//[c]
public func has children changed (m: tree listener, item: tree item)
has children changed (m) {recipient (m), item}
end
//[c]
public func children replaced (m: tree listener, e: tree replace event)
children replaced (m) {recipient (m), e}
end
//[cf]
//[cf]
//[of]:tree item changed event
//[c]
public struct tree item changed event : local event
tree item : tree item
end
//[c]
public def tree item changed event type : local event type
//[cf]
//[c]
//[of]:tree box
//[of]:type
public struct tree box : local box
private
tree model: tree model
selected item: tree item
synchronizing selection: bool
listener: local tree listener
image list: image list
original selected item: tree item
end
//[cf]
//[of]:instance creation
//[of]:new tree box (parent)
public func new tree box (parent: box)
equ s = sizeof local tree box
def e = allocate memory (s): tree box
initialize (e, parent)
return e
end
//[cf]
//[cf]
//[of]:tree
//[of]:tree
public func tree (m: tree box)
return tree model (m)
end
//[cf]
//[of]:set tree (tree)
public func set tree (m: tree box, tree: tree model)
def selection = not nil (tree) -> root (tree), nil
set tree (m, tree, selection)
end
//[cf]
//[of]:set tree (tree, selection)
//[c]Change the tree and selection
//[c]
//[c]ARGUMENTS
//[c] tree -- the tree to show
//[c] selection -- the node to select
//[c]
//[c]REMARKS
//[c] tree must be the same as the one edited by the source box.
//[c]
private func set tree (m: tree box, tree: tree model, selection: tree item)
def old tree = tree model (m)
tree model (m) = tree
if not nil (old tree)
remove listener (old tree, listener (m))
end
if not nil (tree)
add listener (tree, listener (m))
end
// Delete the current tree
if not nil (old tree)
send message (m, TVM_DELETEITEM, 0:WPARAM, TVI_ROOT:LPARAM)
end
synchronize widget tree (m)
selected item (m) = nil // force update
set selection (m, selection)
end
//[cf]
//[cf]
//[of]:selection
//[of]:selection
//[c]Returns the the currently selected item or nil
//[c]
public func selection (m: tree box)
return selected item (m)
end
//[cf]
//[of]:set selection (item)
//[c]Changes the current selection
//[c]to unselect, use nil as item
//[c]
public func set selection (m: tree box, item: tree item)
if item <> selected item (m)
selected item (m) = item
synchronize widget selection (m)
on selection changed (m)
end
end
//[cf]
//[cf]
//[of]:image list
//[of]:set image list (list)
public func set image list (m: tree box, list: image list)
image list (m) = list
synchronize image list (m)
end
//[cf]
//[cf]
//[of]:style
//[of]:set style (style)
//[c]
public func set style (m: tree box, style: box style)
set style (super (m), style)
update from style (m)
end
//[cf]
//[cf]
//[c]
//[of]:restricted
//[of]:initialize (parent)
public func initialize (m: tree box, parent: box)
initialize (super (m), parent)
class (m) = tree box class
tree model (m) = nil
selected item (m) = nil
original selected item (m) = nil
synchronizing selection (m) = false
image list (m) = nil
recipient (listener (m)) = m
text changed (listener (m)) = ^text changed (tree box, tree item)
data changed (listener (m)) = ^data changed (tree box, tree item)
has children changed (listener (m)) = ^has children changed (tree box, tree item)
children replaced (listener (m)) = ^children replaced (tree box, tree replace event)
create managed window ex (
m,
get ex style (m),
WC_TREEVIEW,
nil,
get style (m),
m:HMENU,
nil)
update from style (m)
end
//[cf]
//[c]
//[of]:notify proc (pnmtv)
//[c]Standard notify procedure
//[c]
public func notify proc (m: tree box, pnmh: LPNMHDR)
equ pnmtv = pnmh : LPNMTREEVIEW
if code (pnmh) == TVN_ITEMEXPANDINGA && action (pnmtv) == TVE_EXPAND
def hItem = hItem (itemNew (pnmtv))
// Windows sends this notification even if the node is already expanded
// when pressing the '+' key from the notepad. So we need to check
// the expand status of the item before adding children.
if ~ is expanded (m, hItem)
def item = lParam (itemNew (pnmtv)) : tree item
add children (m, hItem, item)
end
elsif code (pnmh) == TVN_ITEMEXPANDINGA && action (pnmtv) == TVE_COLLAPSE
def hItem = hItem (itemNew (pnmtv))
def item = lParam (itemNew (pnmtv)) : tree item
// selection is changed, but SELCHANGED is not emitted:
// need to force selection
def child = selected item (m)
while not nil (child)
if child == item
set selection (m, item)
break
end
child = parent (child)
end
send message (m,
TVM_EXPAND,
(TVE_COLLAPSE | TVE_COLLAPSERESET) : WPARAM,
hItem : LPARAM)
close opened (m, hItem, item)
elsif code (pnmh) == TVN_SELCHANGEDA
if ~ synchronizing selection (m)
def hItem = hItem (itemNew (pnmtv))
def item = lParam (itemNew (pnmtv)) : tree item
selected item (m) = item
on selection changed (m)
end
end
return 0
end
//[c]
func close opened (m: tree box, hItem: HTREEITEM, item: tree item) : void
def hChild = first child (m, hItem)
if is nil (hChild)
return
end
while not nil (hChild)
close opened (m, hChild, tree item (m, hChild))
hChild = next sibling (m, hChild)
end
close (item)
end
//[cf]
//[of]:window proc (msg, wparam, lparam)
public func window proc (
m: tree box,
msg: UINT,
wParam: WPARAM,
lParam: LPARAM)
if msg == WM_RBUTTONDOWN
def ht: TVHITTESTINFO
x (pt (ht)) = LOWORD (lParam) : int
y (pt (ht)) = HIWORD (lParam) : int
send message (m, TVM_HITTEST, 0:WPARAM, ht: LPARAM)
if not nil (hItem (ht)) && (flags (ht) & (TVHT_ONITEMICON | TVHT_ONITEMLABEL)) <> 0
original selected item (m) = selected item (m)
selected item (m) = tree item (m, hItem (ht))
synchronizing selection (m) = true
def tvi: TVITEM
mask (tvi) = TVIF_STATE
hItem (tvi) = hItem (ht)
stateMask (tvi) = TVIS_SELECTED
send message (m, TVM_GETITEM, 0:WPARAM, tvi:LPARAM)
if (state (tvi) & TVIS_SELECTED) == 0
send message (m, TVM_SELECTITEM, TVGN_CARET:WPARAM, hItem (tvi):LPARAM)
end
synchronizing selection (m) = false
end
// process default
end
return window proc (super (m), msg, wParam, lParam)
end
//[cf]
//[c]
//[of]:actual compute min size
public func actual compute min size (m: tree box)
def w = 100
def h = 100
set min size(m, w, h)
end
//[cf]
//[of]:actual release
public func actual release (m: tree box)
actual release (super (m))
def tree = tree model (m)
if not nil (tree)
remove listener (tree, listener (m))
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -