macOS Save and Open Dialog Classes for accessing more properties

FWIW, I did just test using a pagepanel and that works just fine, and you can even change the height of the panel to match your requirements.

I don’t get what you want to do with the page panel. Multiple filetypes use each setting. For example almost all of them use missing value, a lot use encoding. A completely different set use transpose etc. As far as I’m aware you couldn’t have a control on more than one panel. Am I wrong? Can one control be in different locations on two or more pages of the panel?

If you are talking about stepping through the options page by page until you have specified all of them Wizzard style its not something I would ever use in an app? Here are 6 variations of the same dialog based on different file types:






I’m talking about one set of controls per type. The page panel doesn’t have to cover the entire space either. The common items could be at the top and the things that change at the bottom if you want.

But yes if the page panel was the full size, you’d need to have a different control for each, but it would be easy enough to have the controls set properties, such that common items on each panel would write to the same property. It would be safer that way too as when a container is closing, properties are usually still there while controls are usually in the process of being closed and may even be nil.

I’m not sure that is going to work. There is not one single control that is on every variety of the panel. Nor is there an order that makes things sticky, apart from the FileType, even that is only common to saving and not opening.

As for duplicating controls the matrix is as follows:

There would be 4 panels:

  1. TXT / CSV
  2. XLSX / DIF
  3. OXD
  4. DBF

Just giving it a try now.

OK, the page panel works well. However, changing the accessory view after it has been used once fraught with issues.

I made the view visible on my main window in order to figure out what could be happening with things, once it is assigned to the accessory view property and the dialog opens the original view disappears from the make window. Attempts to move things on the view are completely ignored. It becomes sticky, as if it is locked in some way. The two types of window look like this, import:

Export:

Which is all fine so long as you start from a brand new main application window each time, in other words a fresh copy of the container control that makes the accessory view. I’m just about to start looking at dynamically adding and removing a container control to the main window as required, which would give me a solid foundation to build on.

Yes, that solves all the problems. Each time you use the thing is it automatically back in its base state and is able to be adjusted correctly prior to assigning to the dialog. When the dialog is closed remember any details from it and then dispose of it correctly.

Add a property of say called AccessoryPanel of the type of your DesktopContainer.

Private Property AccessoryPanel As conLoadSaveOptions

In the code where you are instantiating the NSOpenPanelGTO or NSSavePanelGTO. do the following:

AccessoryPanel = New conLoadSaveOptions ' my Desktopcontainer class
AccessoryPanel.LockLeft = false ' lock it so as it keep it off the edge of the window
AccessoryPanel.LockRight = true
AccessoryPanel.EmbedWithin self, self.width + 20, 324, 800, 276 ' Add it off the edge of the window

Now you can assign properties to AccessoryPanel as you wish.

mDialog.AccessoryView = AccessoryPanel ' Assign it to the dialog.

Now in the items selected method you need to dispose of the container

Private Sub NSSavePanel_ItemsSelected(obj as NSSavePanelGTO, items() as FolderItem)
    'UpdateFileList(items)
  
  'label1.Text = "Option 1: " + SaveAccessories1.Option1Value.ToString + _
  '" Option 2: " + SaveAccessories1.Option2Value.ToString
  
  mDialog = Nil
  AccessoryPanel.Close ' close it out from the window
  AccessoryPanel = Nil ' clear the property for next time.
End Sub

I forgot to add that you have to couple up a method for the FileTypeChanged event on the panel. I’ve made all those changes to my branch of the source and generated a pull request for review. I’m certainly open to improvements?

The latest “exciting” update. There seems to be nothing I can do to cause a canvas to repaint itself within the accessory view. All attempts simply do nothing. I’ve tried a simple blank canvas object and the following in the paint event:

Sub Paint(g As Graphics, areas() As Rect) Handles Paint
  Static a As Integer = 0 
  a = a + 1
  If a = 1 Then
    g.DrawingColor = Color.black
  ElseIf a = 2 Then
    g.DrawingColor = Color.red
  ElseIf a=3 Then
    g.DrawingColor = Color.green
  End If
  g.FillRectangle 0,0, Me.Width,Me.Height
End Sub

even a button with a Canvas1.Refresh( true ) fails to draw anything.

I’ve tried triggering the event via declares, nope.

