File: Menu.chs

package info (click to toggle)
haskell-gtk 0.11.0-5
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 2,920 kB
  • ctags: 82
  • sloc: haskell: 1,929; ansic: 714; sh: 5; makefile: 3
file content (498 lines) | stat: -rw-r--r-- 15,438 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
{-# LANGUAGE CPP #-}
-- -*-haskell-*-
--  GIMP Toolkit (GTK) Widget Menu
--
--  Author : Axel Simon
--
--  Created: 21 May 2001
--
--  Copyright (C) 1999-2005 Axel Simon
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2.1 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Lesser General Public License for more details.
--
-- TODO
--
-- The following not bound functions might be useful:
--   menuSetAccelGroup, menuSetAccelGroup, menuReposition
--
-- The function menuPopup at a specific position is difficult to bind:
--   The callback function that determines at which position the menu is
--   to be shown is keept after the call returns. Maybe we could destroy
--   this function pointer with a destory event?
--
-- |
-- Maintainer  : gtk2hs-users@lists.sourceforge.net
-- Stability   : provisional
-- Portability : portable (depends on GHC)
--
-- A menu widget
--
module Graphics.UI.Gtk.MenuComboToolbar.Menu (
-- * Detail
-- 
-- | A 'Menu' is a 'MenuShell' that implements a drop down menu consisting of
-- a list of 'MenuItem' objects which can be navigated and activated by the
-- user to perform application functions.
--
-- A 'Menu' is most commonly dropped down by activating a 'MenuItem' in a
-- 'MenuBar' or popped up by activating a 'MenuItem' in another 'Menu'.
--
-- A 'Menu' can also be popped up by activating a 'OptionMenu'. Other
-- composite widgets such as the 'Notebook' can pop up a 'Menu' as well.
--
-- Applications can display a 'Menu' as a popup menu by calling the
-- 'menuPopup' function.

-- * Class Hierarchy
-- |
-- @
-- |  'GObject'
-- |   +----'Object'
-- |         +----'Widget'
-- |               +----'Container'
-- |                     +----'MenuShell'
-- |                           +----Menu
-- @

-- * Types
  Menu,
  MenuClass,
  castToMenu, gTypeMenu,
  toMenu,

-- * Constructors
  menuNew,

-- * Methods
  menuReorderChild,
  menuPopup,
  menuSetAccelGroup,
  menuGetAccelGroup,
  menuSetAccelPath,
  menuSetTitle,
  menuGetTitle,
  menuPopdown,
  menuReposition,
  menuGetActive,
  menuSetActive,
  menuSetTearoffState,
  menuGetTearoffState,
  menuAttachToWidget,
  menuDetach,
  menuGetAttachWidget,
#if GTK_CHECK_VERSION(2,2,0)
  menuSetScreen,
#endif
#if GTK_CHECK_VERSION(2,4,0)
  menuSetMonitor,
  menuAttach,
#endif
#if GTK_CHECK_VERSION(2,6,0)
  menuGetForAttachWidget,
#endif

-- * Attributes
#if GTK_CHECK_VERSION(2,6,0)
  menuTearoffState,
#endif
  menuAccelGroup,
  menuActive,
  menuTitle,

-- * Child Attributes
  menuChildLeftAttach,
  menuChildRightAttach,
  menuChildTopAttach,
  menuChildBottomAttach,
  ) where

import Control.Monad	(liftM)
import Data.Maybe  (fromMaybe)

import System.Glib.FFI
import System.Glib.UTFString
import System.Glib.GList
import System.Glib.Attributes
import System.Glib.Properties
import System.Glib.GObject		(makeNewGObject)
import Graphics.UI.Gtk.Abstract.Object	(makeNewObject)
{#import Graphics.UI.Gtk.Types#}
import Graphics.UI.Gtk.Abstract.ContainerChildProperties
import Graphics.UI.Gtk.Gdk.Events (MouseButton, TimeStamp)

{# context lib="gtk" prefix="gtk" #}

--------------------
-- Constructors

-- | Creates a new 'Menu'.
--
menuNew :: IO Menu
menuNew =
  makeNewObject mkMenu $
  liftM (castPtr :: Ptr Widget -> Ptr Menu) $
  {# call unsafe menu_new #}

--------------------
-- Methods

-- | Moves a 'MenuItem' to a new position within the 'Menu'.
--
menuReorderChild :: (MenuClass self, MenuItemClass child) => self
 -> child -- ^ @child@ - the 'MenuItem' to move.
 -> Int   -- ^ @position@ - the new position to place @child@. Positions are
          -- numbered from 0 to n-1.
 -> IO ()
menuReorderChild self child position =
  {# call menu_reorder_child #}
    (toMenu self)
    (toWidget child)
    (fromIntegral position)

-- | Popup a context menu where a button press occurred. 
--
-- * This function must be called in response to a button click. It opens
--   the given menu at a place determined by the last emitted event (hence
--   the requirement that this function is called as response to a button
--   press signal).
--
menuPopup :: MenuClass self => self -- ^ The menu to be shown.
  -> Maybe (MouseButton, TimeStamp)
  -- ^ The mouse button returned by 'Graphics.UI.Gtk.Gdk.EventM.eventButton' and
  -- the time of the event returned by 'Graphics.UI.Gtk.Gdk.eventTime'. These
  -- values are used to match the corresponding release of the button. If this
  -- context menu is shown by programmatic means, supply @Nothing@.
  -> IO ()
menuPopup self (Just (b,t)) =
  {# call menu_popup #}
    (toMenu self)
    (Widget nullForeignPtr)
    (Widget nullForeignPtr)
    nullFunPtr
    nullPtr
    ((fromIntegral . fromEnum) b)
    (fromIntegral t)
menuPopup self Nothing = do
  t <- {# call unsafe get_current_event_time #}
  {# call menu_popup #}
    (toMenu self)
    (Widget nullForeignPtr)
    (Widget nullForeignPtr)
    nullFunPtr nullPtr 0 t

-- | Set the 'AccelGroup' which holds global accelerators for the menu. This
-- accelerator group needs to also be added to all windows that this menu is
-- being used in with 'windowAddAccelGroup', in order for those windows to
-- support all the accelerators contained in this group.
--
menuSetAccelGroup :: MenuClass self => self
 -> AccelGroup -- ^ @accelGroup@ - the 'AccelGroup' to be associated with the
               -- menu.
 -> IO ()
menuSetAccelGroup self accelGroup =
  {# call menu_set_accel_group #}
    (toMenu self)
    accelGroup

-- | Gets the 'AccelGroup' which holds global accelerators for the menu. See
-- 'menuSetAccelGroup'.
--
menuGetAccelGroup :: MenuClass self => self
 -> IO AccelGroup -- ^ returns the 'AccelGroup' associated with the menu.
menuGetAccelGroup self =
  makeNewGObject mkAccelGroup $
  {# call unsafe menu_get_accel_group #}
    (toMenu self)

-- | Sets an accelerator path for this menu from which accelerator paths for
-- its immediate children, its menu items, can be constructed. The main purpose
-- of this function is to spare the programmer the inconvenience of having to
-- call 'menuItemSetAccelPath' on each menu item that should support runtime
-- user changable accelerators. Instead, by just calling 'menuSetAccelPath' on
-- their parent, each menu item of this menu, that contains a label describing
-- its purpose, automatically gets an accel path assigned.
--
-- For example, a menu containing menu items \"New\" and \"Exit\", will, after
-- calling
--
-- > menu `menuSetAccelPath` "<Gnumeric-Sheet>/File"
--
-- assign its items the accel paths: @\"\<Gnumeric-Sheet\>\/File\/New\"@ and
-- @\"\<Gnumeric-Sheet\>\/File\/Exit\"@.
--
-- Assigning accel paths to menu items then enables the user to change their
-- accelerators at runtime. More details about accelerator paths and their
-- default setups can be found at 'accelMapAddEntry'.
--
menuSetAccelPath :: MenuClass self => self
 -> String -- ^ @accelPath@ - a valid accelerator path
 -> IO ()
menuSetAccelPath self accelPath =
  withUTFString accelPath $ \accelPathPtr ->
  {# call menu_set_accel_path #}
    (toMenu self)
    accelPathPtr

-- | Sets the title string for the menu. The title is displayed when the menu
-- is shown as a tearoff menu.
--
menuSetTitle :: MenuClass self => self -> String -> IO ()
menuSetTitle self title =
  withUTFString title $ \titlePtr ->
  {# call unsafe menu_set_title #}
    (toMenu self)
    titlePtr

-- | Returns the title of the menu. See 'menuSetTitle'.
--
menuGetTitle :: MenuClass self => self
 -> IO (Maybe String) -- ^ returns the title of the menu, or @Nothing@ if the
                      -- menu has no title set on it.
menuGetTitle self =
  {# call unsafe menu_get_title #}
    (toMenu self)
  >>= maybePeek peekUTFString

-- | Removes the menu from the screen.
--
menuPopdown :: MenuClass self => self -> IO ()
menuPopdown self =
  {# call menu_popdown #}
    (toMenu self)

-- | Repositions the menu according to its position function.
--
menuReposition :: MenuClass self => self -> IO ()
menuReposition self =
  {# call menu_reposition #}
    (toMenu self)

-- | Returns the selected menu item from the menu. This is used by the
-- 'OptionMenu'.
--
menuGetActive :: MenuClass self => self
 -> IO MenuItem -- ^ returns the 'MenuItem' that was last selected in the menu.
                -- If a selection has not yet been made, the first menu item is
                -- selected.
menuGetActive self =
  makeNewObject mkMenuItem $
  throwIfNull "menuGetActive: menu contains no menu items." $
  liftM castPtr $
  {# call menu_get_active #}
    (toMenu self)

-- | Selects the specified menu item within the menu. This is used by the
-- 'OptionMenu' and should not be used by anyone else.
--
menuSetActive :: MenuClass self => self
 -> Int   -- ^ @index@ - the index of the menu item to select. Index values
          -- are from 0 to n-1.
 -> IO ()
menuSetActive self index =
  {# call menu_set_active #}
    (toMenu self)
    (fromIntegral index)

-- | Changes the tearoff state of the menu. A menu is normally displayed as
-- drop down menu which persists as long as the menu is active. It can also be
-- displayed as a tearoff menu which persists until it is closed or reattached.
--
menuSetTearoffState :: MenuClass self => self
 -> Bool  -- ^ @tornOff@ - If @True@, menu is displayed as a tearoff menu.
 -> IO ()
menuSetTearoffState self tornOff =
  {# call menu_set_tearoff_state #}
    (toMenu self)
    (fromBool tornOff)

-- | Returns whether the menu is torn off. See 'menuSetTearoffState'.
--
menuGetTearoffState :: MenuClass self => self
 -> IO Bool -- ^ returns @True@ if the menu is currently torn off.
menuGetTearoffState self =
  liftM toBool $
  {# call unsafe menu_get_tearoff_state #}
    (toMenu self)

-- | Attach this menu to another widget.
--
menuAttachToWidget :: (MenuClass self, WidgetClass attachWidget) => self -> attachWidget -> IO ()
menuAttachToWidget self attachWidget =
  {# call menu_attach_to_widget #}
    (toMenu self)
    (toWidget attachWidget)
    nullFunPtr

-- | Detach this menu from the widget it is attached to.
--
menuDetach :: MenuClass self => self -> IO ()
menuDetach self =
  {# call menu_detach #}
    (toMenu self)

-- | Get the widget this menu is attached to. Returns Nothing if this is a
-- tearoff (context) menu.
--
menuGetAttachWidget :: MenuClass self => self -> IO (Maybe Widget)
menuGetAttachWidget self = do
  wPtr <- {#call unsafe menu_get_attach_widget#} (toMenu self)
  if wPtr==nullPtr then return Nothing else liftM Just $ 
    makeNewObject mkWidget (return wPtr)

#if GTK_CHECK_VERSION(2,2,0)
-- | Sets the 'Screen' on which the menu will be displayed.
--
-- * Available since Gtk+ version 2.2
--
menuSetScreen :: MenuClass self => self
 -> Maybe Screen -- ^ @screen@ - a 'Screen', or @Nothing@ if the screen should
                 -- be determined by the widget the menu is attached to.
 -> IO ()
menuSetScreen self screen =
  {# call menu_set_screen #}
    (toMenu self)
    (fromMaybe (Screen nullForeignPtr) screen)
#endif

#if GTK_CHECK_VERSION(2,4,0)
-- | Informs Gtk+ on which monitor a menu should be popped up. See
-- 'screenGetMonitorGeometry'.
--
-- * Available since Gtk+ version 2.4
--
menuSetMonitor :: MenuClass self => self
 -> Int   -- ^ @monitorNum@ - the number of the monitor on which the menu
          -- should be popped up
 -> IO ()
menuSetMonitor self monitorNum =
  {# call menu_set_monitor #}
    (toMenu self)
    (fromIntegral monitorNum)

-- | Adds a new 'MenuItem' to a (table) menu. The number of \'cells\' that an
-- item will occupy is specified by @leftAttach@, @rightAttach@, @topAttach@
-- and @bottomAttach@. These each represent the leftmost, rightmost, uppermost
-- and lower column and row numbers of the table. (Columns and rows are indexed
-- from zero).
--
-- Note that this function is not related to 'menuDetach'.
--
-- * Available since Gtk+ version 2.4
--
menuAttach :: (MenuClass self, MenuItemClass child) => self
 -> child -- ^ @child@ - a 'MenuItem'.
 -> Int   -- ^ @leftAttach@ - The column number to attach the left side of the
          -- item to.
 -> Int   -- ^ @rightAttach@ - The column number to attach the right side of
          -- the item to.
 -> Int   -- ^ @topAttach@ - The row number to attach the top of the item to.
 -> Int   -- ^ @bottomAttach@ - The row number to attach the bottom of the
          -- item to.
 -> IO ()
menuAttach self child leftAttach rightAttach topAttach bottomAttach =
  {# call gtk_menu_attach #}
    (toMenu self)
    (toWidget child)
    (fromIntegral leftAttach)
    (fromIntegral rightAttach)
    (fromIntegral topAttach)
    (fromIntegral bottomAttach)
#endif

#if GTK_CHECK_VERSION(2,6,0)
-- | Returns a list of the menus which are attached to this widget.
--
-- * Available since Gtk+ version 2.6
--
menuGetForAttachWidget :: WidgetClass widget => 
    widget                  -- ^ @widget@ - a 'Widget'
 -> IO [Menu]
menuGetForAttachWidget widget =
  {# call gtk_menu_get_for_attach_widget #}
    (toWidget widget)
  >>= fromGList
  >>= mapM (\elemPtr -> makeNewObject mkMenu (return elemPtr))
#endif

--------------------
-- Attributes

-- | A title that may be displayed by the window manager when this menu is
-- torn-off.
--
-- Default value: \"\"
--
menuTitle :: MenuClass self => Attr self String
menuTitle = newAttrFromStringProperty "tearoff-title"

#if GTK_CHECK_VERSION(2,6,0)
-- | A boolean that indicates whether the menu is torn-off.
--
-- Default value: @False@
--
menuTearoffState :: MenuClass self => Attr self Bool
menuTearoffState = newAttr
  menuGetTearoffState
  menuSetTearoffState
#endif

-- | \'accelGroup\' property. See 'menuGetAccelGroup' and 'menuSetAccelGroup'
--
menuAccelGroup :: MenuClass self => Attr self AccelGroup
menuAccelGroup = newAttr
  menuGetAccelGroup
  menuSetAccelGroup

-- | \'active\' property. See 'menuGetActive' and 'menuSetActive'
--
menuActive :: MenuClass self => ReadWriteAttr self MenuItem Int
menuActive = newAttr
  menuGetActive
  menuSetActive

--------------------
-- Child Attributes

-- | The column number to attach the left side of the child to.
--
-- Allowed values: >= -1
--
-- Default value: -1
--
menuChildLeftAttach :: (MenuClass self, WidgetClass child) => child -> Attr self Int
menuChildLeftAttach = newAttrFromContainerChildIntProperty "left-attach"

-- | The column number to attach the right side of the child to.
--
-- Allowed values: >= -1
--
-- Default value: -1
--
menuChildRightAttach :: (MenuClass self, WidgetClass child) => child -> Attr self Int
menuChildRightAttach = newAttrFromContainerChildIntProperty "right-attach"

-- | The row number to attach the top of the child to.
--
-- Allowed values: >= -1
--
-- Default value: -1
--
menuChildTopAttach :: (MenuClass self, WidgetClass child) => child -> Attr self Int
menuChildTopAttach = newAttrFromContainerChildIntProperty "top-attach"

-- | The row number to attach the bottom of the child to.
--
-- Allowed values: >= -1
--
-- Default value: -1
--
menuChildBottomAttach :: (MenuClass self, WidgetClass child) => child -> Attr self Int
menuChildBottomAttach = newAttrFromContainerChildIntProperty "bottom-attach"