⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 paned-box.zc

📁 实现树形结构
💻 ZC
字号:
//[of]:description
//[c]paned-box - a container with two children
//[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"
//[c]
import "graphics/geometry"
import "graphics/graphics"
import "user/box"
import "user/container-box"
import "user/blank-box"
//[cf]
//[c]
//[of]:paned box mode
//[c]
public enum paned box mode

	pbm single
	pbm horizontal
	pbm vertical

	pbm browser 3
	pbm browser 4
	pbm browser 5

	pbm vbrowser 3
	pbm vbrowser 4
	pbm vbrowser 5
	
end
//[cf]
//[of]:paned box
//[of]:type
public struct paned box : local container box

	mode : paned box mode
		
	// remember if a children has the focus
	private has focus : bool

	// the last page having the focus
	private last activated child : box

end
//[cf]
//[of]:instance creation
//[of]:new paned box (parent box, mode)
public func new paned box (parent: box, mode: paned box mode)

	equ s = sizeof local paned box
	def b = allocate memory (s): paned box
	initialize (b, parent, mode)
	return b

end
//[cf]
//[of]:new hpaned box (parent box)
public func new hpaned box (parent: box)

	return new paned box (parent, pbm horizontal)

end
//[cf]
//[of]:new vpaned box (parent box)
public func new vpaned box (parent: box)

	return new paned box (parent, pbm vertical)

end
//[cf]
//[cf]
//[of]:focus
//[of]:set focus (child)
//[c]Sets the focus on a child
//[c]
public func set focus (m: paned box, child: box)

	if has focus (m)
		set focus (child)
	else
		// well, we don't have the focus yet, but we must
		// remember to activate the first pane 
		last activated child (m) = child
	end

end
//[cf]
//[of]:focused child
//[c]Returns the immediate child that contain the focused widget or nil
//[c]
public func focused child (m: paned box)
	
	def child = last activated child (m)
	if not nil (child)
		while not nil (child)
			def parent = parent (child)
			if parent == m
				return child
			end
			child = parent
		end
	end
	return first child (m)

end
//[cf]
//[cf]
//[of]:accessing
//[of]:set mode (mode)
public func set mode (m: paned box, mode: paned box mode)

	if mode (m) == mode
		return
	end
	mode (m) = mode

	// focus must be updated before visibility otherwise the framework (GTK)
	// may throw the focus in outer space
	update focus (m)
	update visibility (m)

	// only if sized
	if ~ is empty (client rect (m))
		compute layout (m)
	end

	invalidate min size (m)
	invalidate (m)

end
//[cf]
//[c]
//[of]:number of pages
public func number of pages (m: paned box)

	return number of pages (m, mode (m))

end
//[cf]
//[of]:number of pages (mode)
//[c]Returns the number of pages for a given mode
//[c]
public equ number of pages (m: paned box, mode: paned box mode) =
	nb [mode]
//[c]
private def nb = const [] int (1, 2, 2, 3, 4, 5, 3, 4, 5)
//[cf]
//[cf]
//[of]:testing
//[of]:is browser
//[c]Returns true if the layout shows more than 2 controls
//[c]
public func is browser (m: paned box)

	return mode (m) > pbm vertical

end
//[cf]
//[cf]
//[c]
//[of]:restricted
//[of]:initialize (parent box, orientation)
public func initialize (m: paned box, parent: box, mode: paned box mode)

	initialize (super (m), parent)
	class (m) = paned box class
	mode (m) = mode
	has focus (m) = false
	last activated child (m) = nil
	
end
//[cf]
//[c]
//[of]:handle size
//[c]The grid has been resized
//[c]
public func handle size (m: paned box)
	compute layout (m)
