Friday, December 20, 2013

Portable GreyMap

The whole family of portable pixmaps in the Netpbm family of formats have a very extensive set of tools to convert and process them. These tools are however not included as standard on many platforms you'd want to develop in RB for.

The format of the PGM file format, a greyscale bitmap image, is fairly simple and described widely on the net. Apart from being simple, it however also allows for many variations. All these possible variations make it again a bit more interesting to make a robust reader for these files.

One example of the plain-text version (type P2) is this

        P2
        # feep.pgm
        24 7
        15
        0 0  0  0  0  0  0  0  0 0  0  0  0  0  0  0  0 0  0  0  0  0  0  0
        0 3  3  3  3  0  0  7  7 7  7  0  0 11 11 11 11 0  0 15 15 15 15  0
        0 3  0  0  0  0  0  7  0 0  0  0  0 11  0  0  0 0  0 15  0  0 15  0
        0 3  3  3  0  0  0  7  7 7  0  0  0 11 11 11  0 0  0 15 15 15 15  0
        0 3  0  0  0  0  0  7  0 0  0  0  0 11  0  0  0 0  0 15  0  0  0  0
        0 3  0  0  0  0  0  7  7 7  7  0  0 11 11 11 11 0  0 15  0  0  0  0
        0 0  0  0  0  0  0  0  0 0  0  0  0  0  0  0  0 0  0  0  0  0  0  0

A quick and simple LoadFromPGM function reads the file in and stretches the greyscale values of a regular Picture object. (Blurring in the screenshot is from the scaling of the Picture.)
The LoadFromPGM method is written to be fairly forgiving on the file format. It will read one image from a PGM file, either a binary or a plaintext one. There is a lot of repetitive code, it should really be re-factored and it is not the fastest code. But then again, source is provided here so feel free :)

The source for the example PGM viewer application can be downloaded in this archive.

Tuesday, September 3, 2013

Grabbing pixels, magnifying window

With the developer tools of Apple, in the Graphic Tools, there is a small program that magnifies a small area of the screen. This can be handy to see what is happening on the pixel-level with your program as well as for pixel-perfect aligning of any graphics you are drawing in your application.

This little tool 'Pixie' runs of course in OSX. Apart from curiosity - could we do this with RealBasic - we also rather wanted this function on some older systems running OS9.

And indeed we can do this with RealBasic.


The code in the method listed below does this by doggedly asking for the color of a System.Pixel at a coordinate on the screen. With the color of the pixel of the screen then a small rectangle is drawn onto the receiving canvas to create a magnified view.


  Sub UpdateImage(Cnv As Canvas)

  Dim mX, mY As Integer // the mouse position in global coords
  Dim nX, nY As Integer // the size of the sample we are magnifying
  Dim dX, dY As Integer // the mid-point of the magnifying area
  Dim CounterX, CounterY As Integer
  Dim mag As Integer // magnification factor
  
  mag = App.MagFactor  // get from preferences 
  
  mX = System.MouseX
  mY = System.MouseY
  
  // if the pref is to only update when the mouse moved, 
  // check for the condition and bail from Sub if so 
  If App.LiveUpdating = False Then
    If mX = LastX And mY = LastY Then 
      Exit // bail
    End if
  End If
  
  // still here, so need to update our image so store the current coords
  LastX = mX
  LastY = mY
  
  
  // determine the size of the sample we need to take from Screen by
  // dividing the target canvas size by the magnification factor
  nX = Floor( Cnv.Width / mag )
  nY = Floor( Cnv.Height / mag )
  
  // then the midpoint we need to sample around
  dX = Round( nX/2 )
  dY = Round( nY/2)
  
  // then sample the color of every pixel we need to magnify and draw
  // a corresponding square onto the canvas (that was passed as param)
  For CounterX = 0 To nX
    For CounterY = 0 To nY
      magPic.Graphics.ForeColor = System.Pixel(mX+CounterX-dX, mY+CounterY-dY)
      magPic.Graphics.FillRect( CounterX*mag, CounterY*mag,mag,mag)
    Next
  Next
  
  Cnv.Refresh

  End Sub

