menu.zc

来自「实现树形结构」· ZC 代码 · 共 835 行 · 第 1/2 页

ZC
835
字号
//[of]:new (i label command, recipient, components)
//[c]
//[c]DESCRIPTION
//[c]	Creates a command from a label command initializer structure.
//[c]	
//[c]ARGUMENTS
//[c]	i is a pointer to the structures describing the label.
//[c]	recipient is the object that will be passed to all commands defined in this menu.
//[c]	c is an array to store labels
//[c]
//[c]RETURN VALUE
//[c]	Returns a newly created popup object
//[c]
private func new (i: i label command, recipient: object, c: [] object)

	def cmd = new (cmd (i), recipient)
	c [label (i)] = cmd
	return cmd

end
//[cf]
//[cf]
//[cf]
//[c]
//[of]:popup
//[of]:show popup (menu, pos, box)
//[c]
public func show popup (menu: menu, pos: point, owner: box)

	def popup = popup menu (menu)
	def id = g_signal_connect (
		popup, 
		"deactivate", 
		^popup deactivated (GtkMenuShell, gpointer): GCallback, 
		nil)

	gtk_menu_popup (
		popup,
		nil, // menu shell
		nil, // menu item
		nil, // func
		nil, // data
		0,
		gtk_get_current_event_time)

	gtk_main
	g_signal_handler_disconnect (popup, id)

end
//[c]
private func popup deactivated (shell: GtkMenuShell, data: gpointer)
	gtk_main_quit
end
//[cf]
//[cf]
//[of]:searching
//[of]:menu (m, id)
//[c]Returns the first child with given id
//[c]
public func menu (m: menu, id: int)

	each (m) ? menu
		if id == id (menu)
			return menu
		end
	end

	return nil

end
//[cf]
//[cf]
//[of]:enumerating
//[of]:each (m)
//[c]Enumerates children
//[c]
public equ each (menu: menu)

	each (children (menu)) ? m
		yield (m:menu base)
	end

end
//[cf]
//[cf]
//[of]:adding - removing
//[of]:append menu (m, child menu)
//[c]
public func append menu (menu: menu, child: menu)

	add (children (menu), child)

	if is menu bar (menu)
		gtk_menu_shell_append (menu bar (menu), menu item (child))
	else
		gtk_menu_shell_append (popup menu (menu), menu item (child))
	end

end
//[cf]
//[of]:append menu (m, cmd)
//[c]
public func append menu (menu: menu, cmd: command)

	def item = new menu item (cmd, menu)
	add (children (menu), item)

	gtk_menu_shell_append (popup menu (menu), menu item (item))

	return item
end
//[cf]
//[of]:append separator (m)
//[c]
public func append separator (menu: menu)

	def s = new menu separator
	add (children (menu), s)

	gtk_menu_shell_append (popup menu (menu), widget (s))

end
//[cf]
//[c]
//[of]:remove menu (m, index)
//[c]
public func remove menu (m: menu, index: dword)

	delete (child (m, index))
	remove (children (m), index)

end
//[cf]
//[cf]
//[of]:accessing
//[of]:child (m, index)
//[c]
public func child (m: menu, index: dword)
	return children (m) [index] : menu base
end
//[cf]
//[of]:number of children (m)
//[c]
public func number of children (m: menu)
	return size (children (m))
end
//[cf]
//[cf]
//[cf]
//[c]
//[c]private:
//[of]:menu base
//[of]:instance creation
//[of]:delete (m)
//[c]
private func delete (m: menu base)
	if is menu (m)
		delete (m: menu)
	elsif is separator (m)
		delete (m: menu separator)
	else
		delete (m: menu item)
	end
end
//[cf]
//[cf]
//[cf]
//[of]:menu item
//[of]:instance creation
//[of]:new menu item (command, parent menu)
//[c]
private func new menu item (cmd: command, parent: menu)

	def item = allocate memory (sizeof local menu item): menu item
	id (item) = 0
	is menu (item) = false
	is separator (item) = false
	accel group (item) = nil
	cmd (item) = cmd
	parent (item) = parent
	caption (item) = nil
	update caption (item)
	
	// register the menu item as a listener on the command
	initialize (listener (item), item, ^command event (menu item, command, command event))
	add listener (cmd, listener (item))

	// Creates the gtk object
	def menu item = gtk_menu_item_new_with_mnemonic (to UTF8 (caption (item))) : GtkMenuItem
	gtk_widget_show (menu item)
	menu item (item) = menu item
	update enabling (item)

	g_signal_connect (
		menu item, 
		"activate",
		^activate (GtkMenuItem, menu item):GCallback,
		item : gpointer)

	g_signal_connect (
		menu item, 
		"destroy",
		^destroy (GtkMenuItem, menu item):GCallback,
		item : gpointer)

	return item

