From: Duncan C. <dun...@wo...> - 2007-11-10 18:17:58
|
Fri Nov 9 07:29:40 PST 2007 hth...@zo... * Tutorial_Port: The Layout Container (Chapter 6.3) addfile ./docs/tutorial/Tutorial_Port/Example_Code/GtkChap6-3.hs hunk ./docs/tutorial/Tutorial_Port/Example_Code/GtkChap6-3.hs 1 +import Graphics.UI.Gtk + +main :: IO () +main = do + initGUI + window <- windowNew + set window [windowTitle := "Alphabet" , windowDefaultWidth := 350, + windowDefaultHeight := 350 , containerBorderWidth := 10] + sw <- scrolledWindowNew Nothing Nothing + set sw [scrolledWindowPlacement := CornerBottomRight, [_$_] + scrolledWindowShadowType := ShadowEtchedIn, + scrolledWindowHscrollbarPolicy := PolicyAutomatic, + scrolledWindowVscrollbarPolicy := PolicyAutomatic ] + containerAdd window sw + + layt <- layoutNew Nothing Nothing + layoutSetSize layt myLayoutWidth myLayoutHeight + widgetModifyBg layt StateNormal (Color 65535 65535 65535) + containerAdd sw layt [_$_] + [_$_] + upleft <- labelNew (Just "[_\e2_][_\80_][_\a1_](0,0)") + layoutPut layt upleft 0 0 + upright <- labelNew (Just ("[_\e2_][_\80_][_\a1_](" ++ (show (myLayoutWidth - 50)) ++",0)")) + layoutPut layt upright (myLayoutWidth -50) 0 + dwnright <- labelNew (Just ("[_\e2_][_\80_][_\a1_](0," ++ (show (myLayoutHeight -20)) ++ ")")) + layoutPut layt dwnright 0 (myLayoutHeight -20) + dwnleft <- labelNew (Just ("[_\e2_][_\80_][_\a1_](" ++ (show(myLayoutWidth -70)) ++ "," ++ + (show (myLayoutHeight -20)) ++ ")")) + layoutPut layt dwnleft (myLayoutWidth -70) (myLayoutHeight - 20) + [_$_] + labels <- sequence $ map (labelNew . Just) txtls + sequence_ $ map (\x -> widgetModifyFg x StateNormal (Color 0 0 45000)) labels + [_$_] + let wnums = zip labels [0..] + sequence_ $ map (myLayoutPut layt) wnums [_$_] + + widgetShowAll window + onDestroy window mainQuit + mainGUI + +-- parameters +myLayoutWidth :: Int +myLayoutWidth = 800 + +myLayoutHeight :: Int +myLayoutHeight = 800 + +txtls :: [String] +txtls = map (\x -> x:[]) ['A'..'Z'] +-- end parameters + +step :: Double +step = (2 * pi)/(fromIntegral (length txtls)) + +ox :: Int +ox = myLayoutWidth `div` 2 + +oy :: Int +oy = myLayoutHeight `div` 2 + +radius :: Double +radius = 0.25 * (fromIntegral ox) + +angle :: Int -> Double +angle num = 1.5 * pi + (fromIntegral num) * step + +num2x :: Int -> Int +num2x n = ox + relx where [_$_] + relx = round $ radius * (cos (angle n)) + +num2y :: Int -> Int +num2y n = oy + rely where + rely = round $ radius * (sin (angle n)) + +myLayoutPut :: Layout -> (Label, Int) -> IO () +myLayoutPut lt (lb, n) = do [_$_] + layoutPut lt lb (num2x n) (num2y n) [_$_] + labelSetAngle lb (letterAngle n) + +letterAngle :: Int -> Double +letterAngle n = (270 - degree) where + degree = (angle n) * (180.0 /pi) addfile ./docs/tutorial/Tutorial_Port/Images/GtkChap6-3.png binary ./docs/tutorial/Tutorial_Port/Images/GtkChap6-3.png hunk ./docs/tutorial/Tutorial_Port/chap6-2.xhtml 21 - <a href="chap6-2.xhtml">Next</a> + <a href="chap6-3.xhtml">Next</a> hunk ./docs/tutorial/Tutorial_Port/chap6-2.xhtml 258 - <br />6.3</span> + <br />The Layout Container</span> addfile ./docs/tutorial/Tutorial_Port/chap6-3.xhtml hunk ./docs/tutorial/Tutorial_Port/chap6-3.xhtml 1 +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + <head> + <meta http-equiv="Content-Type" + content="text/html; charset=utf-8" /> + <title>Gtk2Hs Tutorial: The Layout Container</title> + <link href="default.css" type="text/css" rel="stylesheet" /> + </head> + <body> + <div id="header"> + <h1>Gtk2Hs Tutorial</h1> + <span class="nav-previous"> + <a href="chap6-2.xhtml">Previous</a> + </span> + <span class="nav-home"> + <a href="index.xhtml">Home</a> + </span> + <span class="nav-next"> + <a href="chap6-4.xhtml">Next</a> + </span> + </div> + <h2>6.3 The Layout Container</h2> + <p>Until now packing of widgets has been done either through + sequencing in horizontal or vertical boxes, or in a table. You + can, however, also place widgets in any position you like, + using a [_$_] + <code>Fixed</code> or a [_$_] + <code>Layout</code> widget. Use of the [_$_] + <code>Fixed</code> container is not recommended, because it does + not resize well.</p> + <p>The Layout container is similar to the Fixed container + except that it implements an infinite (where infinity is less + than 2^32) scrolling area. The X window system has a limitation + where windows can be at most 32767 pixels wide or tall. The + Layout container gets around this by doing some + exotic stuff using window and bit gravities, so that you can + have smooth scrolling even when you have many child widgets in + your scrolling area. Since it is used in a scrolled window, the + disadvantages of the [_$_] + <code>Fixed</code> widget do not apply.</p> + <p>A Layout container is created using:</p> + <pre class="codebox">layoutNew :: Maybe Adjustment -> Maybe Adjustment -> IO Layout +</pre> + <p>As you can see, you can optionally specify the Adjustment + objects that the Layout widget will use for its scrolling.</p> + <p>You can add and move widgets in the Layout container using + the following two functions:</p> + <pre class="codebox">layoutPut :: (LayoutClass self, WidgetClass childWidget) +=> self -> childWidget -> Int -> Int -> IO () +layoutMove :: (LayoutClass self, WidgetClass childWidget) +=> self -> childWidget -> Int -> Int -> IO () [_$_] +</pre> + <p>The first argument is the x position, the second the y + position. The top left is (0,0), x grows from left to right, + and y from top to bottom.</p> + <p>The size of the [_$_] + <code>Layout</code> container can be set using the next + function:</p> + <pre class="codebox">layoutSetSize :: LayoutClass self => self -> Int -> Int -> IO () +</pre> + <p>The first argument is the width of the entire scrollable + area, the second the height.</p> + <p>In the example we place a list of labels, each with an upper + case letter of the alphabet, in a circle around a chosen + centre. The labels are positioned perpendicular to the radius + using the Gtk2Hs function:</p> + <pre class="codebox">labelSetAngle :: labelClass self => self -> Double -> IO () +</pre> + <p>The angle is in degrees, measured counterclockwise.</p> + <img src="Images/GtkChap6-3.png" alt="Alphabet" + id="imgGtkChap6-3" /> + <p>The layout widget is placed into a scrolled window with [_$_] + <code>containerAdd</code> because it is scrollable, and so does + not need a view port, as in Chapter 6.1. The labels are + positioned using angular coordinates, which are then + transformed into Cartesian coordinates with the Prelude [_$_] + <code>sin</code> and [_$_] + <code>cos</code> functions. These take radians as their + arguments (between 0 and (2 * pi)). Width and Height in the + example are parametrized, as is the list to be displayed. + Furthermore, in [_$_] + <code>main</code> the corners of the [_$_] + <code>Layout</code> are marked, so you can easily experiment with its + size, if you want. Note that the actual marker has been replaced with '+' here, because + the validator complained.</p> + <pre class="codebox">import Graphics.UI.Gtk + +main :: IO () +main = do + initGUI + window <- windowNew + set window [windowTitle := "Alphabet" , windowDefaultWidth := 350, + windowDefaultHeight := 350 , containerBorderWidth := 10] + sw <- scrolledWindowNew Nothing Nothing + set sw [scrolledWindowPlacement := CornerBottomRight, [_$_] + scrolledWindowShadowType := ShadowEtchedIn, + scrolledWindowHscrollbarPolicy := PolicyAutomatic, + scrolledWindowVscrollbarPolicy := PolicyAutomatic ] + containerAdd window sw + + layt <- layoutNew Nothing Nothing + layoutSetSize layt myLayoutWidth myLayoutHeight + widgetModifyBg layt StateNormal (Color 65535 65535 65535) + containerAdd sw layt [_$_] + [_$_] + upleft <- labelNew (Just "+(0,0)") + layoutPut layt upleft 0 0 + upright <- labelNew (Just ("+(" ++ (show (myLayoutWidth - 50)) ++",0)")) + layoutPut layt upright (myLayoutWidth -50) 0 + dwnright <- labelNew (Just ("+(0," ++ (show (myLayoutHeight -20)) ++ ")")) + layoutPut layt dwnright 0 (myLayoutHeight -20) + dwnleft <- labelNew (Just ("+(" ++ (show(myLayoutWidth -70)) ++ "," ++ + (show (myLayoutHeight -20)) ++ ")")) + layoutPut layt dwnleft (myLayoutWidth -70) (myLayoutHeight - 20) + [_$_] + labels <- sequence $ map (labelNew . Just) txtls + sequence_ $ map (\x -> widgetModifyFg x StateNormal (Color 0 0 45000)) labels + [_$_] + let wnums = zip labels [0..] + sequence_ $ map (myLayoutPut layt) wnums [_$_] + + widgetShowAll window + onDestroy window mainQuit + mainGUI + +-- parameters +myLayoutWidth :: Int +myLayoutWidth = 800 + +myLayoutHeight :: Int +myLayoutHeight = 800 + +txtls :: [String] +txtls = map (\x -> x:[]) ['A'..'Z'] +-- end parameters + +step :: Double +step = (2 * pi)/(fromIntegral (length txtls)) + +ox :: Int +ox = myLayoutWidth `div` 2 + +oy :: Int +oy = myLayoutHeight `div` 2 + +radius :: Double +radius = 0.25 * (fromIntegral ox) + +angle :: Int -> Double +angle num = 1.5 * pi + (fromIntegral num) * step + +num2x :: Int -> Int +num2x n = ox + relx where [_$_] + relx = round $ radius * (cos (angle n)) + +num2y :: Int -> Int +num2y n = oy + rely where + rely = round $ radius * (sin (angle n)) + +myLayoutPut :: Layout -> (Label, Int) -> IO () +myLayoutPut lt (lb, n) = do [_$_] + layoutPut lt lb (num2x n) (num2y n) [_$_] + labelSetAngle lb (letterAngle n) + +letterAngle :: Int -> Double +letterAngle n = (270 - degree) where + degree = (angle n) * (180.0 /pi) +</pre> + <div id="footer"> + <span class="nav-previous"> + <a href="chap6-1.xhtml">Previous</a> + <br />6.2 Event Boxes and Button Boxes</span> + <span class="nav-home"> + <a href="index.xhtml">Home</a> + </span> + <span class="nav-next"> + <a href="chap6-4.xhtml">Next</a> + <br />6.4</span> + </div> + </body> +</html> hunk ./docs/tutorial/Tutorial_Port/index.xhtml 98 + <li> + <a href="chap6-3.xhtml">6.3 The Layout Container</a> + </li> [_$_] |