Saturday, December 16, 2017

#26 2009-09-27 06:12:22 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5200

Re: get value of tableview items from array controller

robdut wrote:

I just downloaded a fresh copy of your florida app and it does the same thing!


Guess who missed his own advice: make sure Handles Content as Compound Value is checked for the Array Controller's binding!


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#27 2009-09-27 08:47:27 pm

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Ok - it works. I think.

The two tables are now in sync without any weird behavior. I had to mess around with the array controller settings for the bindings and the attributes to get it right. I'll post the result if it all looks good tomorrow.

Thanks Shane. If this works it will have saved me many lines of code.

Rob

Offline

 

#28 2009-09-28 08:38:34 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Shane,

I thought I was out of the woods. The two tables are working perfectly in snyc.

In my app though, table 2  should be empty (no placeholders). Table one can have a placeholder representing the first set fine.

I have spent many hours trying to make this work.

First I tried initializing with this:

Applescript:

set my theData to {{backupset:"newset", sourcefiles:""}}

but weird things happen when you try to add new files to the list.

Applescript:

set sourcefiles of item actualSelectedRow of theOriginalData to :{{ filename:newFilename, filepath:newFilepath}}}

}

It adds the new row but then all the sets show the same new row in their list. The bugs go on...

double curly braces instead of "" in sourcefiles doesn't work at all.

I also tried using the placeholder text and replacing it with the new data, which works but then there are other bugs.

Should we be using NSMutableArray instance instead of a plain record to send to OBJ-c array controllers?

Stumped,  Rob

Offline

 

#29 2009-09-28 06:28:14 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5200

Re: get value of tableview items from array controller

robdut wrote:

double curly braces instead of "" in sourcefiles doesn't work at all.


That's what I'd expect to work, and does here in my (limited) testing.


but weird things happen when you try to add new files to the list.

Applescript:

set sourcefiles of item actualSelectedRow of theOriginalData to :{{ filename:newFilename, filepath:newFilepath}}}

}


Where does theOriginalData fit into the scheme of things?


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#30 2009-09-28 09:17:36 pm

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Shane Stanley wrote:

Where does theOriginalData fit into the scheme of things?


I was using "my thedata" referring to the variable bound to the array controllers content. I tried setting theOriginalData to my theData and did the changes to that and then set my theData back to theOriginalData at the end. It  seemed to work better that way. I tried both ways.

But using soucrefiles:"" and then trying to set soucrefiles in table 2 causes the all the sets in table 1 to also have added that record. You will see if you try it out.

Here is the project if you, or anyone else, wants to give it a try. It is just two tables that are bound. I commented out the "good" code if you want to see how it can run perfectly you can reconstitute the good code.  As is - I set it up for allowing an empty table 2 which is what I am struggling with here.

http://rdutoit.home.comcast.net/~rdutoi … s_test.zip

Thanks, Rob

Offline

 

#31 2009-09-28 11:29:11 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5200

Re: get value of tableview items from array controller

OK, you need to use sourcefiles:{} in each instance.

And you can also skip using theOriginalData if you follow up changes to theData like this:

Applescript:

       if bTableView's numberOfRows() = 0 then
           set sourcefiles of item actualSelectedRow of my theData to {{filename:"somefile", filePath:"pathtofile"}}
           set my theData to my theData -- registers change

In fact, this lets you do away with that whole test, replaced by:

Applescript:

       set end of sourcefiles of item actualSelectedRow of my theData to {filename:"somefile", filePath:"pathtofile"}
       set my theData to my theData

You can also set the selection in table 1 like this:

Applescript:

       set x to current application's class "NSIndexSet"'s indexSetWithIndex_(setSelection)
       aTableView's selectRowIndexes_byExtendingSelection_(x, false)

Hmmm, doing it that way you also need to trap for for when there's no selection in table 1 and someone hits Add for table 2. So maybe:

Applescript:

       if actualSelectedRow > 0 then
           set end of sourcefiles of item actualSelectedRow of my theData to {filename:"somefile", filePath:"pathtofile"}
           set my theData to my theData
           set x to current application's class "NSIndexSet"'s |indexSetWithIndex_|(setSelection)
           aTableView's selectRowIndexes_byExtendingSelection_(x, false)
       end if

