summaryrefslogtreecommitdiff
path: root/files/practicum/Uitlijnen.icl
blob: 44bb8ac9e1fe82b11304ca51c1e698be8bd79826 (plain) (blame)
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
module Uitlijnen

import StdEnv, StdIO

//  Een aantal synomiem types:
::	UitlijnMode     :== Char
::  Tekst           :== String
::  Woord           :== String
::  Regel           :== String
::  TekstBreedte    :== Int
::  LetterBreedte   :== Int
::  Spatie			:== String   // De witruimte tussen twee woorden. Lengte > 0, en alle tekens zijn ' '.

//  UitlijnMode geeft de mogelijkheden weer van het algoritme.
Links				= 'l'
Centreren			= 'c'
Rechts				= 'r'
Uitlijnen			= 'u'

/*  uitlijnen is de functie die je zelf moet schrijven. 
    Argumenten:
        UitlijnMode:   hoe moet de uitvoer uitgelijnd worden (links, gecentreerd, rechts, of uitgelijnd)
        LetterBreedte: breedte van een letterteken (alle lettertekens zijn even breed)
        TekstBreedte:  breedte van het uitvoervenster
        Tekst:         de brontekst die uitgelijnd dient te worden.
    Uitvoer:
        [Regel]:       de lijst van regels die onder elkaar getekend worden. 
                       De lengte van alle regels moet gelijk zijn.
*/

uitlijnen :: UitlijnMode LetterBreedte TekstBreedte Tekst -> [Regel]
uitlijnen ...


/*  Vanaf hier volgt het voorgegeven deel van het programma dat een venster op je scherm
    tevoorschijn tovert. Dit deel hoef je niet te snappen. We nodigen je wel van harte uit
    om eens naar dit stuk functioneel programma te kijken als je nieuwsgierig bent hoe dat
    werkt.
    Uit gewoonte is de rest van dit programma in het Engels geschreven. 
*/

//  The data types used in the program:
::  FontInfo
 =  {   font    :: !Font
    ,   width   :: !Int
    ,   height  :: !Int
    }
::  State
 =  {   fontInfo:: !FontInfo
    ,   mode    :: !UitlijnMode
    ,   window  :: !Id
    }

/*  The text to be outlined. You can change this value to test your program. This example contains sufficient
    problems. ;-)
*/
text =: "In dit kleine verhaaltje komen korte woorden voor, zoals 'a', 'b', 'c' en 'd' maar ook " +++
        "exorbitant lange woorden zoals 'hottentottententententoonstellingexhibitieruimte'. "     +++
        "Je algoritme moet natuurlijk ook regels met zulke lange woorden aankunnen. "

Start :: *World -> *World
Start world
# (fontInfo,world)  = accScreenPicture (getFontInfo 8) world
# (windowId,world)  = openId world
# initialState      = {fontInfo=fontInfo,mode=Links,window=windowId}
= startIO SDI initialState initialiseGUI [ProcessClose closeProcess] world
where
//  initialiseGUI creates the window and menu of this interactive process.
    initialiseGUI :: (PSt State) -> PSt State
    initialiseGUI pst=:{ls=state}
    # (error,pst)	= openWindow undef wdef pst
    | error<>NoError= abort "Could not open the window."
    # (error,pst)	= openMenu   undef mdef pst
    | error<>NoError= abort "Could not open the menu."
    | otherwise		= pst
    where
    //  mdef defines the menu of the application.
        mdef        = Menu 
		                "&File"                                         // The menu title
		                (                                               // The menu elements
		                    SubMenu "Font&Size"
		                (   RadioMenu        [  (toString fsize,Nothing,Nothing,noLS (setFontSize fsize))
		                                     \\ fsize<-[8,10..30]
		                                     ]  0 []
		                )   []
		                :+: SubMenu "Mode"
		                (   RadioMenu        [  (toString mode,Nothing,Nothing,noLS (setMode mode))
		                                     \\ mode<-[Links,Centreren,Rechts,Uitlijnen]
		                                     ]  0 []
		                )   []
		                :+: MenuSeparator    []
		                :+: MenuItem "E&xit" [MenuShortKey 'q',MenuFunction (noLS closeProcess)]
		                )   []                                          // The menu has no attributes
        where
        //  setFontSize sets the new size of the current font and redraws everything.
            setFontSize :: Int (PSt State) -> PSt State
            setFontSize fsize pst=:{ls=state,io}
            # (maybe_info,io)   = accWindowPicture window (getFontInfo fsize) io
            | isNothing maybe_info
                = abort ("Could not retrieve font information of size "+++toString fsize)
            | otherwise
                # info		= fromJust maybe_info
                # state		= {state & fontInfo=fromJust maybe_info}
                # io		= appWindowPicture window (setPenFont info.font) io
                # io		= setWindowLook window True (False,look state) io
                = {pst & ls=state,io=io}
            where
                window      = state.window
        
        //  setMode sets the new UitlijnMode and redraws everything.
            setMode :: UitlijnMode (PSt State) -> PSt State
            setMode mode pst=:{ls=state,io}
            # state			= {state & mode=mode}
            # io			= setWindowLook window True (False,look state) io
            = {pst & ls=state,io=io}
            where
                window      = state.window

    
    //  wdef defines the window that displays the text.
        wdef		= Window
		                "Uitlijnen"                                     // The window title
		                NilLS                                           // The window contains no controls
		                [                                               // Window attributes:
		                    WindowClose    (noLS closeProcess)          // Closing the window terminates the program
		                ,   WindowLook     False (look state)           // The visible content of the window
		                ,   WindowId       state.window                 // The identification value of the window
		                ,   WindowInit     (noLS (appPIO (appWindowPicture state.window (setPenFont state.fontInfo.font))))
		                                                                // Set a non-proportional font
		                ,   WindowViewSize {w=300,h=300}
		                ]

//  getFontInfo retrieves the font metrics and non-proportional font.
    getFontInfo :: Int *Picture -> (FontInfo,*Picture)
    getFontInfo fsize picture
    # ((ok,font),picture)   = openFont {NonProportionalFontDef & fSize=fsize} picture
    | not ok
        = abort "Could not retrieve NonProportionalFontDef from screen picture"
    | otherwise
        # (metrics,picture) = getFontMetrics font picture
        = ({font=font,width=metrics.fMaxWidth,height=fontLineHeight metrics},picture)

//  look draws the visible content of the window.
    look :: State SelectState UpdateState *Picture -> *Picture
    look {fontInfo,mode} _ {oldFrame,newFrame} picture
    # picture		= unfill newFrame picture
    # picture		= setPenColour Red picture
    # picture		= drawAt {zero & x=framewidth/charwidth*charwidth} {zero & vy=frameheight} picture
    # picture		= setPenColour Black picture
    = seq [  drawAt {x=i*charwidth,y=y} line.[i]
          \\ line<-linedtext & y<-[lineheight,2*lineheight..], i<-[0..size line-1]
          ]  picture
    where
        linedtext   = uitlijnen mode charwidth framewidth text
        framesize   = rectangleSize newFrame
        framewidth  = framesize.w
        frameheight = framesize.h
        lineheight  = fontInfo.height
        charwidth   = fontInfo.width