Why The Roman Empire Fell

Historians tell us that the Roman Empire failed for many reasons, yet I haven't seen the real reason explained properly.  Quite simply, an organisation the size of Ancient Rome needs an immense amount of organisation which needs calculation and the abacus just doesn't cut it.  What the Roman Empire needed, but didn't have, was the pocket calculator.

With the aid of Dyalog APL and Microsoft's WPF/XAML framework I've been able to explore what might have been...



Defining the Form

The form is defined by this XAML file, initially built with Visual Basic then hand-crafted into its final form.

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Computus" Height="212" Width="621" FontFamily="Felix Titling" FontSize="14" FontWeight="Bold" Background="#FFDB9730"
      Icon="d:/dick/mycode/dyalog121/apps/dogcalc/APLKEYS.ICO">
       <Window.Resources >
        <Style x:Key="DogButton" TargetType="Button" >
         <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid>
                            <Ellipse Fill="{TemplateBinding Background}"
                             Stroke="{TemplateBinding BorderBrush}"/>
                            <ContentPresenter HorizontalAlignment="Center"
                                          VerticalAlignment="Center"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Background" Value="Gold" />
            <Setter Property="Margin" Value="5" />
            <Setter Property="Height" Value="50" />
            <Setter Property="Width" Value="75" />
        </Style>
        </Window.Resources>
    <Grid Height="205" Width="746">
        <Label Height="37" HorizontalAlignment="Left" Name="LabelDisplay" VerticalAlignment="Top" Width="610" Background="Yellow" FontWeight="Normal" VerticalContentAlignment="Center" />
        <StackPanel Height="63" HorizontalAlignment="Left" Margin="0,43,0,0" Name="StackPanel1" VerticalAlignment="Top" Width="610" Orientation="Horizontal">
            <Button Style="{StaticResource DogButton}"  Content="M" Name="ButtonM" />
            <Button Style="{StaticResource DogButton}"  Content="D" Name="ButtonD" />
            <Button Style="{StaticResource DogButton}"  Content="C" Name="ButtonC" />
            <Button Style="{StaticResource DogButton}"  Content="L" Name="ButtonL" />
            <Button Style="{StaticResource DogButton}"  Content="X" Name="ButtonX" />
            <Button Style="{StaticResource DogButton}"  Content="V" Name="ButtonV" />
            <Button Style="{StaticResource DogButton}"  Content="I" Name="ButtonI" />
        </StackPanel>
        <StackPanel Height="63" HorizontalAlignment="Left" Margin="0,112,0,0" Name="StackPanel2" VerticalAlignment="Top" Width="610" Orientation="Horizontal">
            <Button Style="{StaticResource DogButton}"  Content="PLUS" Name="ButtonPlus" />
            <Button Style="{StaticResource DogButton}"  Content="Minus" Name="ButtonMinus" />
            <Button Style="{StaticResource DogButton}"  Content="VICIS" Name="ButtonTimes" />
            <Button Style="{StaticResource DogButton}"  Content="tribuo" Name="ButtonDivide" />
            <Button Style="{StaticResource DogButton}"  Content="Procedo" Name="ButtonCalc" Width="160" />
            <Button Style="{StaticResource DogButton}"  Content="Plane" Name="ButtonClear" />
        </StackPanel>
    </Grid>
</Window>

Remember, these are early days for me and XAML, so there might be a better/neater form for it to take.

APL/W Code

The overall shape of the code should be fairly familiar to anyone who has been using APL/W to build GUI-based applications, first we have the main function...

 Computus w;⎕IO;⎕ML
⍝ Roman Calculator - exploring WPF and XAML
 ⎕IO ⎕ML←0 3
 ⎕EX'#.frmCalc'
 #.frmCalc←#.WPF.LoadXamlFile #.GLOBALS.homefolder,'computus.xaml'
 #.frmCalc←Initialise #.frmCalc
 #.frmCalc←SetCallbacks #.frmCalc
 #.frmCalc.Show

Nothing really revolutionary here, we define the form (using the WPF namespace of Jonathan Manktelow's demo workspace), initialise it, set the callbacks then wait for Caesar Maximus to start doing his sums.  Some of the details...

We can leave LoadXamlFile as a magic box for now.

Initialisation in this instance is quite simple...

 z←Initialise w;⎕IO;⎕ML;lab
⍝ Initialise the form
 ⎕IO ⎕ML←0 3
 z←w
 lab←z.FindName⊂'LabelDisplay'
 lab.Content←''

We're avoiding a VALUE ERROR here, since the XAML file doesn't define any content (maybe it should - I'm not perfect) we have to put something in there to start with.  It also illustrates the common method of identifying which control we want to work on - seems a bit clunky, maybe cleaner approaches are going to make themselves known as experience grows.

The XAML file hasn't said anything about events and callbacks, I'm leaving this entirely in the APL domain, so...

 z←SetCallbacks w;⎕IO;⎕ML;button;suffix
⍝ Set callbacks for the form
 ⎕IO ⎕ML←0 3
 z←w
 :For suffix :In 'I' 'V' 'X' 'L' 'C' 'D' 'M' 'Plus' 'Minus' 'Times' 'Divide' 'Calc' 'Clear'
     ⍎'z.button',suffix,'←z.FindName⊂''Button',suffix,''''
     ⍎'z.button',suffix,'.onClick←''#.Click'''
 :EndFor

The callback itself is also somewhat under-complicated...
 Click w;⎕IO;⎕ML;lab;btn;expr;result
⍝ Callback for button click
 ⎕IO ⎕ML←0 3
 lab←#.frmCalc.FindName⊂'LabelDisplay'
 btn←,6↓(↑w).Name
 :Select btn
 :CaseList ,¨'I' 'V' 'X' 'L' 'C' 'D' 'M' 'Plus' 'Minus' 'Times' 'Divide'
     lab.Content,←((,¨'I' 'V' 'X' 'L' 'C' 'D' 'M' 'Plus' 'Minus' 'Times' 'Divide')⍳⊂btn)⌷'IVXLCDM+-×÷'
 :Case 'Calc'
     expr←lab.Content
     result←#.EVALUATE.Evaluate expr
     lab.Content←result
 :Case 'Clear'
     lab.Content←''
 :Else
     ∘
 :EndSelect

Most of the keys just append the appropriate character onto the display, and in the spirit of simplicity Evaluate does as little as it can get away with...

 z←Evaluate w;⎕IO;⎕ML;s;t;⎕TRAP
⍝ Evaluate a Roman expression
 ⎕IO ⎕ML←0 3
 t←Parse w~' '
 s←{∧/⍵∊'MDCLXVI'}¨t
 (s/t)←#.TRANSLATE.Arabic¨s/t
 :Trap 0
     z←#.TRANSLATE.Roman⍎⍕t
 :Else
     z←'DOMAIN ERRORIS'
 :EndTrap

I'm not bothering my pretty little head with stuff like verifying valid input; after all this is already way more advanced than what Centimus Maximus had to work with.

The Arabic/Roman translation code is straight out of the Toronto Toolkit.

Issues

So there we have it - 21st century technology solving a simple problem.  Aside from finding out that it works, what else needs sorting out?


More chapters on the joys of XAML and WPF will no doubt appear over the coming weeks and months - watch this space.

Page created 30 June 2010; Copyright © Dogon Research 2010