And you need to capitalize the "P" in filePath in your binding of the second column of the second table.

You were so close...

Last edited by Shane Stanley (2009-09-28 11:37:27 pm)


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#32 2009-09-29 04:49:26 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Shane Stanley wrote:

OK, you need to use sourcefiles:{} in each instance.


I tried that and it didn't work...

Shane Stanley wrote:

In fact, this lets you do away with that whole test, replaced by:

Applescript:

       set end of sourcefiles of item actualSelectedRow of my theData to {filename:"somefile", filePath:"pathtofile"}
       set my theData to my theData


Brilliant. I knew there must be a way to place that more simply.

I actually tried "set my theData to my theData" to see if it would give everything a kick but no luck. But other things were off.

Shane Stanley wrote:

Applescript:

       set x to current application's class "NSIndexSet"'s indexSetWithIndex_(setSelection)
       aTableView's selectRowIndexes_byExtendingSelection_(x, false)


I looked up NSIndexSet and got scared - I had been doing pretty well with OBJ-C and Cocoa stuff till then.

Shane Stanley wrote:

And you need to capitalize the "P" in filePath in your binding of the second column of the second table.


I never would have seen that! One of the major mistakes I keep making is with punctuation. But you know- my applescript could get pretty sloppy with naming conventions and ASOC is forcing me to clean up my act.

Shane Stanley wrote:

You were so close...


A good lesson here; you can try things that will work along the way but you need to know why they are right to write code well.

I got burned out with bindings and lost my way, and missed some crucial things. You have been a great help Shane - thanks.

And this does show the really good possibilities with ASOC going forward- so much less code! I will put together the Two tables as an example project.

Rob

Offline

 

#33 2009-09-29 05:11:13 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Hi Shane,

I just found one more thing.

When you delete the last row in table 2, you can no longer add a new row. This one seems trickier since the remove call is built and we have no control over it. I'll ponder this... perhaps a manual remove handler instead.

Rob

Offline

 

#34 2009-09-29 05:43:59 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

And now - I can't add a new row to table 2 after editing the name of a row in table 1. That did work before.

Rob

Offline

 

#35 2009-09-29 06:04:55 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5200

Re: get value of tableview items from array controller

Yes, it looks like I was being too smart with "set end..." -- the remove is change a list of lists to a simple list. Change back to this:

Applescript:

           set sourcefiles of item actualSelectedRow of my theData to {{filename:"somefile", filePath:"pathtofile"}} & sourcefiles of item actualSelectedRow of my theData


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#36 2009-09-29 06:46:52 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

That does it. It is looking very stable now. Table 1 edits and table 2 removes cleanly....

My only last wish is that sets could be added to the end of the table 1, which is the expected behavior. I switched

Applescript:

set my theData to {{backupsets:"NewSet", sourcefiles:{}}} & my theData

to

Applescript:

set my theData to my theData & {{backupsets:"NewSet", sourcefiles:{}}}

and this seems to work now. You had mentioned that it may cause theData to become a pointer, or something like that?

Thanks, Shane

Rob

Offline

 

#37 2009-09-29 07:07:08 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5200

Re: get value of tableview items from array controller

It works because of the extra "set my theData to my theData" line.

It's been a bit of a battle, and you can see why bindings have a reputation for being fiddly. But even if you'd just used them to supply the data, and did the adding and deleting by code, I reckon they still beat fiddling with data sources and table delegates.  And some people are happy with just one table :-)


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#38 2009-09-30 05:37:49 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

A few subtleties with the near perfect two_tables_example project:

The one thing I hadn't tried was sorting the columns. An old friend appeared. In ASS list there were many posts about sorting a table and the datasource not reflecting the new order. The same appears here.

With a several sets created:
Sort table 1 and then select set 1
Add an item to table 2 and the item gets added to the last set, not the set you selected!

This is because our bound variable theData is not sorted as well.

I have looked at all the settings and can not find anything there. In ASS I remember getting the id of a row and then proceeding from there but I don't see id anywhere.


