Bundling a custom dialog window into a class

I’ve put together a set of routines that communicates with a remote API via an HTTPsocket , and would like to have everything bundled into a single class. What seemed to be the most obvious choice was to make a subclass of the HTTPsocket, and add all of the routines to that. However, I’ve encountered a problem. There’s a situation where the user must be presented with a dialog that contains a listbox where the user must select one item. In my original project this wasn’t a problem. I just created this dialog as a window with all of the necessary controls and called it from the main application window code. But I’d like to have this as part of the HTTPsocket subclass if possible. It doesn’t appear to be possible to add a window to the HTTPsocket subclass, and I don’t know if it’s possible to create a dialog window on the fly in code (other than a simple message dialog). Is it possible to do this?

Of course you can.
Create your dialog as, for example, a Movable Modal Window containing all the needed controls.
To show the dialog simply create an instance of your window using the New operator and use the Window.ShowModal method: program execution will resume when the dialog gets closed.

Robert wants I think to have only one item in the project and create the window only with code.
I don’t see how it’s possible, out of messageDialog method.

The window has to be a separate class.
If you just looking to simplify the packing you might be able to put both your HTTPSocket subclass and Window class inside a module.

[quote=452066:@Jean-Yves Pochez]Robert wants I think to have only one item in the project and create the window only with code.
I don’t see how it’s possible, out of messageDialog method.[/quote]

Robert seems not new to Xojo so I suppose he know a window of any kind can’t be constructed on the fly only with code .

[quote=452067:@Kevin Gale]The window has to be a separate class.
If you just looking to simplify the packing you might be able to put both your HTTPSocket subclass and Window class inside a module.[/quote]
I’d been thinking of a module too, but it doesn’t appear that I can add a window to a module.

It’s true that I’ve been using Xojo (and RealBasic) for many years, but there are a lot of things that I’ve never touched on. So, I wasn’t absolutely sure that I couldn’t construct a window in code. Now that it’s confirmed, it looks as if my best alternative is to use the dialog window itself as the overall entity to group the code and controls. The dialog will just remain hidden unless user input is required.

Windows are very odd items and thats one reason you cant put a window into a module
https://web.archive.org/web/20071024004133/http://ramblings.aaronballman.com/2007/06/windows_a_weird_odyssey.html

I’m not in the position to suggest you how to write your code and I don’t know what is your application goal.
There are so many different way to write code for the same task.
Use what your knowledge suggest and ask if you need for a different view.

[quote=452147:@Maurizio Rossi]I’m not in the position to suggest you how to write your code and I don’t know what is your application goal.
There are so many different way to write code for the same task.[/quote]
Yes, you’re absolutely right. So some further explanation is in order.

The purpose of this little project is to get an Audio CD track list when the user loads an Audio CD into the CD/DVD drive. This is done automatically on MacOS by iTunes, assuming that you haven’t expunged iTunes from your computer, in a fit of rage. In lieu of iTunes, there are at least two free online database servers that provide this information: freedb.org, and musicbrainz.org. In either case, it’s necessary to read the CD’s hidden .toc.plist file and use that info to generate a discID code that is sent to the server.

BTW, credit to Norman for his example project for detecting Audio CDs:
http://great-white-software.com/gws-rb-samples/AudioCDOSX.zip

I’ve already sorted out freedb.org, so my concern at the moment is with musicbrainz.org protocol, which is a two step procedure.

  1. You send it a search query with the discID, and it responds with a release list containing a single (hopefully) release: your CD (a releaseID and title only, and no track list unfortunately).
  2. You send a second search query with the releaseID that the server returned in the first query, in order to retrieve the actual track list.

In some cases, because the discID is just a hash code, Step 1 can result in multiple CD releases being returned. This is where the dialog comes in. The user is now presented with a dialog box with a list of CD titles. The user selects the one with the correct title, and the routine continues with step 2 to get the track list.

I prefer to hide this multiple release complication from the main application which only wants to see a final single track list. This is why the listbox dialog needs to be part of the server lookup procedure.

I’ve now refactored the code so that it’s all part of the dialog window, and it seems to work. I must admit that I was a bit apprehensive about this line of code:

self.showmodal

but remarkably, it did what I wanted.

Anyway, I’d be interested to hear how others would approach this.

Like you, I design communication classes whenever I work with an API. I once tried to use a subclass of the socket, but found I limited myself that way. What I found works best is to use a wrapper class. The wrapper class has a private scoped property to hold a queue of sockets.

I also work with the asynchronous methods to prevent the need for ShowModal which stops execution and locks up the rest of the UI. This all ends up being a little more work, as you’ll need to AddHandler hook into the events. However, I can assure it is very much worth the time. You can make things like fetching the tracklist super easy to do.

Based on your description of how the musicbrainz API works I might:

[code]0. clsBrainz handles preparing, sending, parsing of API interactions with musicbrainz

  1. clsBrainz.RequestTracklist(discID as String) function accepts the discID and requests the releaseID list from musicbrainz

  2. musicbrainz responds, clsBrainz parses

  3. if one releaseID skip to step 8 with releaseID || if multiple releaseID raise event

  4. Event clsBrainz.TracklistRequestSelectRelease(arsReleaseIDs() as String) is raised which

  5. EventHandler for the instance of clsBrainz constructs selection window and loads it with releases

  6. User selects release from window

  7. Event handler from user selection (Button.Action or however you implement the window) requests tracklist using release id

  8. clsBrainz.RequestTracklistWithRelease(releaseID as String) accepts the release ID and requests the tracklist from musicbrainz

  9. musicbrainz responds, clsBrainz parses

  10. Event clsBrainz.TracklistReceived(discID as String, releaseID as String, jsTracklist as JSONItem) raised

  11. EventHandler for the instance of clsBrainz takes the jsTracklist to where it needs to go[/code]

I wouldn’t worry myself with trying to bundle the window into the class. As Norman linked, it’s not possible within Xojo at the moment; and trying to come up with clever packaging isn’t what I would spend my time on. I would just take the advice others have mentioned and use a folder.

The design I outlined separates the data from the UI. clsBrainz can operate without the window (though admittedly not for multiple releases, but it will compile). The event handlers on the instance of clsBrainz take the data and send it to the UI. The API class doesn’t require the UI.

Designing the API interaction with the asynchronous methods and separating the class from the UI has a couple of advantages. I can quickly and easily implement API interaction UI, and variations of. I can also take the very same class and create chained functions like fetching the tracklist. I’ve also found that once you implement one endpoint, implementing others is very easy.

If the design permits with synchronous functions, a similar wrapper => sockets design can be used for synchronous requests. This lends itself to being used within threads quite easily. Though I’m not sure how much to trust that, the synchronous calls rely on App.DoEvents.

This is exactly the way that I do it. I let the Window be the module/class and add all of the associated code and assets to the window.

As you discovered, .ShowModal is used when you want the window to interrupt the main loop’s flow. I’ll wager that you would find its functionality useful in some of your older projects if you go back and look at them with an eye toward refactoring to the current (19r1.1) Xojo.