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

📄 box.zc

📁 实现树形结构
💻 ZC
📖 第 1 页 / 共 4 页
字号:
//[of]:description
//[c]The base object for the user interface
//[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"
import "base/memory-allocator"
import "collection/linked-collection"
import "text/string"
import "text/string-buffer"
import "text/vector-of-strings"
import "net/uri"
import "file/file"
//[c]
import "graphics/geometry"
import "graphics/graphics"
import "toolbox/clipboard"
import "toolbox/timer"
import "user/keyboard"
import "user/command"
//[c]
import "glib/glib"
import "glib/glib-object"
import "gdk/gdk"
import "gtk/gtk"
import "private/boot"
import "private/sys-graphics"
import "private/sys-command"
//[cf]
//[c]
//[of]:GTK+
//[of]:description
//[c]This part contains GTK+ specific code.
//[c]
//[c]The definitions of this part must only be used by the GTK+ specific
//[c]components.
//[cf]
//[of]:sys drop file event
public struct sys drop files event
	list : local vector of strings
end
//[cf]
//[of]:sys box class
//[c]
public struct sys box class
	activate: {box} void
	set focus: {box} void
	set read only: {box, bool} void
	is read only: {box} bool
	set enable: {box, bool} void
end
//[cf]
//[of]:sys box
//[of]:type
public struct sys box
	widget: GtkWidget
	key mask: dword
	cursor: cursor

	private visible : bool
	private enabled : bool
	accept drop files: bool
	activated: bool
	read only: bool
	private input method: GtkIMContext
	private right pressed : bool
end
//[cf]
//[c]
//[of]:signal functions
//[of]:connect (event, function)
public func connect (m: box, event: [] gchar, function: -> void)

	return g_signal_connect(
		widget (m), 
		event, 
		function:GCallback, 
		m)

end
//[cf]
//[of]:disconnect (handler)
public func disconnect (m: box, handler: gulong)

	g_signal_handler_disconnect (widget (m), handler)

end
//[cf]
//[cf]
//[of]:event handling
//[of]:commit (input method, string, box)
//[c]Recieved an UTF-8 string
//[c]
func commit (im: GtkIMContext, s: string, m: box)

	def bytes: [1] gsize
	def p = from UTF8 (s, -1, bytes)
	def n = bytes[0]
	while n > 0:gsize
		def c = p++[]
		def ec : local char event
		type (ec) = char event type
		char code (ec) = c
		status (ec) = 0
		on char (m, ec)
		n -= 1:gsize
	end

end
//[cf]
//[of]:key press event (widget, event, box)
//[c]A key has been pressed
//[c]
public func key press event (w: GtkWidget, ev: GdkEventKey, m: box)

	// Hack - GTK+ sends the event to the toplevel first
	// this step force ignoring event by SWIFT
	if parent (m) == nil
		def handled = gtk_window_propagate_key_event (w : GtkWindow, ev)
		if handled == FALSE
			gtk_window_activate_key (w : GtkWindow, ev)
		end
		return TRUE
	end
	if gtk_widget_is_focus (w) == FALSE
		return FALSE
	end

	def k = keyval (ev) : int
	def e : local key event
	type (e) = key down event type
	status (e) = get key state (state (ev))
	if k == GDK_ISO_Left_Tab
		k = VK TAB
	end
	if k >= $a:int && k <= $z:int
		key (e) = k - 32
	else
		key (e) = k
	end
	def processed = on key down (m, e)

	def uc = gdk_keyval_to_unicode (k)

	// some key have several codes
	switch k
	case VK LCONTROL, VK RCONTROL
		k = VK CONTROL
	case VK LSHIFT, VK RSHIFT
		k = VK SHIFT
	case VK LMENU, VK RMENU
		k = VK MENU
	else
		k = 0
	end
	if k <> 0
		key (e) = k
		processed |= on key down (m, e)
	end

	if ~ processed
		// Create the input method multicontext on demand in order
		// to create useless objects
		def im = input method (m)
		if is nil (im)
			im = gtk_im_multicontext_new
			input method (m) = im
			g_signal_connect (
				im, 
				"commit", 
				^commit (GtkIMContext, string, box): GCallback, 
				m)
			gtk_im_context_set_client_window(im, gtk_widget_get_window(w))
		end		
		gtk_im_context_filter_keypress(im, ev)
	end
	
	return bool to gboolean (processed)