This method is used to make a magnifying window very much like the Pixie tool. The program in this source is localized into Dutch, but we're sure you will be able to figure out what it all means and be able to change it to the language of your choice. Source is provided right here.

The source also includes handling of preferences and remembering window positions. Because it is not possible to change the type of a Window (document, floating) after it has been created, the program uses two windows and shows/hides these depending on the program state.

Activating the program with a mouse click in the system-wide floater also is a bit of a hack. Have a look at the code :)


Wednesday, June 5, 2013

Graph, just a simple graph

For RealBasic there are several Plot, Graph or graphing components to draw simple and even very complex graphs. Some of the more capable components are commercial software and indeed are on a professional level. Sometimes however all that is needed is a quick chart to show some trend or series of data in an application.

Also there are free and open source components out there with again varying levels of complexity and capability. Having used some for a while, we ended up making our own version to be very simple in use and to introduce only one class. So there is not the Graph that can include several Plots that can include several Series objects. This class or component is a single Graph object that can plot a line-graph.


All the data are copied to arrays in the Graph object, no additional files or classes are needed.

In the GraphExample project the Graph object is included and of course with all source code readable and editable. It only draws line graphs; adding bar graphs or other plot types is of course possible. The handling of the text sizing could be more elegant and the scale-values could be simpler. But it comes as source code and free to use and extend.

To figure out the current capabilities (range limiting, x-grid only etc...) do have a rummage round the example project and the Graph source.

We may even extend it ourselves.

Good luck :)

Wednesday, April 24, 2013

Fullscreen on Snow Leopard

On previous OSX versions it was of course already possible and quite easy to make a fullscreen application with RealBasic. Toggle the fullscreen property of the Window, this will make the window cover the whole screen.

Two small niggles still remained: the grow-icon and a menubar hiding glitch.

If the application window is re-sizable when not in fullscreen, the 'grow icon' is still visible when the window is fullscreen. Grabbing this also allows the window to be resized when 'officially' in fullscreen mode. One way to solve this is to maintain two Window objects, one for windowed and one non-sizable for the fullscreen view. Another, easier solution is to use the SetWindowGrowTab function from the excellent collection of CarbonDeclares. (Yes, with Cocoa these will be obsolete ultimately, but now still useful.)

When toggling the fullscreen mode, call:
   SetWindowGrowTab( MyWindow,  Not MyWindow.FullScreen)

The function itself from CarbonDeclares:
Sub SetWindowGrowTab(w as window, b as boolean)
  // Added 11/13/2001 by Jarvis Badgley
  // Renamed 11/16/2001 by Jarvis Badgley from DisableWindowMinimizeWidget
  
  const attrib = 16

  dim err as integer
  #if TargetCarbon then
    Declare Function ChangeWindowAttributes Lib "Carbon" (window as WindowPtr, setTheseAttributes as Integer, clearTheseAttributes as Integer) as Integer
    
    if b then
      err = ChangeWindowAttributes(w, attrib, 0)
    else
      err = ChangeWindowAttributes(w, 0, attrib)
    end
    
  #endif // TargetCarbon
End Sub



The second niggle is that after the user selects a menu item by pressing the shortcut key (e.g. Cmd-O) , the menubar comes out of hiding and does not go back. The simple hack to work around this is to toggle the MenuBarVisible state. Call this hack at the end of every menu handler.


  If MyWindow.FullScreen Then
    MyWindow.MenuBarVisible = True //brings state in sync with OS again, otherwise the hide won't trigger
    MyWindow.MenuBarVisible = Not MyWindow.FullScreen
  End if
 

There are likely other or better ways to avoid these small niggles, but these worked. These allow the application to have a 'clean' fullscreen option for it's window also on older versions of OSX.