So, I’ve no idea why my canvas example above didn’t work. But I do now find that my control had implemented a paint event that only drew a box and then didn’t call the other elements drawing routines. Once I fixed that it now updates correctly most of the time. I do occasionally get IO Errors, which I have a lead on. So far all is looking good.

The major step forward was when I switched to a new DesktopContainer added by code between uses of the dialog, it prevented too many mad issues. Doing it that was would also allow you to have custom constructors for the DesktopContainer and lessen the memory footprint when the dialog is not in use.

Well I spoke too soon. Having code in the paint event of a control seems to have issues when embedded with the dialog. To be more precise I have a DesktopContainer within the DesktopContainer, ie my grid control within the DesktopContainer that is the accessoryview for the dialog. Painting in the top level of the grid works every time, but painting in the sub-controls seems to have a problem. The code seems to execute well enough, the graphics context is correct as fas as I can see, but the contents does not get transferred to the screen. This seems to include self drawn items or standard controls, like scrollbars.

My grid control consists of a DesktopContainer, which contains a canvas (for the grid data), a vertical and horizontal scrollbar and an edit field for data editing. There is a tiny amount of code in the Container paint event to draw a rectangle around the control, if required. The grid is all drawn in the canvas’ paint event. Obviously the scrollbars draw themselves. When used within the dialog the container paint operates correctly, the canvas paint is called and draws correctly not showing on screen. The scrollbars fail to paint also.

I’ve used the control many times within a container so that’s not the issue, it must be to do with the dialog box.

OK, I’ve now got to the bottom of my issue with his item and it’s quite odd. Consider the following container control.

On the right hand side is a second container control. In it is a canvas and a pair of scrollbars. All fairly normal. However, when I use that in an accessory view of the NSFileOpenDialog I have discovered a small problem. Which I have finally been able to work out. Any painting code in the container prevents the controls within the container from drawing at all.

OK consider the organisation of the container (right hand side)

Container
   Canvas
   Vscroll
   Hscroll

The events are as follows:

Container
   - Paint event, if required draws a bounding rectangle around the control.
   Canvas
      - Paint event, draws my grid contents
   Vscroll
   Hscroll

Any drawing in the container paint event prevents any output from the Canvas paint event from being drawn and even prevents the Vscroll and Hscroll controls from drawing. Don’t draw in the Container paint event and everything works correctly. Rather odd but at least I can proceed.

I’m not saying that the canvas paint event doesn’t happen, it does. You can trace the code perfectly step by step drawing its contents. The only thing is nothing is drawn when it completes. Only the container paint output is presented.

Updated my pull request to implement ShowModal method and add recommendation to use Timer.CallLater when using NSSavePanel_ItemsSelected after closeout of dialog.

@Greg_O I’ve one last particularly annoying problem with this system and it relates to UTIs.

I’m passing in a Filetype I’ve built for text files. It had an identifier of “public.plain-text” and I’ve specified “.txt;.text” as extensions. The problem is that the dialog reads the UTI from the system and includes all sorts of additional extensions that derive from “public.plain-text”, for example, a “.sql” file with the following UTI tree:

    "com.barebones.bbedit.sql-source",
    "public.source-code",
    "public.plain-text",
    "public.text",
    "public.data",
    "public.item",
    "public.content"

Do you know of any way to limit the extensions provided or to use the Xojo Filtype rather than reading from the system.

Not home at the moment, but I seem to remember that one of the delegate methods lets you determine on a file by file basis if they are enabled.

Yes, but it is super slow. Nothing urgent. The system works really well and I’ve got it doing everything I want apart from this extension issue.

I’m looking at tweaking the UTI after it is returned. Alternatively building one from scratch.

Try making one uti per extension. I don’t think that they officially support more than one.

One UTI, two extensions. Not the other way round.

Right, but what I was thinking you could try is two UTI entries in the IDE, each with one extension. I don’t know if they support more than one at a time.

It works perfectly with the built in Filetype and Open dialog methods. It doesn’t work when provided to your mechanism. The FileType editor supports multiple extensions per filetype. I’ll try splitting it, just in case the IDE is splitting it up under the skin.

Just out of curiosity, what’s the state of the “unique to my app” checkbox on the type definition?

It doesn’t work either if I take it down to just .txt. Here is the filetype panel:

The file browser still shows .sql files. As you can see the unique checkbox is off. I don’t claim to own txt files.

Wackier and wackier. I’ve just discovered that it is also including .php files too. Likely anything that conforms to “public.plain-text”.