end
//[cf]
//[of]:key release event (widget, event, box)
//[c]A key has been released
//[c]
public func key release event (w: GtkWidget, ev: GdkEventKey, m: box)

	// hack - gtk sends the event to the toplevel first
	// this step force ignoring event
	if gtk_widget_is_focus (w) == FALSE
		return FALSE
	end
	
	def e : local key event
	def k = keyval (ev) : int
	type (e) = key up event type
	status (e) = get key state (state (ev))
	key (e) = k

	def processed = on key up (m, e)
	
	// some key have several codes
	switch k
	case VK LCONTROL, VK RCONTROL
		k = VK CONTROL
	case VK LSHIFT, VK RSHIFT
		k = VK SHIFT
	case VK LMENU, VK RMENU
		k = VK MENU
	else
		k = 0
	end
	if k <> 0
		key (e) = k
		processed |= on key up (m, e)
	end

	return bool to gboolean (processed)

end
//[cf]
//[of]:focus in event (widget, event, box)
//[c]The control has gained the focus
//[c]
public func focus in event (w: GtkWidget, e: GdkEventFocus, m: box)
//[c]
//[c]	The clipboards needs to be updated: update now.
//[c]	"update targets" re-enters the message loop, that's why it can not be 
//[c]	invoked from anywhere. The destroy event could be handled at an
//[c]	unexpected location, resulting operation on destroyed widgets.
//[c]
//[c]	The "clipboard need update" is set when the window is reactivated
//[c]	(see in frame.zc).
//[c]
	if clipboard need update
		update targets
		clipboard need update = false
	end
//[c]
//[c]	GTK+ sometimes restore focus on an hidden control (notebook)
//[c]	Check visibility first.
//[c]
	if ~ is visible (m)
		return FALSE
	end
//[c]
	return bool to gboolean (on focus (m))

end
//[cf]
//[of]:focus out event (widget, event, box)
//[c]The control has lost the focus
//[c]
public func focus out event (w: GtkWidget, e: GdkEventFocus, m: box)
	return bool to gboolean (on blur (m))
end
//[cf]
//[of]:button press event (widget, event, box)
//[c]A button has been pressed
//[c]
public  func button press event (
		w: GtkWidget, 
		ev: GdkEventButton, 
		m: box)

	def b = gdk_event_button_button (ev)
	if b >= 1 && b < 4
		def e: local mouse button event
		button (e) = (
			(b == 1) -> left mouse button, 
			(b == 3) -> right mouse button,
			middle mouse button)

		status (e) = get key state (state (ev))
		x (position (e)) = max (0, gdk_event_button_get_x (ev))
		y (position (e)) = max (0, gdk_event_button_get_y (ev))
	
		if type (ev) == GDK_2BUTTON_PRESS
			type (e) = mouse double click event type
			return bool to gboolean (on mouse double click (m, e))
		else
			type (e) = mouse down event type
			right pressed (m) = (button (e) == right mouse button)
			return bool to gboolean (on mouse down (m, e))
		end
	end

	return FALSE
end
//[cf]
//[of]:button release event (widget, event, box)
//[c]A button has been released
//[c]
public func button release event (
		w: GtkWidget, 
		ev: GdkEventButton, 
		m: box)

	def b = gdk_event_button_button (ev)
	if b >= 1 && b < 4
		def e: local mouse button event
		type (e) = mouse up event type
		button (e) = (
			(b == 1) -> left mouse button, 
			(b == 3) -> right mouse button,
			middle mouse button)

		status (e) = get key state (state (ev))
		x (position (e)) = max (0, gdk_event_button_get_x (ev))
		y (position (e)) = max (0, gdk_event_button_get_y (ev))
		def processed = on mouse up (m, e)

		// Right click -> simulate a popup menu
		if ~ processed && button (e) == right mouse button && right pressed (m)
			right pressed (m) = false
			processed = popup menu (m, position (e))
		end
		
		return bool to gboolean (processed)
	end
	
	return FALSE

