📄 paned-box.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 + -