]> gitweb.factorcode.org Git - factor.git/commitdiff
graphical tutorial
authorSlava Pestov <slava@factorcode.org>
Mon, 18 Jul 2005 22:14:13 +0000 (22:14 +0000)
committerSlava Pestov <slava@factorcode.org>
Mon, 18 Jul 2005 22:14:13 +0000 (22:14 +0000)
library/ui/books.factor [new file with mode: 0644]
library/ui/borders.factor
library/ui/buttons.factor
library/ui/init-world.factor
library/ui/load.factor
library/ui/paint.factor
library/ui/scrolling.factor
library/ui/tutorial.factor [new file with mode: 0644]

diff --git a/library/ui/books.factor b/library/ui/books.factor
new file mode 100644 (file)
index 0000000..382bbc4
--- /dev/null
@@ -0,0 +1,53 @@
+! Copyright (C) 2005 Slava Pestov.
+! See http://factor.sf.net/license.txt for BSD license.
+IN: gadgets
+USING: generic kernel lists math matrices sequences ;
+
+TUPLE: book page ;
+
+C: book ( pages -- book )
+    <gadget> over set-delegate
+    0 over set-book-page
+    swap [ over add-gadget ] each ;
+
+M: book pref-dim ( book -- dim )
+    gadget-children { 0 0 0 } [ pref-dim vmax ] reduce ;
+
+M: book layout* ( book -- )
+    dup shape-dim over gadget-children [
+        f over set-gadget-visible?
+        { 0 0 0 } over set-shape-loc
+        set-gadget-dim
+    ] each-with
+    dup book-page swap gadget-children nth
+    t swap set-gadget-visible? ;
+
+: show-page ( n book -- )
+    [ gadget-children length rem ] keep
+    [ set-book-page ] keep relayout ;
+
+: first-page ( book -- )
+    0 swap show-page ;
+
+: prev-page ( book -- )
+    [ book-page 1 - ] keep show-page ;
+
+: next-page ( book -- )
+    [ book-page 1 + ] keep show-page ;
+
+: last-page ( book -- )
+    -1 swap show-page ;
+
+: book-buttons ( book -- gadget )
+    <line-shelf> swap [
+        [ "|<" first-page drop ]
+        [ "<" prev-page drop ]
+        [ ">" next-page drop ]
+        [ ">|" last-page drop ]
+    ] [
+        uncons swapd cons <button> over add-gadget
+    ] each-with ;
+
+: <book-browser> ( book -- gadget )
+    dup book-buttons <frame>
+    [ add-top ] keep [ add-center ] keep ;
index e19ac141976f626fa56a10661ee3bdbfcf70e8a8..3600e9edb42ed018fd6297c15baac40193989741 100644 (file)
@@ -11,9 +11,15 @@ C: border ( child delegate size -- border )
     [ set-delegate ] keep
     [ over [ add-gadget ] [ 2drop ] ifte ] keep ;
 
+: empty-border ( child -- border )
+    <gadget> { 5 5 0 } <border> ;
+
 : line-border ( child -- border )
     <etched-gadget> { 5 5 0 } <border> ;
 
+: bevel-border ( child -- border )
+    <bevel-gadget> { 5 5 0 } <border> ;
+
 : layout-border-loc ( border -- )
     dup border-size swap gadget-child set-shape-loc ;
 
index ac9375d83e508d85ebeb8c8dac74e060edb1a582..82cd7eac394f2ca57519893ad5bf64e69655394a 100644 (file)
@@ -43,4 +43,8 @@ sequences io sequences styles ;
     [ drop ] [ drag 1 ] set-action ;
 
 : <button> ( label quot -- button )