And unfortunately, setting the new set to the end still doesn't work- it causes buggy behavior even with

set my theData to my theData

I tried all sorts of trickery but can't put at the end.

It is not the end of the world if the new rows go to the end and sorting is off for table 1, but users will be asking why... etc.



rob

Offline

 

#39 2009-09-30 06:53:37 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5200

Re: get value of tableview items from array controller

robdut wrote:

The one thing I hadn't tried was sorting the columns. An old friend appeared. In ASS list there were many posts about sorting a table and the datasource not reflecting the new order. The same appears here.


Yes, the sorting doesn't go back to theData. The array controller has an arrangedObjects method; perhaps you can call that, add/insert to what it returns, and set theData to the result.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#40 2009-10-01 04:33:50 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Just for completeness here is the solution to getting the sorted item in a table.

the newFilepath variable is retrieved from an open file dialog and then we get the filename and icon

Applescript:

set newFilename to do shell script ("basename " & quoted form of newFilepath)
       
set theIconImage to NSWorkspace's sharedWorkspace()'s iconForFile_(newFilepath)

Then - instead of accessing theData variable (which is bound to the array controller's content) we ask the array controller itself for its arranged objects, and as the name suggests, that is the sorted array.

Then we get the objectAtIndex which is the particular selected object (or the record's item) in the Array. And ask it for it's valueForKey_("sourcefiles") which is the key in the array containing another array which is the record of items displayed in table 2. This can then be added to with a new record for the new row we want to add to table 2.

Applescript:

if actualSelectedRow > 0 then
    set indexnum to FileSet's selectionIndex()
    set theOldArraysValues to FileSet's arrangedObjects()'s objectAtIndex_(indexnum)
    set theOldTableValues to theOldArraysValues's valueForKey_("sourcefiles")
    set theNewTableValues to {{fileicon:theIconImage, filename:newFilename, pathtofile:newFilepath}} & theOldTableValues
    theOldArraysValues's setValue_forKey_(theNewTableValues, "sourcefiles")
end if

All along I was sure this would never work - that I would have to create an array object first to send to the Array Controller's Array. But, as Shane suggested, it seems we can use a plain old applescript record which we AS folks all know and love.

Now I have two tables connected with bindings using about ten lines of code, and only the code needed to add items to them! This creates a "Source List" style of app where data in the right table is tied to the "source" items in left table.

After years of struggling with two tables in ASS, this is a miracle, to me any ways. And being able to write one line of code to get the file's icon without needing a separate OBJ-C class file is cool too.

Thanks everyone for helping me to solve this.

I already posted the new sample app but here it is:

http://rdutoit.home.comcast.net/~rdutoi … sample.zip

Rob

Last edited by robdut (2009-10-01 04:35:57 am)

Offline

 

#41 2009-10-02 09:59:00 pm

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Ok, I have my two table sample working great, So now I want to save the table data.

I try saving it to user defaults simply but realized I have set my record to contain image objects

Applescript:

set theValue to NSWorkspace's sharedWorkspace()'s iconForFile_(newFilepath)
set theNewTableValues to {{fileicon:theValue, filename:newFilename, pathtofile:newFilepath, filesize:"---"}} & theOldTableValues

This creates weird corrupt plist files. So I remove the images and it all works.

Then I try adding in the images at run time and removing them at quit. That works but the defaults plist is being written to during runtime and the odd plist files are created as I add rows to the table etc...

So forget User defaults. Can I write these records to file somehow, including the image objects? Remember we are dealing with a record here...

Applescript:

{{backupset:"newBackupset", sourcefiles:{{fileicon:theValue, filename:newFilename, pathtofile:newFilepath, filesize:"---"}}}}

I have tried to convert it to NSMutableArray with no luck. This is an OBJ-C area that really confuses me.

I also read that you can have a datasource for a table that uses bindings but can't get that to work so far. I figured I could then use the table datasource methods to set the images as Craig does in booklist example.

So close again but not sure of what direction to take this. Any guidance appreciated.

Rob

Offline

 

#42 2009-10-03 07:05:31 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

I should really start a new thread here but...

It isn't the image that causes the corrupted plist file. It is the open panel!

my plist file name is normally
com.rdutoit.backuplistc.plist

When the open panel gets called:

Applescript:

set openPanel to current application's class "NSOpenPanel"'s openPanel()
       tell openPanel
           set allowsMultipleSelection of it to true
           set canChooseDirectories of it to true
           set allowsOtherFileTypes of it to true
           runModal()
           set fileUrl to |URL| of it
           if fileUrl is missing value then
               return
           end if
           set newFilepath to |path| of fileUrl as text -- Error occurs without 'as text'
end tell

When I press the "add" button it triggers the above open panel call. At that moment and after accepting a choice in the open panel,  endless new defaults plist files are generated with a names like

com.rdutoit.backuplistc.plist.7gSYoM7
com.rdutoit.backuplistc.plist.0XVtcPM
etc.

They are corrupted files!

I suspect something odd is happening with the URL word?

Anyone have a clue here.

I am suing this for defaults write:



Applescript:

-- on Awake from nib
tell NSUserDefaults of current application
   tell its standardUserDefaults()
       set storedDataArray to its arrayForKey_("theArrayRecord")
       set my theData to storedDataArray
       if my theData is in {"", missing value} then set my theData to {{backupset:"newBackupset",sourcefiles:{}}}
   end tell
end tell

-- on quit
tell NSUserDefaults of current application
   tell its standardUserDefaults()
       its setObject_forKey_( my theData, "theArrayRecord")
   end tell
end tell

Rob

Offline

 

#43 2009-10-03 07:15:03 am

tellboy
Member
Registered: 2005-06-23
Posts: 152

Re: get value of tableview items from array controller

Hi Rob,

Not really sure of why you have a problem but I have used this snippet without any problems:

It may help


All the best

Terry

Applescript:



       tell class "NSOpenPanel" of current application to set myOpenPanel to its openPanel
       
       myOpenPanel's setAllowsMultipleSelection_(false)
       myOpenPanel's setCanChooseFiles_(true)
       myOpenPanel's setCanChooseDirectories_(false)
       
       myOpenPanel's runModal
       
       set tFileArray to myOpenPanel's filenames()
       set tFilepath to tFileArray's objectAtIndex_(0)
       tell MyView to setImageWithPath_(tFilepath)


Filed under: NSOpenPanel

Offline

 

#44 2009-10-06 06:58:04 pm

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Hi All,
Back with my two tables experiment. All is well and I am trying to now save the table data. USer defaults weren't working for reasons I posted earlier so I tried "writeToFile" which seems to be working. Here it reads in the file and then writes out.

Applescript:

on awakeFromNib()
       set theNewArray to NSMutableArray's alloc()'s initWithContentsOfFile_(FILE_PATH)
       if theNewArray is equal to missing value then
           set theNewArray to NSMutableArray's alloc()'s init()
           set theData to {{backupset:"newBackupset", sourcefiles:{}}}
           theNewArray's addObjectsFromArray_(theData)
           set my theData to theNewArray
       else
           --workaround for empty image column. We set the images one by one!
           set my theData to theNewArray
           my addImagesAfterArchiving()
       end if
       set my theData to my theData
   end awakeFromNib

on writeToFile()
       set theNewAnotherArray to NSMutableArray's alloc()'s init()
       theNewAnotherArray's addObjectsFromArray_(my theData)
       if not theNewAnotherArray's writeToFile_atomically_(FILE_PATH, true) then
           set messageText to "There was an error writing to file"
           display dialog messageText buttons {"Ok"} default button 1
       end if
end writeToFile

What confuses me is I am using a record but then it gets turned into an array so it will archive. This seems to work. One little bug though is if you add a new set to table one and try to quit without editing the set name, it throws the "WriteToFile" error and doesn't retain the new entry.

Applescript:

on addSets_(sender)
       set my theData to {{backupset:"newBackupset", sourcefiles:{}}} & my theData
       set my theData to my theData
end addSets_

Somehow the new entry is seen as something foreign by writeToFile_atomically?

It isn't the end of the world but makes me nervous. Any thoughts appreciated, or thoughts about a better archiving method.

Thanks, Rob

Offline

 

#45 2009-10-06 07:49:44 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5200

Re: get value of tableview items from array controller

Try logging the value of theNewAnotherArray when you get the error. My guess is that having sourcefiles as {} is causing the problem, although I can't see an obvious alternative.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#46 2009-10-07 08:09:42 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Shane Stanley wrote:

Try logging the value of theNewAnotherArray when you get the error. My guess is that having sourcefiles as {} is causing the problem, although I can't see an obvious alternative.


The log shows something interesting

Applescript:

on applicationShouldTerminate_(sender)
       --before archiving, we need to clear out all the image objects
       my removeImagesBeforeArchiving()
       my writeToFile()
       return true
end applicationShouldTerminate_

on removeImagesBeforeArchiving()
       set theOldArraysValues to Backset's arrangedObjects()
       repeat with i from 1 to count of theOldArraysValues
           set theSourceItems to Backset's arrangedObjects()'s objectAtIndex_(i - 1)'s valueForKey_("sourcefiles")
           repeat with j from 1 to count of theSourceItems
               set theSourceItemsObject to theSourceItems's objectAtIndex_(j - 1)
--here we remove the image and set fileicon to ""
               theSourceItemsObject's setValue_forKey_("", "fileicon")
           end repeat
       end repeat
       log theOldArraysValues
end removeImagesBeforeArchiving

You can see that, on terminate, the images are removed so the array can be archived (I tried NSCoding etc. with no luck.)

So when a new item is added to table 1 and you quit without editing that items name, it returns the array with images in it even though removeImagesBeforeArchiving() is called. Then the error happens. When you edit the new item in table 1 or do anything there, it returns the image-less array which is archived fine.

I have tried numerous ways of triggering the array into the current form but no luck yet.

Cheers,  Rob

Offline

 

#47 2009-10-07 05:27:12 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5200

Re: get value of tableview items from array controller

Can you try something like changing the selection when quitting?


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#48 2009-10-07 07:49:24 pm

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

Shane Stanley wrote:

Can you try something like changing the selection when quitting?


I tried that and no luck but this works

Applescript:

on writeToFile()
       set theCurrentArrayValues to Backset's arrangedObjects()
       set theNewAnotherArray to NSMutableArray's alloc()'s init()
       theNewAnotherArray's addObjectsFromArray_(theCurrentArrayValues)
       if not theNewAnotherArray's writeToFile_atomically_(FILE_PATH, true) then
           set messageText to "There was an error writing to file"
           display dialog messageText buttons {"Ok"} default button 1
       end if
end writeToFile

That makes sense since I change the images to "" in Backset's arrangedObjects(). It is theData variable that isn't getting updated yet.

What I don't understand is why this doesn't work as well:

Applescript:

on writeToFile()
       set theCurrentArrayValues to Backset's arrangedObjects()
       if not theCurrentArrayValues y's writeToFile_atomically_(FILE_PATH, true) then
           set messageText to "There was an error writing to file"
           display dialog messageText buttons {"Ok"} default button 1
       end if
end writeToFile

Isn't Backset's arrangedObjects() an array? Why do I have to create new array and then add that to it to pass to writeToFile?

Well, It's solved now. The archive works and the table bindings are incredibly fast, even with dozens of files and images added and with hardly any code!

Now if I can only add drag and drop to the table - so far no luck. There are six datasource methods! I may have to make aOBJ-C class for that one.

Thanks, Shane

Rob

Last edited by robdut (2009-10-07 07:49:54 pm)

Offline

 

#49 2009-10-07 08:02:59 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5200

Re: get value of tableview items from array controller

Could it be that something requires an NSMutableArray and you were passing an immutable one?


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#50 2009-10-08 04:24:23 am

robdut
Member
Registered: 2009-09-02
Posts: 301

Re: get value of tableview items from array controller

I thought of that. I think I read somewhere that NSAArrayController's arrangedObjects returns a plain Array... though you can change the values of it with setValue_forKey_ so maybe not. Is there a way in cocoa to log what class something is?

Or perhaps we need to pass the writeToFile an new instance of the Array and not the results of the array controller itself?

Rob

Last edited by robdut (2009-10-08 04:26:34 am)

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)