How to use a single NSValueTransformer subclass to toggle the titles of multiple menu items - objective-c

I would like to make some bindings that toggle item titles in a popup menu based on a single numerical value in a text field. Let me explain:
This is my UI:
I want my menu items to automatically adjust to singular or plural based on the number in the text field. For example, when I type "1" in the box, I want the menu items to be labeled "minute", "hour" and "day". When I type "4", I want the menu items to be labeled "minutes", "hours" and "days".
What I did to date:
I bound the three menu item's labels to the same key path as the text field's value.
I created an NSValueTransformer subclass to interpret the value in the text field and return singular or plural to be used as item titles.
I applied this value transformer to the three bindings.
The issue:
My value transformer can either return singular or plural but it can't set the appropriate string based on the menu item it's applied to.
It looks to me like a value transformer is generic and can't return different values for different destinations. That would mean that to have the three titles change automatically, I would need to have three different value transformers that return the appropriate string for each menu item. That doesn't seem optimal at all.
Ideally I would be able to combine a string stored in the destination menu item (let's say in the item's tag property) with an "s" in the value transformer when the text field's value is larger than one, or something similar that would enable me to use a single value transformer for all the menu items.
Is there something I missed? What would be an ideal solution?

Okay, this is probably not an ideal solution, but something you could consider: if you set your value transformers from your code (and not in IB), you could instantiate 3 different transformers of the same class. You could give your value transformer an ivar NSString *unit (and add something like [[MyValueTransformer alloc] initWithUnit:]) to allow each to return their own string, but you still have to write the value transformer's code only once.
(Also, if you're ever going to consider making your application localizable, simply appending an "s" to create the plurals is not going to work. You could of course add ivars for both NSString *singular and NSString *plural to do that.)
Edit: Wait, I just realized you can register value transformers! If you register them as MyValueTransformerHours and MyValueTransformerMinutes (by manually allocating and initializing them in your code), you can use them from Interface Builder. See also https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ValueTransformers/Concepts/Registration.html#//apple_ref/doc/uid/20002166-BAJEAIEE.

Related

Using placeholder template in core data without saving the placeholders?

I am wondering if its possible to have a core data and use a NSFetchedResultsController to display template holders; without saving the placeholder template holder to core data.
I am writing an app where a table view will have the following characteristics
Maximum amount of rows (ie: 8)
Each cell uses a partial view, a single table cell instance with clickable buttons;
A user clicking on the buttons replaces the content for each button
When a user comes to save the data it stores the content in the exact places, but crucially it should not save the blank placeholder state; but still respect the placement positioning.
IE: Lets say a user picks the right button for cell 1 and saves it;
when the the user returns to this dataset sometime in the future, it
should have the imagery and data in the correct place; but still keep
the left button for cell 1 empty (placeholder)
The reason I don't want to save the placeholder content is because I consider this data to be "dirty"; its meaningless and has no place in a dataset; its a view; not data.
Currently:
I create data using insertInManagedObjectContext but do not save it until the user has pressed save.
Each matchRow has many fighters. This relationship is a NSOrderedSet, managed by core data.
The problems I'm having are;
NSFetchedResultsController only respects saved core data items; and ignores the placeholder data.
If a user only saves one (right button) data, the NSOrderedSet sees this as the first (left button) data; which is in correct
If I strip out all the placeholder structures from the core data in a pre-save action, the effect is that the order the user wanted is now lost and it causes a crash when reloading because the size of the arrays are incorrect.
Currently the only way around this is to stop using
NSFetchedResultsController and use a NSArray; and put the placeholders into the array too, then save everything, (dirty objects) and all.
I really don't want to do that. The placeholder content isn't meant to be saved.
I've been reading a blog post on using separate classes for special cases where he has different data sources; and uses the technique to separate class for the "empty" case, and to set it as the table view’s datasource when it's empty.
Whilst this is interesting, it only solves it for an empty case; when my requirement is that the partial view should handle all states; empty data and partial data.
One idea I have is that we need another entity between our record and our match rows;
Match - MatchRowMeta - Fighter
Not sure what the relationship would be
where;
RowMeta {
record.obj (relationship)
fighters.obj (relationship)
positionID (integer) - which button has been set
}
But I don't think this is the best way to do it; it seems expensive and a lot of heavy lifting to do something relatively simple.
Thus, my question:
Is it possible to have a table view made up of template holders; where the structure is saved to core data but none of the empty (dirty) objects are saved; plus NSFetchedResultsController will respect the structure; even when its empty or partially empty?
Edit: Added entity diagram

How to specify different editor widgets for the same column in Dojo DataGrid

I am wondering, is there an official way to specify a different widget editor for the same column in a DataGrid (different rows)?
I found dojox.grid.cells._MultipleEditor, but it is quite complicated and not officially supported.
This is for creating things like a property sheet with DataGrid.
EDIT: People seem to suggest using dgrid. However, I am not sure if dgrid has this feature. Also, unfortunately, ... drum roll... horror music... I must support IE6.
Well, there seems to be a way to do it. Doesn't seem to show much negative side effects (so far)...
Create one column for each value type, one after the other.
Tag each column with a CSS class to indicate its value type (via classes). For example: classes="multivalue int"
For each column, tag it with the correct editor widget and the appropriate constraint & options.
Put styles on each row (with onStyleRow) that correspond to each type. For example, add a type-int class to the row that has an int type.
Put in a CSS style that initially hides all the multi-valued cells:
.dojoxGridCell.multivalue { display:none; }
Un-hide all the cells with the correct type:
.dojoxGridRow.type-int .dojoxGridCell.multivalue.int
{
display:table-cell;
*display:block; /* For IE6/7 */
}
For this to work, obviously, each row must match exactly one column.
Obviously, you must set all these fields to the same property name. DataGrid allows you to do that.
Put display:none (via CSS etc.) on all the header cells of multi-valued columns except the first one. Otherwise, you'll end up with too many header cells.

Displaying dynamic kanban colors according to record state in OpenERP 7

could someone tell me in what way I can display the items in a view kanban with a specific color according to the state that is the record.
I'm trying something like this
<div t-attf-class="#{record.state=='scheduled' ? oe_kanban_color_#{kanban_getcolor(1)} : oe_kanban_color_#{kanban_getcolor(0)}">
but I looked ALL elements and not only those who are in the "scheduled".
Thanks :)
If you have copy/pasted exactly what you typed in the view definition, then your t-attf- class attribute is malformed, and all record will have the following class:
class="#{record.state=='scheduled' ? oe_kanban_color_1 : oe_kanban_color_0"
which, due to CSS class precedence, will cause them all to have the oe_kanban_color_1 style.
A few hints:
To avoid coloring some records, you can omit the oe_kanban_color_X entirely in some cases
You can use a t-att-class attribute to allow arbitrary Javascript expressions, depending on what you want to do. In contrast, t-attf-class only allows replacing placeholders.
When comparing field values with Javascript operators you normally want to use the value or raw_value of the field, rather that the Field object itself. value will only differ from raw_value when the value needs specific rendering, such as dates, numbers, etc.
The kanban_getcolor() function accepts any integer or string and returns one of the 10 default kanban color indexes.
Based on the above, the following might be closer to what you tried to do (note the t-att-class attribute:
<div t-att-class="record.state.value == 'scheduled' ?
'oe_kanban_color_1' :
'oe_kanban_color_0' ">
Alternatively, you could use t-attf-class and let kanban_getcolor() pick a color based on the state string:
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.state.value)}">
That last example is similar to what is done in many default kanban views in the official OpenERP distribution.