end
//[cf]
//[of]:delete (m)
//[c]
private func delete (item: menu item)

	def w = menu item (item)
	if not nil (w)
		gtk_widget_destroy (w)
	end

	remove listener (cmd (item), listener (item))
	if not nil (caption (item))
		delete (caption (item))
	end
	free memory (item)

end
//[cf]
//[cf]
//[of]:updating
//[of]:update caption (m)
//[c]Updates the caption of the menu
//[c]
private func update caption (item: menu item)

	def s = temp string buffer
	
	// compute the new string in the buffer
	append caption (caption (cmd (item)), s)

	// update only if there is no previous value or if the
	// new value differ from the previous one
	def old = caption (item)
	if is nil (old) || old <> as string (s)
		caption (item) = new string (s)
		if not nil (old)
			delete (old)
		end
	end

	release (s)

end
//[cf]
//[of]:update enabling (m)
//[c]Updates the enabling of the menu item
//[c]
private func update enabling (item: menu item)

	def en = bool to gboolean (is enabled (cmd (item)))
	gtk_widget_set_sensitive (menu item (item), en)

end
//[cf]
//[of]:command event (m, cmd)
//[c]Updates the menu according to the new state of the command.
//[c]
//[c]	The following properties may have changed:
//[c]	- caption
//[c]	- enabled
//[c]	- checked
//[c]
private func command event (item: menu item, cmd: command, event: command event)

	switch type (event)
	case command caption changed
		update caption (item)
	case command enabling changed
		update enabling (item)
	case command accelerator changed
		if not nil (accel group (item))
		
			def a = accelerator (event)
			def key = key (a)
			def flags = flags (a) : dword
			if key <> 0
				gtk_widget_remove_accelerator (
					menu item (item),
					accel group (item),
					key: guint,
					mask2 (flags))
			end
		
			a = accelerator (cmd)
			key = key (a)
			flags = flags (a) : dword
			if key <> 0
				gtk_widget_add_accelerator (
					menu item (item),
					"activate",
					accel group (item),
					key: guint,
					mask2 (flags),
					GTK_ACCEL_VISIBLE)
			end

		end
	end
	
	/*def flags = MF_BYCOMMAND | MF_STRING
	if ~ is enabled (cmd)
		flags |= MF_DISABLED | MF_GRAYED
	end
	if is checked (cmd)
		flags |= MF_CHECKED
	end

	ModifyMenuA (
		handle (peer (parent (item))),
		id (cmd):UINT,
		flags,
		id (cmd):UINT,
		caption (item))*/

end
//[c]
//[of]:mask (flags)
//[c]Registers a shortcut
//[c]
private func mask2 (flags: dword)

	def mask = 0
	if (flags & SHIFT) <> 0
		mask |= GDK_SHIFT_MASK : int
	end
	if (flags & CTRL) <> 0
		mask |= GDK_CONTROL_MASK : int
	end
	if (flags & ALT) <> 0
		mask |= GDK_MOD1_MASK : int
	end
	return mask : GdkModifierType

end
//[cf]
//[cf]
//[cf]
//[of]:event handling
//[of]:activate (GtkMenuItem, menu item)
//[c]
private func activate (w: GtkMenuItem, m: menu item)

	def cmd = cmd (m)
	run (cmd)

end
//[cf]
//[of]:destroy (GtkMenuItem, menu item)
//[c]
private func destroy (w: GtkMenuItem, m: menu item)

	menu item (m) = nil

end
//[cf]
//[cf]
//[cf]
//[of]:menu separator
//[of]:instance creation
//[of]:new menu separator
//[c]
private func new menu separator

	def s = allocate memory (sizeof local menu separator): menu separator
	id (s) = 0
	is menu (s) = false
	is separator (s) = true

	// Creates the gtk object
	def sep = gtk_separator_menu_item_new : GtkSeparatorMenuItem
	gtk_widget_show (sep)
	widget (s) = sep

	g_signal_connect (
		sep,
		"destroy",
		^destroy (GtkMenuItem, menu separator):GCallback,
		s: gpointer)

	return s

end
//[cf]
//[of]:delete (m)
//[c]
private func delete (s: menu separator)

	def w = widget (s)
	if not nil (w)
		gtk_widget_destroy (w)
	end

	free memory (s)

end
//[cf]
//[cf]
//[of]:event handling
//[of]:destroy (GtkMenuItem, menu separator)
//[c]
private func destroy (w: GtkMenuItem, m: menu separator)

	widget (m) = nil

end
//[cf]
//[cf]
//[cf]

⌨️ 快捷键说明

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