source: subversion/applications/rendering/rendercontrol/rendercontrol.pl @ 30554

Last change on this file since 30554 was 1545, checked in by joerg, 13 years ago

insert Man pages/Copyright Info/Copright? Stubs to some of our perl Programs

  • Property svn:executable set to *
File size: 19.1 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=head1 SEE ALSO
35
36osmarender
37
38josm
39
40http://www.openstreetmap.org/
41
42=cut
43use strict;
44use Tk;
45use IO::Socket::INET;
46use Tk::Pane;
47use Tk::Label;
48use Tk::Menu;
49use Tk::Image;
50use Data::Dumper;
51use LWP::Simple qw(getstore);
52use File::Copy qw(copy);
53#DownloadFiles();exit;
54#-----------------------------------------------------------------------------
55# Options
56#-----------------------------------------------------------------------------
57my $NAME = "RenderControl";
58my $Files = "Files"; # Main directory
59
60#-----------------------------------------------------------------------------
61# Pre-GUI stage
62#-----------------------------------------------------------------------------
63
64# Globals
65my $Status = "Statusbar";
66my ($Lat1,$Long1,$Lat2,$Long2,$Title,$CoordsValid,$DisplayText,$ProjectName);
67my %Options = ("RenderWidth"=>"1000");
68my $WikiPage = "http://wiki.openstreetmap.org/index.php/Rendercontrol";
69
70# If this is the first time the program has run, ask user some questions
71FirstTime() if(! -d $Files);
72
73# Load options from a file
74LoadOptions("$Files/options.txt");
75
76#-----------------------------------------------------------------------------
77# Create GUI
78#-----------------------------------------------------------------------------
79PrintBig("Loading GUI");
80my $Window = new MainWindow(-title => $NAME);
81my %Controls;
82
83$Window->optionAdd("*tearOff", "false");
84$Window->optionAdd('*BorderWidth' => 1);
85         
86#-----------------------------------------------------------------------------
87# Create menus
88#-----------------------------------------------------------------------------
89# File menu
90my $Menu = $Window->Menu;
91my $FileMenu = $Menu->cascade(-label => "~File");
92 
93  $FileMenu->command(-label=> "~Open", -command => sub{ReplaceFile("$Files/data.osm","osm");});
94  $FileMenu->separator();
95  $FileMenu->command(-label=> "E~xit", -command => sub{exit});
96
97# View menu
98my $ViewMenu = $Menu->cascade(-label => "~View");
99  $ViewMenu->command(-label=> "OSM data", -command => sub{SetView("text", "$Files/data.osm");});
100  $ViewMenu->command(-label=> "Osmarender", -command => sub{SetView("text", "$Files/osm-map-features.xml");});
101  $ViewMenu->command(-label=> "SVG", -command => sub{SetView("text", "$Files/output.svg");});
102  $ViewMenu->command(-label=> "Image", -command => sub{SetView("image", "$Files/output.gif");});
103
104  $ViewMenu->separator();
105  $ViewMenu->command(-label=> "Open SVG in editor", -command => sub{OpenFile("Editor", "$Files/output.svg");});
106  $ViewMenu->command(-label=> "Open image in editor", -command => sub{OpenFile("ImageEditor", "$Files/output.png");});
107
108# Project menu
109my $ProjectMenu = $Menu->cascade(-label => "~Project");
110  my $LoadProjectMenu = $ProjectMenu->cascade(-label=> "Load ~project");
111  ListProjects($LoadProjectMenu);
112 
113  $ProjectMenu->command(-label=> "~Save project as", -command => \&SaveProjectDialog);
114 
115  $ProjectMenu->separator();
116  $ProjectMenu->command(-label=>"Reload project list",
117    -command => sub{RefreshListProjects($LoadProjectMenu);});
118
119# Bookmarks menu
120my $BookmarksMenu = $Menu->cascade(-label => "~Bookmarks");
121  my $Bookmarks1 = $BookmarksMenu->cascade(-label=> "Global bookmarks");
122  BookmarkMenu($Bookmarks1, "$Files/Bookmarks");
123  my $Bookmarks2 = $BookmarksMenu->cascade(-label=> "JOSM Bookmarks");
124  BookmarkMenu($Bookmarks2, $Options{"JosmBookmarks"});
125
126# Update from web
127my $UpdateMenu = $Menu->cascade(-label=>"~Update");
128  $UpdateMenu->command(-label=>"~Download latest files", 
129    -command => \&DownloadFiles);
130  $UpdateMenu->command(-label=>"~Reload options", 
131    -command => sub{LoadOptions("$Files/options.txt");});
132
133# Help menu
134my $HelpMenu = $Menu->cascade(-label => "~Help");
135  $HelpMenu->command(-label=>"~Web page", 
136    -command => sub{BrowseTo($WikiPage);});
137
138$Window->configure(-menu => $Menu);
139# tst change
140
141#-----------------------------------------------------------------------------
142# Create rest of window
143#-----------------------------------------------------------------------------
144my $LeftFrame = $Window->Frame()->pack(-expand=>0,-fill=>'y',-side=>"left");
145my $ControlFrame = $LeftFrame->Frame(-borderwidth=>2,-relief=>'ridge')->pack(-side=>'top');
146my $ListFrame = $LeftFrame->Scrolled('Pane', -scrollbars => 'e',-borderwidth=>2,-relief=>'ridge')->pack(-side=>'bottom', -expand=>1,-fill=>'both');
147
148$ControlFrame->Entry(-textvariable=>\$Lat1)->pack(-side=>'top');
149$ControlFrame->Entry(-textvariable=>\$Lat2)->pack(-side=>'top');
150$ControlFrame->Entry(-textvariable=>\$Long1)->pack(-side=>'top');
151$ControlFrame->Entry(-textvariable=>\$Long2)->pack(-side=>'top');
152$ControlFrame->Button(-text=>"Download", -command=>\&DownloadData)->pack(-side=>'top');
153
154$ControlFrame->Entry()->pack(-side=>'top');
155$ControlFrame->Button(-text => 'Render', -command => \&Render)->pack(-side=>'left');
156$ControlFrame->Message(-textvariable => \$Status)->pack(-side=>'left', -expand=>1, -fill=>'x');
157
158my $RightFrame = $Window->Frame(-borderwidth=>2,-relief=>'ridge')->pack(-expand=>1,-fill=>'both',-side=>"right");
159my $List2 = $RightFrame->Scrolled('Pane', -scrollbars => 'se',-relief=>'ridge')->pack(-expand=>1,-fill=>'both');
160
161# Create image
162my $Image = $Window->Photo(-format=>"GIF");
163my $Canvas = $List2->Canvas(-width => $Image->width,
164        -height => $Image->height)->pack(-expand=>1, -fill=>'both');
165my $TextView = $List2->Text()->pack(-expand=>1, -fill=>'both');
166
167my $IID = $Canvas->createImage(0, 0,
168        -anchor => 'nw',
169        -image  => $Image);
170   
171AddDemoControls($ListFrame) if(0);
172MainLoop;
173
174#-----------------------------------------------------------------------------
175# Refresh the list of projects in the file menu
176#-----------------------------------------------------------------------------
177sub RefreshListProjects(){
178  my ($Menu) = @_;
179  $ProjectMenu->cget(-menu)->delete(0, "end");
180  ListProjects($Menu);
181}
182sub ListProjects(){
183  my ($Menu) = @_;
184  opendir(DIR, $Files) || return;
185  while(my $File = readdir(DIR)){
186    my $FullFile = "$Files/$File";
187    if(-d $FullFile && $File ne "." && $File ne ".."){
188      $ProjectMenu->command(
189          -label => "Proj " . $File, 
190          -command => sub{$ProjectName = $File; WithProject("load");});
191    }
192  }
193  closedir(DIR);
194}
195
196#-----------------------------------------------------------------------------
197# Dialog box allowing project files to be saved in particular place
198#-----------------------------------------------------------------------------
199sub SaveProjectDialog(){
200  my $SaveProject;
201  my $Dialog = $Window->Toplevel(-title=>"Save project");
202  $Dialog->Message(-text=>"Enter a project name")->pack();
203  $Dialog->Entry(-textvariable=>\$SaveProject)->pack();
204  $Dialog->Button(-text=>"Cancel", -command=>sub{$Dialog->withdraw()})->pack(-side=>'left');
205  $Dialog->Button(-text=>"OK", -command=>sub{$ProjectName = $SaveProject; WithProject("save"); $Dialog->withdraw()})->pack(-side=>'right');
206}
207
208#-----------------------------------------------------------------------------
209# Load a file, storing it in the specified location
210#-----------------------------------------------------------------------------
211sub ReplaceFile(){
212  my ($ToFile, $Ext) = @_;
213  my @FileTypes = (["$Ext files", "*.$Ext"], ["All Files", "*"] );
214 
215  my $FromFile = $Window->getOpenFile(-filetypes => \@FileTypes);
216  return if(!$FromFile);
217 
218  copy($FromFile, $ToFile);
219}
220
221#-----------------------------------------------------------------------------
222# Do something with a "project" (group of data files)
223# - load (from project directory into Files/ directory)
224# - save (into project directory)
225# - delete project directory
226#-----------------------------------------------------------------------------
227sub WithProject(){
228  my $Mode = shift();
229  return if(!$ProjectName);
230 
231  my $ProjectDir = "$Files/$ProjectName";
232  mkdir($ProjectDir) if(! -d $ProjectDir && $Mode eq "save");
233 
234  foreach ("data.osm","output.svg","output.png","output.jpg","output.gif"){
235    if($Mode eq "save"){
236      copy("$Files/$_","$ProjectDir/$_");
237    }
238    elsif($Mode eq "load"){
239      copy("$ProjectDir/$_", "$Files/$_");
240    }
241    elsif($Mode eq "delete"){
242      unlink "$ProjectDir/$_";
243    }
244  }
245  unlink $ProjectDir if($Mode eq "delete");
246}
247
248#-----------------------------------------------------------------------------
249# Download all rendering files from disk
250#-----------------------------------------------------------------------------
251sub DownloadFiles(){
252  my @Files = ("http://svn.openstreetmap.org/utils/osmarender/osmarender.xsl", 
253  "http://svn.openstreetmap.org/utils/osmarender/osm-map-features.xml",
254  "http://wiki.openstreetmap.org/index.php/OJW/Bookmarks",
255  "http://svn.openstreetmap.org/freemap/freemap.xml");
256
257  foreach my $File(@Files){
258    if($File =~ /\/([^\\\/]*?)$/){
259      my $Title = $1;
260      $Status = "Downloading $Title";
261      my $Store = "$Files/$Title";
262      print "Downloading $File to $Store\n";
263      getstore($File, $Store);
264    }
265  }
266  $Status = "Download complete";
267}
268
269#-----------------------------------------------------------------------------
270# Downloads OSM data from web
271#-----------------------------------------------------------------------------
272sub DownloadData(){
273  if(!$CoordsValid){
274    $Status = "Enter some coordinates, or load a bookmark";
275    return;
276    }
277
278  PrintBig("Downloading $Title ($Lat1,$Long1,$Lat2,$Long2)");
279   
280  $Options{"username"} =~ s/\@/%40/;
281 
282  my $URL = sprintf( "http://%s:%s\@www.openstreetmap.org/api/0.3/map?bbox=$Long1,$Lat1,$Long2,$Lat2",
283  $Options{"username"},
284  $Options{"password"});
285 
286  $Status = "Downloading\n";
287  getstore($URL, "$Files/data.osm");
288  $Status = "Download complete\n";
289}
290
291#-----------------------------------------------------------------------------
292# Renders a map
293#-----------------------------------------------------------------------------
294sub Render(){
295  if($Options{"XmlStarlet"}){
296    my $Cmd = sprintf("\"%s\" tr %s %s > %s",
297      $Options{"XmlStarlet"},
298      "$Files/osmarender.xsl",
299      "$Files/osm-map-features.xml",
300      "$Files/output.svg");
301    `$Cmd`;
302    $Status = "Render complete";
303  }
304  else {
305    $Status = "No XLST program (e.g. xmlstarlet) available";
306    return;
307  }
308 
309  if($Options{"Inkscape"}){
310    my $Cmd = sprintf("\"%s\" -D -w %d -b FFFFFF -e %s %s",
311      $Options{"Inkscape"},
312      $Options{"RenderWidth"},
313      "$Files/output.png",
314      "$Files/output.svg");
315   
316    PrintBig($Cmd); 
317    `$Cmd`;
318  }
319  else{
320    $Status = "No SVG renderer available";
321    return;
322  }
323  ConvertOutputs();
324}
325#-----------------------------------------------------------------------------
326# Convert between bitmap graphics formats
327#-----------------------------------------------------------------------------
328sub ConvertOutputs(){
329  return if(!$Options{"ImageMagick"});
330 
331  foreach my $Output("$Files/output.png","$Files/output.gif"){
332    my $Cmd = sprintf("\"%s\" %s %s",
333      $Options{"ImageMagick"},
334      "$Files/output.png",
335      $Output);
336   
337    `$Cmd`;
338  }
339 
340  SetView("image","$Files/output.gif");
341}
342
343#-----------------------------------------------------------------------------
344# Set what's displayed in the right-hand pane
345#-----------------------------------------------------------------------------
346sub SetView(){
347  my ($Style, $Filename) = @_;
348  if($Style eq "text"){
349    print "Loading text file $Filename\n";
350
351    if(open(IN, "<",$Filename)){
352      $DisplayText = join('', <IN>);
353      close IN;
354    }
355    else{
356      $DisplayText = "File not available:\n$Filename\n";
357    }
358
359    $TextView->delete('1.0','end');
360    $TextView->insert("end", $DisplayText);
361
362    $Canvas->pack('forget');
363    $TextView->pack();
364  }
365  elsif($Style eq "image"){
366    print "Loading image $Filename\n";
367    $Canvas->pack();
368   
369    $Image->configure(-file=>$Filename);
370
371    $Canvas->configure(-width => $Image->width);
372    $Canvas->configure(-height => $Image->height);
373   
374    $TextView->pack('forget');
375  }
376  else{
377    print STDERR "Unknown type of object to display";
378  }
379}
380
381#-----------------------------------------------------------------------------
382# Open a file using external editor
383#  * param1 is what program to use, and is a reference to something in %Options
384#  * param2 is the filename to open
385#-----------------------------------------------------------------------------
386sub OpenFile("ImageEditor", "$Files/output.png"){
387  my ($ProgramType, $Filename) = @_;
388  my $Program = $Options{$ProgramType};
389  if(!$Program){
390    print STDERR "Can't find a $ProgramType to open $Filename\n";
391    return;
392  }
393  my $Cmd = sprintf("\"%s\" \"%s\"", $Program, $Filename);
394  PrintBig($Cmd);
395  `$Cmd`;
396}
397
398#-----------------------------------------------------------------------------
399# Create a submenu showing all bookmarks loaded from a file, where clicking on
400# any menu loads its coordinates into appropriate places
401#-----------------------------------------------------------------------------
402sub BookmarkMenu(){
403  my ($Menu, $File) = @_;
404  return if(!$File);
405 
406  open(IN, $File) || return;
407  my $Data = join('', <IN>);
408  close IN;
409  $Data = $1 if($Data =~ /START_DATA(.*)END_DATA/ms);
410
411  foreach my $Line(split(/\n/, $Data)){
412    my ($Name, $Lat1, $Long1, $Lat2, $Long2, $Spare) = split(/,/,$Line);
413    $Menu->command(-label=> $Name, -command => sub{SetData($Name,$Lat1, $Long1, $Lat2, $Long2);}) if($Name && $Spare eq "false");
414  }
415
416  $Menu->separator();
417  $Menu->command(-label=> "Edit this list (web link)", 
418    -command => sub{BrowseTo("http://wiki.openstreetmap.org/index.php/OJW/Bookmarks")});
419}
420
421#-----------------------------------------------------------------------------
422# Opens a web browser to display the specified URL
423#-----------------------------------------------------------------------------
424sub BrowseTo(){
425  my $URL = shift();
426  my $Browser = $Options{"Browser"};
427  `\"$Browser\" $URL` if($Browser);
428}
429
430#-----------------------------------------------------------------------------
431# Sets-up the application, first time it's run
432#-----------------------------------------------------------------------------
433sub FirstTime(){
434  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";
435  exit if(<> =~ /N/i);
436  mkdir($Files);
437   
438 
439  # Get username and password
440  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";
441  print "Username:"; $Options{"username"} = <>;
442  print "Password:"; $Options{"password"} = <>;
443  chomp($Options{"username"}, $Options{"password"});
444  print "\n";
445 
446  LookFor("Browser", 
447          "C:\\Program Files\\Mozilla Firefox\\firefox.exe", 
448          "C:\\windows\\iexplore.exe", 
449          "C:\\winnt\\iexplore.exe", 
450          "C:\\windows\\iexplore.exe", 
451          "C:/Program Files/Internet Explorer/iexplore.exe",
452          "/usr/bin/firefox");
453 
454  LookFor("XmlStarlet", 
455          "C:\\xml\\xml.exe", 
456          "/usr/bin/xmlstarlet");
457 
458  LookFor("Inkscape", 
459          "C:\\Program Files\\inkscape\\inkscape.exe", 
460          "/usr/bin/inkscape");
461 
462  LookFor("ImageMagick", 
463          "/usr/bin/convert");
464 
465  LookFor("JosmBookmarks", 
466          "$ENV{HOME}/.josm/bookmarks",
467          "$ENV{HOME}/.josm/Bookmarks",
468          "~/.josm/Bookmarks",
469          "C:/Documents and Settings/oliverwhite.CUESIM/.josm/bookmarks");
470
471  LookFor("JOSM", 
472          "$ENV{HOME}/bin/josm-latest.jar",
473          "C:/home/osm/josm-latest.jar");
474 
475  LookFor("Editor", 
476          "c:/windows/notepad.exe",
477          "c:/winnt/notepad.exe",
478          "/usr/bin/kate",
479          "/usr/bin/emacs");
480       
481  LookFor("ImageEditor", 
482          "C:/Program Files/GIMP-2.0/bin/gimp-win-remote.exe",
483          "/usr/bin/gimp",
484          "/usr/bin/gqview");
485 
486  SaveOptions("$Files/options.txt");
487 
488  # Download files for the first time
489  PrintBig("Downloading latest osmarender");
490  DownloadFiles(); 
491 
492}
493
494#-----------------------------------------------------------------------------
495# Save all options to disk
496#-----------------------------------------------------------------------------
497sub SaveOptions(){
498  my $Filename = shift();
499  if(open(SAVEOPTIONS, ">", $Filename)){
500    foreach my $Option(keys %Options){
501      printf SAVEOPTIONS "%s=%s\n", $Option, $Options{$Option};
502    }
503    close SAVEOPTIONS;
504  }
505  else{
506    print STDERR "Problem: Couldn't save options to $Filename\n";
507  }
508}
509
510#-----------------------------------------------------------------------------
511# Try to find a particular program
512# Usage: LookFor("SettingName", "PossibleLocation1", "PossibleLocation2",...)
513#-----------------------------------------------------------------------------
514sub LookFor(){
515  my ($Name, @Options) = @_;
516  foreach my $Option(@Options){
517    if(-f $Option){
518      $Options{$Name} = $Option;
519      print "Using $Name: $Option\n";
520      return;
521    }
522  }
523  print "Where can I find $Name on this computer? (press Enter if you don't know)\n";
524  $Options{$Name} = <>;
525  chomp($Options{$Name});
526}
527
528#-----------------------------------------------------------------------------
529# Load all options from disk
530# as name=value pairs (one per line)
531#-----------------------------------------------------------------------------
532sub LoadOptions(){
533  my $Filename = shift();
534  open(OPT, "<", $Filename) || return;
535  while(my $Line = <OPT>){
536    chomp $Line;
537    if($Line =~ /^\s*(\w+)\s*=\s*(.*)/){
538      $Options{$1} = $2;
539    }
540  }
541  close OPT;
542}
543
544#-----------------------------------------------------------------------------
545# Temporary: fill the left column with dummy controls to see what it looks like
546#-----------------------------------------------------------------------------
547sub AddDemoControls(){
548  my($Frame) = @_;
549 
550  foreach (1..60){
551    my $ItemFrame = $Frame->Frame()->pack(-expand=>1, -fill=>'x');
552    $ItemFrame->Checkbutton(-text => "TODO $_")->pack(-side=>'top')->deselect();
553  }
554}
555
556#-----------------------------------------------------------------------------
557# Sets the download area (used when clicking on bookmark menu)
558#-----------------------------------------------------------------------------
559sub SetData(){
560  ($Title,$Lat1,$Long1,$Lat2,$Long2) = @_;
561  $CoordsValid = 1;
562}
563
564
565#-----------------------------------------------------------------------------
566# Prints a message in big letters on console
567#-----------------------------------------------------------------------------
568sub PrintBig(){
569    print STDERR "=" x 80 . "\n" . shift() . "\n" . "=" x 80 . "\n";
570}
Note: See TracBrowser for help on using the repository browser.