-    >r <label> line-border dup r> button-gestures ;
+    >r
+    <label> bevel-border
+    dup [ 216 216 216 ] background set-paint-prop
+    dup
+    r> button-gestures ;
index 109b92ec4d0135809a1bfdcbe023311580b44550..88a41fb7041ff2b2bd4967af4c4d0a46ab84ca8a 100644 (file)
@@ -17,7 +17,9 @@ SYMBOL: stack-display
         
         {{
             [[ background [ 255 255 255 ] ]]
-            [[ rollover-bg [ 255 255 204 ] ]]
+            [[ rollover-bg [ 216 216 255 ] ]]
+            [[ bevel-1 [ 160 160 160 ] ]]
+            [[ bevel-2 [ 216 216 216 ] ]]
             [[ foreground [ 0 0 0 ] ]]
             [[ reverse-video f ]]
             [[ font "Sans Serif" ]]
index 1971521e0f526bb5db14a4331ba78f691f7abbbb..f693bb6e10689a37db7ba83bc5e92791428ef2fd 100644 (file)
@@ -23,6 +23,8 @@ USING: kernel parser sequences io ;
     "/library/ui/incremental.factor"
     "/library/ui/panes.factor"
     "/library/ui/presentations.factor"
+    "/library/ui/books.factor"
+    "/library/ui/tutorial.factor"
     "/library/ui/init-world.factor"
     "/library/ui/ui.factor"
 ] [
index a95348a9a7c3baa3bf5c4189daa083869a10cad4..31f3021f06aa706d237a1cc9e3cbb951237e5d5c 100644 (file)
@@ -2,7 +2,7 @@
 ! See http://factor.sf.net/license.txt for BSD license.
 IN: gadgets
 USING: generic hashtables io kernel lists math matrices
-namespaces sdl sequences strings styles ;
+namespaces sdl sequences strings styles vectors ;
 
 SYMBOL: clip
 
@@ -62,7 +62,7 @@ GENERIC: draw-gadget* ( gadget -- )
         dup rollover paint-prop rollover-bg background ?
     ] ifte paint-prop ;
 
-! Paint properties
+! Pen paint properties
 SYMBOL: interior
 SYMBOL: boundary
 
@@ -78,6 +78,7 @@ TUPLE: solid ;
     >r x get y get r> dup shape-w swap shape-h
     >r pick + r> pick + ;
 
+! Solid pen
 M: solid draw-interior
     drop >r surface get r> [ rect>screen ] keep bg rgb boxColor ;
 
@@ -85,6 +86,7 @@ M: solid draw-boundary
     drop >r surface get r> [ rect>screen >r 1 - r> 1 - ] keep
     fg rgb rectangleColor ;
 
+! Gradient pen
 TUPLE: gradient vector from to ;
 
 : gradient-color ( gradient prop -- color )
@@ -116,6 +118,40 @@ M: gradient draw-interior ( gadget gradient -- )
     over gradient-vector { 1 0 0 } =
     [ horiz-gradient ] [ vert-gradient ] ifte ;
 
+! Bevel pen
+TUPLE: bevel width ;
+
+: x1/x2/y1 surface get pick pick >r 2unseq r> first swap ;
+: x1/x2/y2 surface get pick pick >r first r> 2unseq ;
+: x1/y1/y2 surface get pick pick >r 2unseq r> second ;
+: x2/y1/y2 surface get pick pick >r second r> 2unseq swapd ;
+
+SYMBOL: bevel-1
+SYMBOL: bevel-2
+
+: bevel-up ( gadget -- rgb )
+    dup reverse-video paint-prop bevel-1 bevel-2 ? paint-prop rgb ;
+
+: bevel-down ( gadget -- rgb )
+    dup reverse-video paint-prop bevel-2 bevel-1 ? paint-prop rgb ;
+
+: draw-bevel ( v1 v2 gadget -- )
+    [ >r x1/x2/y1 r> bevel-up   hlineColor ] keep
+    [ >r x1/x2/y2 r> bevel-down hlineColor ] keep
+    [ >r x1/y1/y2 r> bevel-up   vlineColor ] keep
+    [ >r x2/y1/y2 r> bevel-down vlineColor ] keep
+    3drop ;
+
+M: bevel draw-boundary ( gadget boundary -- )
+    #! Ugly code.
+    bevel-width [
+        [
+            >r x get y get 0 3vector over shape-dim over v+ r>
+            { 1 1 0 } n*v tuck v- { 1 1 0 } v- >r v+ r>
+            rot draw-bevel
+        ] 2keep
+    ] repeat drop ;
+
 M: gadget draw-gadget* ( gadget -- )
     dup
     dup interior paint-prop* draw-interior
@@ -126,3 +162,6 @@ M: gadget draw-gadget* ( gadget -- )
 
 : <etched-gadget> ( -- gadget )
     <plain-gadget> dup << solid f >> boundary set-paint-prop ;
+
+: <bevel-gadget> ( -- gadget )
+    <plain-gadget> dup << bevel f 2 >> boundary set-paint-prop ;
index 59714734dba066148056f47d76c321f7963a2bcd..db072359fbdaa9061e05880b56787d8efe5c9a04 100644 (file)
@@ -77,9 +77,9 @@ TUPLE: slider viewport thumb vector ;
     [ gadget-parent slider-motion ] [ drag 1 ] set-action ;
 
 : <thumb> ( -- thumb )
-    <plain-gadget>
+    <bevel-gadget>
     t over set-gadget-root?
-    dup gray background set-paint-prop
+    dup [ 192 192 192 ] background set-paint-prop
     dup thumb-actions ;
 
 : add-thumb ( thumb slider -- )
@@ -89,9 +89,10 @@ TUPLE: slider viewport thumb vector ;
     [ { 0 0 0 } slider-click ] [ button-down 1 ] set-action ;
 
 C: slider ( viewport vector -- slider )
+    <plain-gadget> over set-delegate
+    dup [ 128 128 128 ] background set-paint-prop
     [ set-slider-vector ] keep
     [ set-slider-viewport ] keep
-    f line-border over set-delegate
     <thumb> over add-thumb
     dup slider-actions ;
 
diff --git a/library/ui/tutorial.factor b/library/ui/tutorial.factor
new file mode 100644 (file)
index 0000000..6dd92ab
--- /dev/null
@@ -0,0 +1,323 @@
+IN: gadgets\r
+USING: generic kernel lists math matrices namespaces sdl\r
+sequences styles ;\r
+\r
+: <title> ( text -- gadget )\r
+    <label> dup 36 font-size set-paint-prop ;\r
+\r
+: <underline> ( -- gadget )\r
+    <gadget>\r
+    dup << gradient f { 1 0 0 } [ 64 64 64 ] [ 255 255 255 ] >> interior set-paint-prop\r
+    { 0 10 0 } over set-gadget-dim ;\r
+\r
+: <page> ( list -- gadget )\r
+    0 1 <pile>\r
+    over car <title> over add-gadget\r
+    <underline> over add-gadget\r
+    swap cdr [ <label> over add-gadget ] each\r
+    empty-border ;\r
+\r
+: tutorial-pages\r
+    [\r
+        [\r
+            "Factor: a dynamic language"\r
+            "This series of slides presents a quick overview of Factor."\r
+            ""\r
+            "Factor is interactive, which means you can test out the code"\r
+            "in this tutorial immediately."\r
+            ""\r
+            "http://factor.sourceforge.net"\r
+        ] [\r
+            "The view from 10,000 feet"\r
+            "- Everything is an object"\r
+            "- A word is a basic unit of code"\r
+            "- Words are identified by names, and organized in vocabularies"\r
+            "- Words pass parameters on the stack"\r
+            "- Code blocks can be passed as parameters to words"\r
+            "- Word definitions are very short with very high code reuse"\r
+        ] [\r
+            "Basic syntax"\r
+            "Factor code is made up of whitespace-speparated tokens."\r
+            "Here is a program that prints ``Hello world'':"\r
+            ""\r
+            "  \"hello world\" print"\r
+            ""\r
+            "The first token (\"hello world\") is a string."\r
+            "The second token (print) is a word."\r
+            "The string is pushed on the stack, and the print word prints it."\r
+        ] [\r
+            "The stack"\r
+            "- The stack is like a pile of papers."\r
+            "- You can ``push'' papers on the top of the pile,"\r
+            "  and ``pop'' papers from the top of the pile."\r
+            ""\r
+            "Here is another code example:"\r
+            ""\r
+            "  2 3 + ."\r
+            ""\r
+            "Try running it in the listener now."\r
+        ] [\r
+            "Postfix arithmetic"\r
+            "What happened when you ran it?"\r
+            ""\r
+            "The two numbers (2 3) are pushed on the stack."\r
+            "Then, the + word pops them and pushes the result (5)."\r
+            "Then, the . word prints this result."\r
+            ""\r
+            "This is called postfix arithmetic."\r
+            "Traditional arithmetic is called infix: 3 + (6 * 2)"\r
+            "Lets translate this into postfix: 3 6 2 * + ."\r
+        ] [\r
+            "Colon definitions"\r
+            "We can define new words in terms of existing words."\r
+            ""\r
+            "  : twice  2 * ;"\r
+            ""\r
+            "This defines a new word named ``twice'' that calls ``2 *''."\r
+            "Try the following in the listener:"\r
+            ""\r
+            "  3 twice twice ."\r
+            ""\r
+            "The result is the same as if you wrote:"\r
+            ""\r
+            "  3 2 * 2 * ."\r
+        ] [\r
+            "Stack effects"\r
+            "When we look at the definition of the ``twice'' word,"\r
+            "it is intuitively obvious that it takes one value from the stack,"\r
+            "and leaves one value behind. However, with more complex"\r
+            "definitions, it is better to document this so-called"\r
+            "``stack effect''."\r
+            ""\r
+            "A stack effect comment is written between ( and )."\r
+            "Factor ignores stack effect comments. Don't you!"\r
+            ""\r
+            "The stack effect of twice is ( x -- 2*x )."\r
+            "The stack effect of + is ( x y -- x+y )."\r
+            "The stack effect of . is ( object -- )."\r
+        ] [\r
+            "Shuffle words"\r
+            "The word ``twice'' we defined is useless."\r
+            "Let's try something more useful: squaring a number."\r
+            ""\r
+            "We want a word with stack effect ( n -- n*n )."\r
+            "However, we cannot use * by itself, since its stack effect"\r
+            "is ( x y -- x*y ); it expects two inputs."\r
+            ""\r
+            "However, we can use the word ``dup''. It has stack effect"\r
+            "( object -- object object ), and it does exactly what we"\r
+            "need. The ``dup'' word is known as a shuffle word."\r
+        ] [\r
+            "The squared word"\r
+            "Try entering the following word definition:"\r
+            ""\r
+            "  : squared ( n -- n*n ) dup * ;"\r
+            ""\r
+            "Shuffle words solve the problem where we need to compose"\r
+            "two words, but their stack effects do not ``fit''."\r
+            ""\r
+            "Some of the most commonly-used shuffle words:"\r
+            ""\r
+            "drop ( object -- )"\r
+            "swap ( obj1 obj2 -- obj2 obj1 )"\r
+            "over ( obj1 obj2 -- obj1 obj2 obj1 )"\r
+        ] [\r
+            "Another shuffle example"\r
+            "Now let us write a word that negates a number."\r
+            "Start by entering the following in the listener"\r
+            ""\r
+            "  0 10 - ."\r
+            ""\r
+            "It will print -10, as expected. Now notice that this the same as:"\r
+            ""\r
+            "  10 0 swap - ."\r
+            ""\r
+            "So indeed, we can factor out the definition ``0 swap -'':"\r
+            ""\r
+            "  : negate ( n -- -n ) 0 swap - ;"\r
+        ] [\r
+            "Seeing words"\r
+            "If you have entered every definition in this tutorial,"\r
+            "you will now have several new colon definitions:"\r
+            ""\r
+            "  twice"\r
+            "  squared"\r
+            "  negated"\r
+            ""\r
+            "You can look at previously-entered word definitions using 'see'."\r
+            "Try the following:"\r
+            ""\r
+            "  \ negated see"\r
+            ""\r
+            "Prefixing a word with \ pushes it on the stack, instead of"\r
+            "executing it. So the see word has stack effect ( word -- )."\r
+        ] [\r
+            "Booleans"\r
+            "In Factor, any object can be used as a truth value."\r
+            "- The f object is false."\r
+            "- Anything else is true."\r
+            ""\r
+            "Here is a word that outputs a boolean:"\r
+            ""\r
+            "  : negative? ( n -- ? ) 0 < ;"\r
+        ] [\r
+            "Branches"\r
+            "Now suppose we want to write a word that computes the"\r
+            "absolute value of a number; that is, if it is less than 0,"\r
+            "the number will be negated to yield a positive result."\r
+            ""\r
+            "  : absolute ( x -- |x| )"\r
+            "    dup negative? [ negated ] when ;"\r
+            ""\r
+            "It duplicates the top of the stack, since negative? pops it."\r
+            "Then if the top of the stack was found to be negative,"\r
+            "it is negated, yielding a postive result."\r
+        ] [\r
+            "More branches"\r
+            "On the previous slide, you saw the 'when' conditional:"\r
+            ""\r
+            "  ... condition ... [ ... code to run if true ... ] when"\r
+            ""\r
+            "Another commonly-used form is 'unless':"\r
+            ""\r
+            "  ... condition ... [ ... code to run if true ... ] unless"\r
+            ""\r
+            "The 'ifte' conditional takes action on both branches:"\r
+            ""\r
+            "  ... condition ... [ ... ] [ ... ] ifte"\r
+        ] [\r
+            "Combinators"\r
+            "ifte, when, unless are words that take lists of code as input."\r
+            ""\r
+            "Lists of code are called ``quotations''."\r
+            "Words that take quotations are called ``combinators''."\r
+            ""\r
+            "Another combinator is times ( n quot -- )."\r
+            "It calls a quotation n times."\r
+            ""\r
+            "Try this:"\r
+            ""\r
+            "  10 [ \"Hello combinators\" print ] times"\r
+        ] [\r
+            "Sequences"\r
+            "You have already seen strings, very briefly:"\r
+            ""\r
+            "  \"Hello world\""\r
+            ""\r
+            "Strings are part of a class of objects called sequences."\r
+            "Two other types of sequences you will use a lot are:"\r
+            ""\r
+            "  Lists: [ 1 3 \"hi\" 10 2 ]"\r
+            "  Vectors: { \"the\" [ \"quick\" \"brown\" ] \"fox\" }"\r
+            ""\r
+            "As you can see in the second example, lists and vectors"\r
+            "can contain any type of object, including other lists"\r
+            "and vectors."\r
+        ] [\r
+            "Sequences and combinators"\r
+            "A very useful combinator is each ( seq quot -- )."\r
+            "It calls a quotation with each element of the sequence in turn."\r
+            ""\r
+            "Try this:"\r
+            ""\r
+            "  [ 10 20 30 ] [ . ] each"\r
+            ""\r
+            "A closely-related combinator is map ( seq quot -- seq )."\r
+            "It also calls a quotation with each element."\r
+            "However, it then collects the outputs of the quotation"\r
+            "into a new sequence."\r
+            ""\r
+            "Try this:"\r
+            ""\r
+            "  [ 10 20 30 ] [ 3 + ] map ."\r
+            "==> [ 13 23 33 ]"\r
+        ] [\r
+            "Numbers - integers and ratios"\r
+            "Factor's supports arbitrary-precision integers and ratios."\r
+            ""\r
+            "Try the following:"\r
+            ""\r
+            "  : factorial ( n -- n! ) 0 <range> product ;"\r
+            "  100 factorial ."\r
+            ""\r
+            "  1 3 / 1 2 / + ."\r
+            "==> 5/6"\r
+            ""\r
+            "Rational numbers are added, multiplied and reduced to"\r
+            "lowest terms in the same way you learned in grade school."\r
+        ] [\r
+            "Numbers - higher math"\r
+            "  2 sqrt ."\r
+            "==> 1.414213562373095"\r
+            ""\r
+            "  -1 sqrt ."\r
+            "==> #{ 0 1.0 }#"\r
+            ""\r
+            "  M[ [ 10 3 ] [ 7 5 ] [ -2 0 ] ]M M[ [ 11 2 ] [ 4 8 ] ]M"\r
+            "==> M[ [ 122 44 ] [ 97 54 ] [ -22 -4 ] ]M"\r
+            ""\r
+            "... and there is much more."\r
+        ] [\r
+            "Object oriented programming"\r
+            "Each object belongs to a class."\r
+            "Generic words act differently based on an object's class."\r
+            ""\r
+            "  GENERIC: describe ( object -- )"\r
+            "  M: integer describe \"The integer \" write . ;"\r
+            "  M: string describe \"The string \" write . ;"\r
+            "  M: object describe drop \"Unknown object\" print ;"\r
+            ""\r
+            "Each M: line defines a ``method.''"\r
+            "Method definitions may appear in independent source files."\r
+            ""\r
+            "integer, string, object are built-in classes."\r
+        ] [\r
+            "Defining new classes with tuples"\r
+            "New classes can be defined:"\r
+            ""\r
+            "  TUPLE: point x y ;"\r
+            "  M: point describe"\r
+            "    \"x =\" write dup point-x ."\r
+            "    \"y =\" write point-y . ;"\r
+            "  100 200 <point> describe"\r
+            ""\r
+            "A tuple is a collection of named slots."\r
+            ""\r
+            "Tuples support custom constructors, delegation..."\r
+            "see the developer's handbook for details."\r
+        ] [\r
+            "The library"\r
+            "Offers a good selection of highly-reusable words:"\r
+            "- Operations on sequences"\r
+            "- Variety of mathematical functions"\r
+            "- Web server and web application framework"\r
+            "- Graphical user interface framework"\r
+            "Browsing the library:"\r
+            "- To list all vocabularies:"\r
+            "  vocabs ."\r
+            "- To list all words in a vocabulary:"\r
+            "  \"sequences\" words ."\r
+            "- To show a word definition:"\r
+            "  \ reverse see"\r
+        ] [\r
+            "Learning more"\r
+            "Hopefully this tutorial has sparked your interest in Factor."\r
+            ""\r
+            "You can learn more by reading the Factor developer's handbook:"\r
+            ""\r
+            "http://factor.sourceforge.net/handbook.pdf"\r
+            ""\r
+            "Also, point your IRC client to irc.freenode.net and hop in the"\r
+            "#concatenative channel to chat with other Factor geeks."\r
+        ]\r
+    ] ;\r
+\r
+: <tutorial> ( pages -- browser )\r
+    tutorial-pages [ <page> ] map <book>\r
+    dup [ 204 204 255 ] background set-paint-prop\r
+    dup << gradient f { 0 1 0 } [ 204 204 255 ] [ 255 204 255 ] >> interior set-paint-prop\r
+    dup "Sans Serif" font set-paint-prop\r
+    dup 18 font-size set-paint-prop\r
+    <book-browser> ;\r
+\r
+: tutorial <tutorial> gadget. ;\r