end
//[cf]
//[of]:destroy (widget, box)
//[c]
private func destroy (widget: GtkWidget, m: box)

	// the widget pointer is cleared
	widget (m) = nil

	return FALSE

end
//[cf]
//[of]:size allocate (widget, allocation, box)
private func size allocate (w: GtkWidget, a: GtkAllocation, m: box)

	def r = client rect (m)
	x (r) = 0
	y (r) = 0
	w (r) = width (a)
	h (r) = height (a)
	
	on size (m)

end
//[cf]
//[of]:drag data received (widget, ...)
//[c]
private func drag data received (
		w: GtkWidget,
		context: GdkDragContext,
		x: gint,
		y: gint,
		selection data: GtkSelectionData,
		info: guint,
		time: guint,
		m: box)

	def uri : local uri
	def e : local drop files event
	def list = list (e)
	initialize (list, 8)

	def p = data (selection data) : string
	repeat
		def c = p []
		if is nul (c)
			break
		end

		// read line
		def t := temp string buffer
		repeat
			c = p []
			if is nul (c)
				break
			end
			++ p
			if c == \r
				if p[] == \n
					++p
				end
				break
			end
			if c == \n
				break
			end
			t << c
		end
		
		// convert string to an uri
		initialize (uri, as string (t))
		release (t)
		if is equal (scheme (uri), "file")
			def u := convert uri to filename (uri)
			def filename = new string (u)
			add (list, filename)
			release (u)
		end
		release (uri)
	end
	
	if size (list) > 0
		on drop files (m, e)
	end
	
	// delete the list		
	each (list) ? s
		delete (s)
	end
	release (list)		
	
end
//[cf]
//[of]:popup menu (widget, win box)
//[c]
private func popup menu (widget: GtkWidget, m: box)

	def pt: local point
	x (pt) = 0
	y (pt) = 0

	return popup menu (m, pt)

end
//[cf]
//[cf]
//[of]:private
//[of]:globals
//[c]
//[c]The box being created.
//[c]Used during initialization of a window before the userdata is set
//[c]
private def box being created = nil: box
//[cf]
//[c]
//[of]:insert child (box)
//[c]
private func insert child (parent: box, child: box)

	parent (child) = parent
	next sibling (child) = nil
	prev sibling (child) = last child (parent)
	
	// update the head of the list
	if is nil (first child (parent))
		first child (parent) = child
	end
	
	// update successor
	def last = last child (parent)
	if not nil (last)
		next sibling (last) = child
	end

	// update the tail of the list
	last child (parent) = child

end
//[cf]
//[of]:remove child (box)
//[c]Removes a child box
//[c]
private func remove child (parent: box, child: box)

	if first child (parent) == child
		first child (parent) = next sibling (child)
	end
	
	if last child (parent) == child
		last child (parent) = prev sibling (child)
	end

	if not nil (prev sibling (child))
		next sibling (prev sibling (child)) = next sibling (child)
	end

	if not nil (next sibling (child))
		prev sibling (next sibling (child)) = prev sibling (child)
	end

	next sibling (child) = nil
	prev sibling (child) = nil
	parent (child) = nil

end
//[cf]
//[cf]
//[c]
//[of]:activate
public func activate (m: box)

	if ~ activated (m)
		activate (class (m)) {m}
		activated (m) = true
	end

end
//[cf]
//[of]:actual set focus
//[c]
public func actual set focus (m: box)

	if can get focus (m)
		// if the control seems to accept focus, call the windows
		// API to transfer actually the focus to the control
		gtk_widget_grab_focus (widget (m))
	else
		// the control does not accept the focus, transfer the
		// focus to the next valid control.
		transfer focus (m, false)
	end

end
//[cf]
//[of]:actual set enable (bool)
//[c]
public func actual set enable (m: box, en: bool)

	// exit if unchanged
	if enabled (m) == en
		return
	end
	
	def sensitive = en -> TRUE, FALSE
	gtk_widget_set_sensitive (widget (m), sensitive)
	
	enabled (m) = en

end
//[cf]
//[of]:actual is read only
public func actual is read only (m: box)
	return read only (m)
end

⌨️ 快捷键说明

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