Thursday, April 18, 2013

More versatile Canvas for showing images

To show a picture, the quick RealBasic way is to add a Canvas object to the window and assign a Picture to the Backdrop property of the Canvas. This will draw the image in the canvas space, stretched to the size of the canvas.

To have a bit more control over how the image is drawn, especially when using pre-drawn graphics as part of the user interface, this ImageCanvas control is made. It adds an Image property and allows selecting the mode of drawing, i.e. how the picture will be drawn.

The new ImageCanvas component is included in the example project. Use the menu to find and open an image file, or drag-and-drop an image file on the window. Use the controls to change the drawing mode and see how it changes the way the picture is drawn.
And of course; browse the code to see how it works and tweak as needed...


Tuesday, April 9, 2013

Automatic file naming code snippet

For some applications, it can be useful to be able to save a file without asking for a filename first with a dialog. Much like e.g. taking a screenshot on a Mac, this ends up on the Desktop with a filename that contains the time of the file, e.g. "Screen shot 2013-04-09 at 10:10 AM".

This code snippet generates a FolderItem with a filename generated in the same way:

Function AutonamedFile(prefix As String, extension As String) As FolderItem
  Dim f As FolderItem
  Dim D As Date
  Dim i As Integer
  
  D = New Date
  
  f = SpecialFolder.Desktop.Child(prefix + D.SQLDate+ " at " + Format(D.Hour,"00")+"."+Format(D.Minute,"00")+"."+Format(D.Second,"00")+ "."+extension)
  
  If f.Exists Then
    i = 1
    Do
      f = SpecialFolder.Desktop.Child(prefix + D.SQLDate+ " at " + Format(D.Hour,"00")+"."+Format(D.Minute,"00")+"."+Format(D.Second,"00")+" " + Str(i)+ "."+extension)
      i = i+1
    Loop Until Not f.Exists
  End if
  
  Return f
  
End Function


Copy-paste into RealStudio as a method. For saving e.g. a Picture (MyPicture) the same way that the screenshot function in the Mac does it, call with the prefix and extension like so:

Dim f As FolderItem

f = AutonamedFile("Screen shot", "png")
MyPicture.Save(f, Picture.SaveAsPNG)


Thursday, April 4, 2013

Harvey balls (or a progress indicator)

For a continuous progress indicator with a custom design, a Rotator object. Of course based on a Canvas with custom drawing and a set of properties to set the look and the mode of the Rotator.  In design it basically is a Harvey ball.



The object is included in an example project, showing how the object is called and can be used.

Look in the code of the Paint event to see the drawing. As can be seen in the screenshot, the Canvas has no transparency on Windows in some cases (GDI+). If that is troubling for an application, the following code snippet can be uncommented:


    If Self.TrueWindow.HasBackColor Then
      g.ForeColor = Self.TrueWindow.BackColor
    Else
      g.ForeColor = FillColor
    End
    g.FillRect(0,0,g.Width,g.Height)
   
Look for it in (of course) the Paint event.

Thursday, March 21, 2013

Analog Clock

This may be the most implemented first graphics object; there must be a gazillion implementations. This is mine. (Object inside an example project.) Colors and elements to be drawn can be chosen in the property editor.
Apart from borrowing from the example code from RealStudio, it also uses experience from earlier versions I once made in Delphi and ObjectiveC.

What is added here is a timer object that dynamically adjusts it's interval to ensure a timely update and reduce the likelyhood of skipping the occasional refresh (no 'jumps'). This compensates for the fact that the timer and interval as well as time taken for drawing is not accurate or constant to the millisecond.

Basic Objects

A collection of really basic objects for RealBasic / RealStudio. During tinkering and playing with the RealStudio tool, sometimes play and sometimes for actual work, I've developed a couple of fairly simple objects that I've found handy.

On this blog I'll be sharing these objects for anyone to use (and comment on (or improve upon)).