end
//[cf]
//[of]:handle paint (canvas, clip)
//[c]
public func handle paint (m: paned box, c: canvas, clip: rectangle)

	def a = client rect (m)
	def p1 = first child (m)
	def p2 = next sibling (p1)
	def r : local rectangle
	def b := brush from system color (color button face)

	switch mode (m)
	case pbm single
		
		return

	case pbm horizontal

		def extra = w (a) - sep size
		extra -= min width (p1)
		extra -= min width (p2)

		x (r) = min width (p1) + (extra + 1) / 2
		w (r) = sep size
		y (r) = 0
		h (r) = h (a)
	
		fill rectangle (c, r, b)
	
	case pbm vertical
	
		def extra = h (a) - sep size
		extra -= min height (p1)
		extra -= min height (p2)
		
		x (r) = 0
		w (r) = w (a)
		y (r) = min height (p1) + (extra + 1) / 2
		h (r) = sep size

		fill rectangle (c, r, b)
	
	case pbm browser 3, pbm browser 4, pbm browser 5

		def h = top height (m)

		def extra = w (a) - top min width (m)
		def n = number of pages (m) - 1
		def last = 0
		x (r) = 0
		y (r) = 0
		w (r) = sep size
		h (r) = h
		def p = p1
		def i = 1
		while i < n
			def sum = i * extra / n
			def increment = sum - last
			last = sum
			
			x (r) += min width (p) + increment
			fill rectangle (c, r, b)
			x (r) += sep size
			
			p = next sibling (p)
			++ i
		end

		x (r) = 0
		w (r) = w (a)
		y (r) = h
		h (r) = sep size
		fill rectangle (c, r, b)

	else
	
		def w = left width (m)

		def extra = h (a) - left min height (m)
		def n = number of pages (m) - 1
		def last = 0
		x (r) = 0
		y (r) = 0
		w (r) = w
		h (r) = sep size
		def p = p1
		def i = 1
		while i < n
			def sum = i * extra / n
			def increment = sum - last
			last = sum
			
			y (r) += min height (p) + increment
			fill rectangle (c, r, b)
			y (r) += sep size
			
			p = next sibling (p)
			++ i
		end

		x (r) = w
		w (r) = sep size
		y (r) = 0
		h (r) = h (a)
		fill rectangle (c, r, b)

	end

end
//[cf]
//[of]:handle focus (event)
//[c]
public func handle focus (m: paned box, e: event)

	// transfer the focus to the last activated pane
	def child = last activated child (m)
	if is nil (child)
		child = first child (m)
	end
	set focus (child)
	return true

end
//[cf]
//[of]:handle child event (child, event)
//[c]
public func handle child event (m: paned box, b: box, e: event)

	def t = type (e)
	if t == focus event type
		has focus (m) = true
		def child = find child (m, b)
		if not nil (child)
			last activated child (m) = child
		end
	elsif t == blur event type
		has focus (m) = false
	end

	return handle child event (super (m), b, e)

end
//[cf]
//[cf]
//[of]:private
//[of]:constants
//[c]
private equ sep size = 4
//[cf]
//[c]
//[of]:actual adjust
//[c]Adjust
//[c]
//[c]	Min sizes may have changed: the layout must be recomputed
//[c]
func actual adjust (m: paned box)

	compute layout (m)

end
//[cf]
//[of]:actual compute min size
//[c]Compute min size
//[c]
public func actual compute min size(m: paned box)

	def p1 = first child (m)
	def p2 = next sibling (p1)
	def a = min size (m)

	switch mode (m)
	case pbm single
	
		set (a, min size (p1))
		
	case pbm horizontal

		w (a) = min width (p1) + min width (p2) + sep size
		h (a) = max (min height (p1), min height (p2))
		
	case pbm vertical

		w (a) = max (min width (p1), min width (p2))
		h (a) = min  height (p1) + min height (p2) + sep size
		
	case pbm browser 3, pbm browser 4, pbm browser 5
	
		def p = bottom pane (m)
		w (a) = max (top min width (m), min width (p))
		h (a) = top min height (m) + min height (p) + sep size

	else

		def p = right pane (m)
		w (a) = left min width (m) +  min width (p) + sep size
		h (a) = max (left min height (m), min height (p))

	end

end
//[cf]
//[c]
//[of]:compute layout
//[c]Compute the layout: move all children
//[c]
private func compute layout (m: paned box)

	def a = client rect (m)
	def w = w (a)
	def h = h (a)
	def p1 = first child (m)
	def p2 = next sibling (p1)
	def r1 : local rectangle
	def r2 : local rectangle
	x (r1) = 0
	y (r1) = 0

	switch mode (m)
	case pbm single

		move (p1, a)
		return
	
	case pbm horizontal

		def extra = w
		extra -= sep size
		extra -= min width (p1)
		extra -= min width (p2)
		def w1 = min width (p1) + (extra + 1) / 2
		def w2 = min width (p2) + extra / 2
		
		w (r1) = w1
		h (r1) = h

		x (r2) = w1 + sep size
		y (r2) = 0
		w (r2) = w2
		h (r2) = h
	
		move (p1, r1)
		move (p2, r2)

	case pbm vertical
	
		def extra = h
		extra -= sep size
		extra -= min height (p1)
		extra -= min height (p2)
		def h1 = min height (p1) + (extra + 1) / 2
		def h2 = min height (p2) + extra / 2
		
		w (r1) = w
		h (r1) = h1

		x (r2) = 0
		y (r2) = h1 + sep size
		w (r2) = w
		h (r2) = h2
		
		move (p1, r1)
		move (p2, r2)

	case pbm browser 3, pbm browser 4, pbm browser 5

		def h1 = top height (m)
		def h2 = bottom height (m)

		def extra = w - top min width (m)
		def n = number of pages (m) - 1
		def i = 1
		def last = 0
		def r : local rectangle
		x (r) = 0
		y (r) = 0
		h (r) = h1
		def p = p1
		while i <= n
			def sum = i * extra / n
			def increment = sum - last
			last = sum
			
			w (r) = min width (p) + increment
			move (p, r)
			x (r) += w (r) + sep size
			
			p = next sibling (p)
			++ i
		end
		
		x (r) = 0
		y (r) = h1 + sep size
		w (r) = w
		h (r) = h - y (r)
		move (bottom pane (m), r)

	else

		def w1 = left width  (m)
		def w2 = right width (m)

		def extra = h - left min height (m)
		def n = number of pages (m) - 1
		def i = 1
		def last = 0
		def r : local rectangle
		x (r) = 0
		y (r) = 0
		w (r) = w1
		def p = p1
		while i <= n
			def sum = i * extra / n
			def increment = sum - last
			last = sum
			
			h (r) = min height (p) + increment
			move (p, r)
			y (r) += h (r) + sep size
			
			p = next sibling (p)
			++ i
		end
		
		x (r) = w1 + sep size
		y (r) = 0
		w (r) = w - x (r)
		h (r) = h 
		move (right pane (m), r)

	end