Enumeration in the dialog box

My tableViewController with a list of items of various types will provide a button to show a modal dialog box. This dialog box (similar to alert view) will provide the user with an exclusive choice from a list of 6 options.
Based on what the user chooses and confirms, the list in the main tableview controller screen will be filtered down to only show items that match the selected type.
At the moment, I have those six types listed in a typedefed enum. So far so good.
However I also need to be able to populate my custom dialog box with six nsstrings whose names will match the types used in the enumeration.
How to reconciliate this enum with my requirement for a source of those strings, but in such a way that I would ensure some level of consistency between the two? I do not want to hardcode anything.
You need a helper method that returns a string for each enum value. This should be written to deal with possible localization. All of your data and event handling should be based on the enum value. The string should be used for display.
The helper method should take an enum value and use a switch statement to return the proper string.
I can think of a few:
Change the enum to a bunch of strings. This makes things a bit tedious if they need to be integers too (-[NSArray indexOfObject:]).
Make a C array of strings. This lets you use C99's handy syntax:
NSString * const names[] = {
[Foo] = #"Foo",
[Bar] = #"Bar",
};
Autogenerated code to do the above.
Caveats:
Both of these will make i18n rather painful. This might not be relevant if it's contract work that will only need to be in one language, but it's Bad Practice.
Using button indexes as keys works until you decide you need to remove buttons in the middle. String keys work much better in the general case (I wrote a UIAlertView/UIActionSheet wrapper that accept (key,title) pairs and returned the key instead of the button index).
I take your remark that you "do not want to hardcode anything" to mean that you don't want any string constants in your code. So:
You could simply assign the strings to your sheet's UI elements (perhaps check boxes, for example) and give those UI elements tag values that match your enumeration (something you could query as your sheet closes). This has the additional benefit that you can easily localize the sheet.
Or:
If you want to keep the strings separate from your sheet, you could create a .strings file (perhaps you could call it Enumeration.strings or some such) formatted something like this:
"001" = "string one";
"002" = "string two";
.
.
"010" = "string ten";
and you could then retrieve the strings using your enumeration values like this:
NSString *myString = NSLocalizedStringFromTable([NSString stringWithFormat:#"%03d", myEnumerationValue], #"Enumeration", #"");
but then you'd have to have a way of plugging the strings into your UI, keeping track of UI elements through IBOutlets. Note that I used three decimal places here; perhaps you could get by with two, or even one. Finally, you get the ability to localize as in the first suggestion.

How do you make a Text Label display how many rows there are in the table

I am using Core Data and want a Text Label to display how many rows there are in the table, what code would I need to enter in the class file's to do this?
Assuming your NSTableView's columns are bound to an NSArrayController, you can bind the value of the NSTextField label to your array controller's with controller key "arrangedObjects" and with a key path of #count. If you want to bind the text field to something like "x rows" where x is the number of rows, you would bind the "Display Pattern Value1" to the same (arrangedObjects.#count) and use "%{value1}# rows" as the Display Pattern.
Set up a fetch request on your managed object context like you normally would, and call countForFetchRequest:. Don't forget to subscribe to NSManagedObjectContextObjectsDidChangeNotification so you can update it when objects are added or removed!