source: subversion/utils/rendercontrol/rendercontrol.pl @ 1406

Last change on this file since 1406 was 1406, checked in by ojw, 13 years ago

Remove XML dependancy for now

  • Property svn:executable set to *
File size: 13.9 KB
Line 
1#!/usr/bin/perl -w
2=head1 NAME
3
4rendercontrol.pl - Perl/TK GUI interface to OpenStreetMap renderers
5
6=head1 SYNOPSIS
7
8Just run the program.  It will create a Files/ directory, download some
9osmarender stuff from the web, and a list of interesting places, and popup
10a window.
11
12=head1 AUTHOR
13
14Oliver White (oliver.white@blibbleblobble.co.uk)
15
16=head1 COPYRIGHT
17
18Copyright 2006, Oliver White
19
20This program is free software; you can redistribute it and/or
21modify it under the terms of the GNU General Public License
22as published by the Free Software Foundation; either version 2
23of the License, or (at your option) any later version.
24
25This program is distributed in the hope that it will be useful,
26but WITHOUT ANY WARRANTY; without even the implied warranty of
27MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28GNU General Public License for more details.
29
30You should have received a copy of the GNU General Public License
31along with this program; if not, write to the Free Software
32Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
33
34=cut
35use strict;
36use Tk;
37use IO::Socket::INET;
38use Tk::Pane;
39use Tk::Label;
40use Tk::Menu;
41use Tk::Image;
42use Data::Dumper;
43use LWP::Simple qw(getstore);
44#DownloadFiles();exit;
45#-----------------------------------------------------------------------------
46# Options
47#-----------------------------------------------------------------------------
48my $NAME = "RenderControl";
49my $Files = "Files"; # Main directory
50
51#-----------------------------------------------------------------------------
52# Pre-GUI stage
53#-----------------------------------------------------------------------------
54
55# Globals
56my $Status = "Statusbar";
57my ($Lat1,$Long1,$Lat2,$Long2,$Title,$CoordsValid,$DisplayText);
58my %Options = ("RenderWidth"=>"1000");
59
60# If this is the first time the program has run, ask user some questions
61FirstTime() if(! -d $Files);
62
63# Load options from a file
64LoadOptions("$Files/options.txt");
65
66#-----------------------------------------------------------------------------
67# Create GUI
68#-----------------------------------------------------------------------------
69print STDERR "\n\nLoading GUI...\n";
70my $Window = new MainWindow(-title => $NAME);
71my %Controls;
72
73$Window->optionAdd("*tearOff", "false");
74$Window->optionAdd('*BorderWidth' => 1);
75         
76#-----------------------------------------------------------------------------
77# Create menus
78#-----------------------------------------------------------------------------
79# File menu
80my $Menu = $Window->Menu;
81my $FileMenu = $Menu->cascade(-label => "~File");
82  my $Bookmarks = $FileMenu->cascade(-label=> "Bookmarks");
83  BookmarkMenu($Bookmarks, "$Files/Bookmarks");
84  $FileMenu->command(-label=> "E~xit", -command => sub{exit});
85
86# View menu
87my $ViewMenu = $Menu->cascade(-label => "~View");
88  $ViewMenu->command(-label=> "OSM data", -command => sub{SetView("text", "$Files/data.osm");});
89  $ViewMenu->command(-label=> "Osmarender", -command => sub{SetView("text", "$Files/osm-map-features.xml");});
90  $ViewMenu->command(-label=> "SVG", -command => sub{SetView("text", "$Files/output.svg");});
91  $ViewMenu->command(-label=> "Image", -command => sub{SetView("image", "$Files/output.gif");});
92
93  $ViewMenu->separator();
94  $ViewMenu->command(-label=> "Open SVG", -command => sub{});
95  $ViewMenu->command(-label=> "Open image", -command => sub{});
96
97# Update from web
98my $UpdateMenu = $Menu->cascade(-label=>"~Update");
99  $UpdateMenu->command(-label=>"~Download latest files", 
100    -command => \&DownloadFiles);
101  $UpdateMenu->command(-label=>"~Reload options", 
102    -command => sub{LoadOptions("$Files/options.txt");});
103
104# Help menu
105my $HelpMenu = $Menu->cascade(-label => "~Help");
106  $HelpMenu->command(-label=>"~Web page", 
107    -command => sub{BrowseTo("http://www.openstreetmap.org/");});
108
109$Window->configure(-menu => $Menu);
110
111#-----------------------------------------------------------------------------
112# Create rest of window
113#-----------------------------------------------------------------------------
114my $Footer = $Window->Frame()->pack(-side=>"bottom", -fill=>"x");
115$Footer->Button(-text => 'Render', -command => \&Render)->pack(-side=>'left');
116$Footer->Button(-text => 'Quit', -command => sub{exit})->pack(-side=>'right');
117$Footer->Message(-textvariable => \$Status)->pack(-side=>'left', -expand=>1, -fill=>'x');
118
119my $LeftFrame = $Window->Frame()->pack(-expand=>0,-fill=>'y',-side=>"left");
120my $ControlFrame = $LeftFrame->Frame(-borderwidth=>2,-relief=>'ridge')->pack(-side=>'top');
121my $ListFrame = $LeftFrame->Scrolled('Pane', -scrollbars => 'e',-borderwidth=>2,-relief=>'ridge')->pack(-side=>'bottom', -expand=>1,-fill=>'both');
122
123$ControlFrame->Entry(-textvariable=>\$Lat1)->pack(-side=>'top');
124$ControlFrame->Entry(-textvariable=>\$Lat2)->pack(-side=>'top');
125$ControlFrame->Entry(-textvariable=>\$Long1)->pack(-side=>'top');
126$ControlFrame->Entry(-textvariable=>\$Long2)->pack(-side=>'top');
127$ControlFrame->Button(-text=>"Download", -command=>\&DownloadData)->pack(-side=>'top');
128
129my $RightFrame = $Window->Frame(-borderwidth=>2,-relief=>'ridge')->pack(-expand=>1,-fill=>'both',-side=>"right");
130my $List2 = $RightFrame->Scrolled('Pane', -scrollbars => 'se',-relief=>'ridge')->pack(-expand=>1,-fill=>'both');
131
132# Create image
133#my $Image = $Window->Photo(-format=>"GIF",-file=>"$Files/blank.gif");
134my $Image = $Window->Photo(-format=>"GIF");
135my $Canvas = $List2->Canvas(-width => $Image->width,
136        -height => $Image->height)->pack(-expand=>1, fill=>'both');
137my $TextView = $List2->Text()->pack(-expand=>1, fill=>'both');
138
139my $IID = $Canvas->createImage(0, 0,
140        -anchor => 'nw',
141        -image  => $Image);
142   
143AddDemoControls($ListFrame);
144MainLoop;
145
146       
147#-----------------------------------------------------------------------------
148# Download all rendering files from disk
149#-----------------------------------------------------------------------------
150sub DownloadFiles(){
151  my @Files = ("http://svn.openstreetmap.org/utils/osmarender/osmarender.xsl", 
152  "http://svn.openstreetmap.org/utils/osmarender/osm-map-features.xml",
153  "http://wiki.openstreetmap.org/index.php/OJW/Bookmarks",
154  "http://svn.openstreetmap.org/freemap/freemap.xml");
155
156  foreach my $File(@Files){
157    if($File =~ /\/([^\\\/]*?)$/){
158      my $Title = $1;
159      $Status = "Downloading $Title";
160      my $Store = "$Files/$Title";
161      print "Downloading $File to $Store\n";
162      getstore($File, $Store);
163    }
164  }
165  $Status = "Download complete";
166}
167
168#-----------------------------------------------------------------------------
169# Downloads OSM data from web
170#-----------------------------------------------------------------------------
171sub DownloadData(){
172  if(!$CoordsValid){
173    $Status = "Enter some coordinates, or load a bookmark";
174    return;
175    }
176   
177  $Options{"username"} =~ s/\@/%40/;
178 
179  my $URL = sprintf( "http://%s:%s\@www.openstreetmap.org/api/0.3/map?bbox=$Long1,$Lat1,$Long2,$Lat2",
180  $Options{"username"},
181  $Options{"password"});
182 
183  $Status = "Downloading\n";
184  getstore($URL, "$Files/data.osm");
185  $Status = "Download complete\n";
186}
187
188#-----------------------------------------------------------------------------
189# Renders a map
190#-----------------------------------------------------------------------------
191sub Render(){
192  if($Options{"XmlStarlet"}){
193    my $Cmd = sprintf("\"%s\" tr %s %s > %s",
194      $Options{"XmlStarlet"},
195      "$Files/osmarender.xsl",
196      "$Files/osm-map-features.xml",
197      "$Files/output.svg");
198    `$Cmd`;
199    $Status = "Render complete";
200  }
201  else {
202    $Status = "No XLST program (e.g. xmlstarlet) available";
203    return;
204  }
205 
206  if($Options{"Inkscape"}){
207    my $Cmd = sprintf("\"%s\" -D -w %d -b FFFFFF -e %s %s",
208      $Options{"Inkscape"},
209      $Options{"RenderWidth"},
210      "$Files/output.png",
211      "$Files/output.svg");
212     
213    print "=" x 80 . "\n$Cmd\n" . "=" x 80 . "\n";
214    `$Cmd`;
215  }
216  else{
217    $Status = "No SVG renderer available";
218    return;
219  }
220  ConvertOutputs();
221}
222
223#-----------------------------------------------------------------------------
224# Convert between bitmap graphics formats
225#-----------------------------------------------------------------------------
226sub ConvertOutputs(){
227  return if(!$Options{"ImageMagick"});
228 
229  foreach my $Output("$Files/output.png","$Files/output.gif"){
230    my $Cmd = sprintf("\"%s\" %s %s",
231      $Options{"ImageMagick"},
232      "$Files/output.png",
233      $Output);
234   
235    `$Cmd`;
236  }
237 
238  SetView("image","$Files/output.gif");
239}
240
241#-----------------------------------------------------------------------------
242# Set what's displayed in the right-hand pane
243#-----------------------------------------------------------------------------
244sub SetView(){
245  my ($Style, $Filename) = @_;
246  if($Style eq "text"){
247    print "Loading text file $Filename\n";
248
249    if(open(IN, "<",$Filename)){
250      $DisplayText = join('', <IN>);
251      close IN;
252    }
253    else{
254      $DisplayText = "File not available:\n$Filename\n";
255    }
256
257    $TextView->delete('1.0','end');
258    $TextView->insert("end", $DisplayText);
259
260    $Canvas->pack('forget');
261    $TextView->pack();
262  }
263  elsif($Style eq "image"){
264    print "Loading image $Filename\n";
265    $Canvas->pack();
266   
267    $Image->configure(-file=>$Filename);
268
269    $Canvas->configure(-width => $Image->width);
270    $Canvas->configure(-height => $Image->height);
271   
272    $TextView->pack('forget');
273  }
274  else{
275    print STDERR "Unknown type of object to display";
276  }
277}
278
279#-----------------------------------------------------------------------------
280# Create a submenu showing all bookmarks loaded from a file, where clicking on
281# any menu loads its coordinates into appropriate places
282#-----------------------------------------------------------------------------
283sub BookmarkMenu(){
284  my ($Menu, $File) = @_;
285  open(IN, $File) || return;
286  my $Data = join('', <IN>);
287  close IN;
288  if($Data =~ /START_DATA(.*)END_DATA/ms){
289    $Data = $1;
290    foreach my $Line(split(/\n/, $Data)){
291      my ($Name, $Lat1, $Long1, $Lat2, $Long2, $Spare) = split(/,/,$Line);
292      $Menu->command(-label=> $Name, -command => sub{SetData($Name,$Lat1, $Long1, $Lat2, $Long2);}) if($Name && $Spare eq "false");
293    }
294  }
295  $Menu->separator();
296  $Menu->command(-label=> "Edit this list (web link)", 
297    -command => sub{BrowseTo("http://wiki.openstreetmap.org/index.php/OJW/Bookmarks")});
298}
299
300#-----------------------------------------------------------------------------
301# Opens a web browser to display the specified URL
302#-----------------------------------------------------------------------------
303sub BrowseTo(){
304  my $URL = shift();
305  my $Browser = $Options{"Browser"};
306  `\"$Browser\" $URL` if($Browser);
307}
308
309#-----------------------------------------------------------------------------
310# Sets-up the application, first time it's run
311#-----------------------------------------------------------------------------
312sub FirstTime(){
313  print "Welcome to $NAME\n\nThis looks like the first time you've run this program.\nIs it okay to create a directory in $Files, and download some data from the web? (y/n)\n";
314  exit if(<> !~ /Y/i);
315  mkdir($Files);
316   
317 
318  # Get username and password
319  print "\n\nYou now have the opportunity to enter an OSM username and password.\n\nThese will appear on your screen, so check nobody is watching!\nThese will be stored in plaintext on disk\n\nIf you don't want to enter a password yet, just press enter twice,\nthen edit $Files/options.txt later\n";
320  print "Username:"; $Options{"username"} = <>;
321  print "Password:"; $Options{"password"} = <>;
322  chomp($Options{"username"}, $Options{"password"});
323  print "\n";
324 
325  LookFor("Browser", 
326    "C:\\Program Files\\Mozilla Firefox\\firefox.exe", 
327    "C:\\windows\\iexplore.exe", 
328    "C:\\winnt\\iexplore.exe", 
329    "/usr/bin/firefox");
330 
331  LookFor("XmlStarlet", 
332    "C:\\xml\\xml.exe", 
333    "/usr/bin/xmlstarlet");
334 
335  LookFor("Inkscape", 
336    "C:\\Program Files\\inkscape\\inkscape.exe", 
337    "/usr/bin/inkscape");
338   
339  LookFor("ImageMagick", 
340    "/usr/bin/convert");
341 
342  SaveOptions("$Files/options.txt");
343 
344  # Download files for the first time
345  DownloadFiles(); 
346 
347}
348
349#-----------------------------------------------------------------------------
350# Save all options to disk
351#-----------------------------------------------------------------------------
352sub SaveOptions(){
353  my $Filename = shift();
354  if(open(SAVEOPTIONS, ">", $Filename)){
355    foreach my $Option(keys %Options){
356      printf SAVEOPTIONS "%s=%s\n", $Option, $Options{$Option};
357    }
358    close SAVEOPTIONS;
359  }
360  else{
361    print STDERR "Problem: Couldn't save options to $Filename\n";
362  }
363}
364
365#-----------------------------------------------------------------------------
366# Try to find a particular program
367# Usage: LookFor("SettingName", "PossibleLocation1", "PossibleLocation2",...)
368#-----------------------------------------------------------------------------
369sub LookFor(){
370  my ($Name, @Options) = @_;
371  foreach my $Option(@Options){
372    if(-f $Option){
373      $Options{$Name} = $Option;
374      print "Using $Name: $Option\n";
375      return;
376    }
377  }
378  print "Where can I find $Name on this computer? (press Enter if you don't know)\n";
379  $Options{$Name} = <>;
380  chomp($Options{$Name});
381}
382
383#-----------------------------------------------------------------------------
384# Load all options from disk
385# as name=value pairs (one per line)
386#-----------------------------------------------------------------------------
387sub LoadOptions(){
388  my $Filename = shift();
389  open(OPT, "<", $Filename) || return;
390  while(my $Line = <OPT>){
391    chomp $Line;
392    if($Line =~ /^\s*(\w+)\s*=\s*(.*)/){
393      $Options{$1} = $2;
394    }
395  }
396  close OPT;
397}
398
399#-----------------------------------------------------------------------------
400# Temporary: fill the left column with dummy controls to see what it looks like
401#-----------------------------------------------------------------------------
402sub AddDemoControls(){
403  my($Frame) = @_;
404 
405  foreach (1..60){
406    my $ItemFrame = $Frame->Frame()->pack(-expand=>1, -fill=>'x');
407    $ItemFrame->Checkbutton(-text => "TODO $_")->pack(-side=>'top')->deselect();
408  }
409}
410
411sub SetData(){
412  ($Title,$Lat1,$Long1,$Lat2,$Long2) = @_;
413  $CoordsValid = 1;
414  print "Ok, loading $Title,$Lat1,$Long1,$Lat2,$Long2\n";
415}
416
Note: See TracBrowser for help on using the repository browser.