end
//[cf]
//[of]:update focus
private func update focus (m: paned box)

	def child = focused child (m)

	def n = number of pages (m)
	def p = first child (m)
	while not nil (p) && n > 0
		if child == p
			return
		end
		p = next sibling (p)
		-- n
	end

	// if we arrive here, we have at least one
	// hidden child, and the focused is also hidden:
	// re-assign focus to the last visible one
	if not nil (p)
		set focus (m, prev sibling (p))
	end
	
end
//[cf]
//[of]:update visibility
private func update visibility (m: paned box)

	def n = number of pages (m)
	def p = first child (m)
	while not nil (p)
		set visible (p, n > 0)
		p = next sibling (p)
		-- n
	end

end
//[cf]
//[c]
//[of]:top min width
private func top min width (m: paned box)

	def n = number of pages (m) - 1
	def w = (n - 1) * sep size
	def p = first child (m)
	while n > 0
		w += min width (p)
		-- n
		p = next sibling (p)
	end

	return w

end
//[cf]
//[of]:top min height
private func top min height (m: paned box)

	def n = number of pages (m) - 1
	def h = 0
	def p = first child (m)
	while n > 0
		h = max (h, min height (p))
		-- n
		p = next sibling (p)
	end

	return h

end
//[cf]
//[of]:top height
private func top height (m: paned box)

	def min = top min height (m)
	def h = h (client rect (m))
	
	return max (min, h / 3)

end
//[cf]
//[of]:bottom height
private func bottom height (m: paned box)

	return height (client rect (m)) - top height (m) - sep size

end
//[cf]
//[of]:bottom pane
private func bottom pane (m: paned box)

	def n = number of pages (m) - 1
	def p = first child (m)
	while n <> 0
		p = next sibling (p)
		-- n
	end
	return p

end
//[cf]
//[c]
//[of]:left min width
private func left min width (m: paned box)

	def n = number of pages (m) - 1
	def w = 0
	def p = first child (m)
	while n > 0
		w = max (w, min width (p))
		-- n
		p = next sibling (p)
	end

	return w

end
//[cf]
//[of]:left min height
private func left min height (m: paned box)

	def n = number of pages (m) - 1
	def h = (n - 1) * sep size
	def p = first child (m)
	while n > 0
		h += min height (p)
		-- n
		p = next sibling (p)
	end

	return h

end
//[cf]
//[of]:left width
private func left width (m: paned box)

	def min = left min width (m)
	def w = w (client rect (m))
	
	return max (min, w / 3)

end
//[cf]
//[of]:right width
private func right width (m: paned box)

	return width (client rect (m)) - left width (m) - sep size

end
//[cf]
//[of]:right pane
private equ right pane (m: paned box) = bottom pane (m)
//[cf]
//[cf]
//[cf]
//[of]:paned box class
//[of]:type
public struct paned box class : local container box class
end
//[cf]
//[of]:paned box class
public func paned box class

	def c = the paned box class
	if ~ initialized
		initialized = true
		c . copy (container box class)
		c . adjust = ^actual adjust (paned box)
		c . compute min size = ^actual compute min size (paned box)
		c . accept focus = ^yes (box)
		c . on size = ^handle size (paned box)
		c . on paint = ^handle paint (paned box, canvas, rectangle)
		c . on focus = ^handle focus (paned box, event)
		c . on child event = ^handle child event (paned box, box, event)
	end
	return c

end

private def initialized = false
private def the paned box class: local paned box class
//[cf]
//[cf]

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -