Archive for December, 2004

December 28th 2004

Converting Time String to Seconds

I just had to implement something for the first time that I knew is easy, but I just didn’t like all the approaches. I thought to myself, “This should be doable in just a few lines.” I had even written code like this before, but since I am not using the unreleased version currently, I didn’t have the ability for block level dims, and I just couldn’t bring myself to dimming off a few more variables.

Finally, I had a revelation. I wrote it in only 7 lines of code.

Problem: You are given a string, such as “1:23″ or “20:47:16″. Convert this to an absolute time in seconds. For example, “23″ should yield 23 seconds, “1:23″ should yield 83 seconds, and “1:00:00″ should yield 3600 seconds.

Solution:

Protected Function TimeToSeconds(inputString As String) As Integer
Dim multiplier,time As Integer
Dim parts() As String = Split( theInputString, ":" )
multiplier = 1
While UBound( parts ) >= 0
time = time + val( trim( parts.pop ) ) * multiplier
multiplier = multiplier * 60
Wend

This is the most elegant solution I can think of to this problem. The idea is to split the string into an array, and then treat it as a stack. Pop each item off, and for each item you pop off, you increase the multiplier by 60. I also inserted a trim because I am accepting this as user input, and if they type in “1: 23″ I want it to still work :). This code will fail if you try to give it time that has a day value (for example, “1:23:45:56″). So, we can make the code less elegant, but still get it done:

Protected Function TimeToSeconds(inputString As String) As Integer
Dim multiplier,time As Integer
Dim multipliers() As Integer = Array( 365, 24, 60, 60 )
Dim parts() As String = Split( inputString, ":" )
multiplier = 1
While UBound( parts ) >= 0
time = time + val( trim( parts.pop ) ) * multiplier
If ubound( multipliers ) < 0 Then Return time
multiplier = multiplier * multipliers.pop
Wend

Return time
End Function

And, walah! You now have a nice, compact solution to a pretty common problem.

No Comments yet »

December 23rd 2004

EndOfLine Usage

The end of line character is unique, because it varies from platform to platform, and sometimes varies between usage inside of that particular platform! REALbasic introduces a global function/class combination called EndOfLine that helps with this.

EndOfLine.Macintosh is Chr(13), a carriage return.
EndOfLine.UNIX is Chr(10), a line feed.
EndOfLine.Windows is Chr(13) + chr(10), which is a carriage return + line feed.

Finally, The EndOfLine class has an Operator_Convert to a string. The automatic conversion is the equivalent of:

#If TargetMacOS
Return EndOfLine.Macintosh
#elseif TargetWindows
Return EndOfLine.Windows
#Else
Return EndOfLine.UNIX
#EndIf

Now, the tricky part. When should you use this? Here’s a short list of good uses for EndOfLine:

  • You are wanting to concatenate several strings together for drawing purposes.
  • You want to concatenate several strings to put them into an EditField, or any other system control.
  • You want to write a string to a text file so that native text editors don’t get confused about the line endings.

Here’s where you don’t want to use EndOfLine:

  • You are dealing with a define protocol, such as any internet protocol like HTTP, SMTP, etc. You must *always* use chr(13) + chr(10) in this case, because that’s what the standard calls for.
  • Splitting text. If you call Split() on a string and you want to split it by line endings, the best way to do this is to replace all the line ending variants (CR, LF, CRLF) with a known ending, and then split by that. For example:

    Dim parts() As String
    parts = Split( ReplaceLineEndings( myString, Chr(13) ), Chr(13 )

    What this does is it first replaces all the line endings with Chr(13). Then, we split by Chr(13). This code now doesn’t matter what type of line endings the string contains, which is a good thing.

  • Any binary data. If you’re dealing with binary data, most likely the bytes that compose the file/memoryblock are very important. In this case, it’s better to use either ChrB or Chr to represent your bytes as strings.

And finally, a few gotchas because “The World Isn’t A Perfect Place”:

  • EditFields on Windows are standard RichEdit controls. Prior to RichEdit 2.0, line endings were Chr(13) + chr(10). In RichEdit 2.0 and higher, they are always Chr(13). Be careful about making assumptions that the text you put into an EditField will be the same when you pull it out — that’s asking for trouble.
  • The UNIX underpinnings of Mac OS are most familiar with Chr(10). When dealing with the Shell class, or any config files that console applications use, use EndOfLine.UNIX or Chr(10).

Feel free to post questions, and I’ll keep updating this because it is a tricky topic. Luckily, with EndOfLine and ReplaceLineEndings, it’s much easier to deal with in REALbasic.

No Comments yet »

December 22nd 2004

Dedication

Now, this is dedication. It’s also pretty dang interesting. Check it out — The Story of Graphing Calculator.

No Comments yet »

December 21st 2004

Happy Holidays

Due to relatives coming to town, and me travelling back up to Kansas during this holiday season, updates will continue to be a little sparse. But here are a few tips to tide everyone over :)

  • Shark is an amazing tool. It’s part of Apple’s Developer Tools. I’m contemplating writing up a short article on how to utilize it with REALbasic applications, as I have actually been profiling quite a bit lately, and it is incredibly useful to see what methods your program is spending the most time in. Once you know that, you know where you can go to optimize your code such that you gain the most performance from the optimization. If you are wanting to experiment with Shark yourself, download the Developer Tools, and use the custom install options to select “CHUD” tools.
  • Dynamic MenuItems are a fact of life for most complex applications, or even simple ones. The Name property on a MenuItem corresponds to which MenuHandler will fire, so this can be used to make a new MenuItem from scratch that will call any particular menu handler when clicked. Of course, another approach is to create a new MenuItem subclass in which you implement the Action event.
  • I steal this one from a coworker: Need a random color? Just use CMY(rnd, rnd, rnd).

Have a great holiday season, everyone!

No Comments yet »

December 20th 2004

Who am I?

Well, the kind person at RBGazette.com pointed out that my entire site doesn’t even mention my name. So, I decided I would bring this to life.

I am Jonathan Johnson, a tester and programmer for REAL Software. Despite being employed by REAL Software, this is a personal blog, and nothing said here represents the company’s viewpoints. All code snippets posted here are from personal projects and are offered as public domain with no guarantees (although if they don’t work, let me know :P).

2 Comments »

December 3rd 2004

High quality scaling, cross platform

REALbasic doesn’t use high quality scaling across all the platforms, but I whipped this piece of code up in just a few minutes. It actually looks slightly better than Quartz for really large images.

Function ScalePicture(p As Picture, newWidth As Integer,_
newHeight As Integer) As Picture
#pragma BackgroundTasks False
#pragma NilObjectChecking False
#pragma BoundsChecking False

Dim out As Picture
Dim inrgb,outrgb As RGBSurface

out = New Picture(newWidth,newHeight,32)

inrgb = p.RGBSurface
outrgb = out.RGBSurface

Dim sectionWidth As Double
Dim sectionHeight As Double
Dim currentX As Double
Dim currentY As Double
Dim xx,yy,xc,yc,goToX,goToY,tmpx,tmpy As Integer
Dim reds,greens,blues As Double
Dim c As Color
Dim totalPixels As Integer

sectionWidth = p.Width / newWidth
sectionHeight = p.Height / newHeight

xc = ceil(sectionWidth)
yc = ceil(sectionHeight)

Dim x,y As Integer

newWidth = newWidth - 1
newHeight = newHeight - 1
For y = 0 To newWidth
currentX = 0
For x = 0 To newHeight
reds = 0
greens = 0
blues = 0
tmpx = currentX
goToX = min(tmpX+ xc, p.width - 1)
totalPixels = 0

For yy = tmpy To goToY
For xx = tmpx To goToX
c = inrgb.Pixel(xx, yy)
reds = reds + c.red
greens = greens + c.green
blues = blues + c.blue
totalPixels = totalPixels + 1
Next
Next

c = RGB( reds / totalPixels, _
greens / totalPixels, _
blues / totalPixels )

outrgb.Pixel(x,y) = c
currentX = currentX + sectionWidth
Next
currentY = currenty + sectionHeight
goToY = min(currentY + yc, p.height - 1)
tmpy = currentY
Next

Return out
End Function

2 Comments »

December 3rd 2004

As per request

I got rid of the new layout :P

I also got sick of it rather quickly ;)

No Comments yet »

  • Current Status

    • Life: Jonathan tweeted Is Microsoft more environmentally friendly because Windows Recycles while OS X throws things away? (Updated 9 hours, 23 minutes ago)
  • Pages

  • Meta