Limiting NSTableView to two selections - objective-c

I am wondering if anyone has a method to limiting the number of selections allowed in an NSTableView to 2 concurrent selections. I am trying to calculate the delta between two selected values and would like for it to only select two at a time.
I was thinking of trying to keep track of what has been selected so that I can programmatically unselect anything if the selection expands above two, but this seems kludgy and possibly not as easy as it sounds.

Implement the delegate method tableView:shouldSelectRow: and return NO if you don't think the user should be allowed to select the row. For any reason you decide - for instance because the number of selected rows is already 2.
To get the number of currently selected rows at any given time, just call selectedRowIndexes on the table view (not the delegate, nor data source). This will give you an NSIndexSet, which has a count method with the information you are looking for.
The index set also holds the information about the other row indexes already selected, in case you want to deselect them.
Not knowing anything about the app, the user experience sounds a bit... strange. It is easy enough to implement, though, so no harm done in trying it out.

In your Table View's delegate you can implement -[<NSTableViewDelegate> tableViewSelectionDidChange:(NSNotification *)]
Maybe something like this:
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
switch ([notification.object numberOfSelectedRows]) {
case 0: break; // Nothing is selected
case 1: break; // Only one row selected
case 2: break; // Two rows
default:
... unselect rows ...
break;
}
}
Of course you can also use an if statement. Maybe you also want to store in which order the rows are clicked—this could be done in the cases one and two.

Thank you both for coming up with something to help jog my brain into the right direction. I started exploring the NSTableViewDelegate a little bit more hoping to find something to help with this and re-read this method: tableView:shouldSelectRow and it allows me to permit or reject the row selection. So now I can simply reject selecting a third row provided I have 2 already selected:
- (BOOL)tableView:(NSTableView *)aTableView shouldSelectRow:(NSInteger)rowIndex
{
BOOL returnValue = YES;
if (_timeStampList.selectedRowIndexes.count >= 2)
returnValue = NO;
return returnValue;
}
I'll have to work on it some more to get exactly the behavior I want because with this small snippet it just rejects the user from selecting anything more; kind of abrupt about it too. So I'll probably add some more code to allow the user to select a new row while auto-un-selecting something else.
Thanks again!

Related

Best Pattern Applyable to Sudoku?

I'm trying to make a Sudoku game, and I gathered the following validations to each number inserted:
Number must be between 1 and 9;
Number must be unique in the line;
Number must be unique in the column;
Number must be unique in the sub-matrix.
As I'm repeating too much the "Number must be unique in..." rule, I made the following design:
There are 3 kinds of groups, ColumnGroup, LineGroup, and SubMatrixGroup (all of them implement the GroupInterface);
GroupInterface has a method public boolean validate(Integer number);
Each cell is related to 3 groups, and it must be unique between the groups, if any of them doesn't evaluate to true, number isn't allowed;
Each cell is an observable, making the group an observer, that reacts to one Cell change attempt.
And that s*cks.
I can't find what's wrong with my design. I just got stuck with it.
Any ideas of how I can make it work?
Where is it over-objectified? I can feel it too, maybe there is another solution that would be more simple than that...
Instead of having 3 validator classes, an abstract GroupInterface, an observable, etc., you can do it with a single function.
Pseudocode ahead:
bool setCell(int cellX, int cellY, int cellValue)
{
m_cells[x][y] = cellValue;
if (!isRowValid(y) || !isColumnValid(x) || !isSubMatrixValid(x, y))
{
m_cells[x][y] = null; // or 0 or however you represent an empty cell
return false;
}
return true;
}
What is the difference between a ColumnGroup, LineGroup and SubMatrixGroup? IMO, these three should simply be instances of a generic "Group" type, as the type of the group changes nothing - it doesn't even need to be noted.
It sounds like you want to create a checker ("user attempted to write number X"), not a solver. For this, your observable pattern sounds OK (with the change mentioned above).
Here (link) is an example of a simple sudoku solver using the above-mentioned "group" approach.

Objective-c dynamically loading more UITableViewCells

I am writing a iPhone app that calls a web service. Let say the web service returns 1000 elements in the json object. I don't want to load all 1000 of them since parsing can take some time. What I would like to do is load the first 15 elements of the NSDictionary that I created from the json object and then when the user scrolls to the bottom of the tableview have a 16th row that says "load more....". Since I already have all of the data stored in the NSDictionary object is there a way to break this up so that it returns the 15, then the user clicks "load more...." and it loads the next 15 and continues until there are no more elements in the NSDictionary? I can present examples of my code but I am wondering if anyone has an example of how to accomplish this. Thanks in advance for any assistance.
i think a UITableView does this for you. Only the visible cells are ever constructed. Their memory is then swapped with the next rows as you scroll down. I don't see a point in re-inventing the wheel.
Also as a note, only the visible cells are "parsed" as you put it. It will not construct a cell for every item in your datasource on load.
Assuming I hear you correctly I would say you just need a little tricky logic to get this working
I would simply maintain an index offset which I would multiply by the amount of rows you want to show at any time(15 in your case)
Your logic is to always return the amount of rows that you want to allow + 1 for the final. ex: return _indexOffset * 15 + 1; //for your numberOfRowsForSection
In your didSelectIndexPathOf you check if you're the last row:
if(indexPath.row == _indexOffset * 15)
{
_indexOffset ++;
[tableView reloadData];
}
This isn't an exact answer but I think it can get you started

What is the best way to read input from keyboard using SDL?

I'm running an update() method n times per second to "update" the keyboard input from the user so I can read it later in the logic part of the program. So I find two ways of implementing this in the SDL Docs and I'm not sure which one should I use.
1; Loop for all events using SDL_PollEvent searching for key down/up events and saving the key states in a map so I can check for each key state in the logic of the program.
Note: Alternatively, I can also use SDL_PeepEvents instead of SDL_PollEvent to take only the event types that matter; so, it would not "thrown away" the events on the queue.
std::map<int, bool> keyboard; // Saves the state(true=pressed; false=released) of each SDL_Key.
void update()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
keyboard[event.key.keysym.sym] = false;
break;
case SDL_KEYUP:
keyboard[event.key.keysym.sym] = true;
break;
}
}
}
2; Taking a snapshot from the keyboard each frame so I can read it easily.
Uint8* keyboard;
void update()
{
SDL_PumpEvents();
keyboard = SDL_GetKeyState(NULL);
}
With any of above implementations I can read keyboard just like this:
if (key_map[SDLK_Return]) printf("Return has been pressed.");
Also, is there another way to do so?
I prefer to do a variation of 1, where I fill three arrays, indicating not only the current state, but also which keys just went down and which keys just went up. This allows me to easily check for those events in code (without comparing to the previous snapshot), but, most importantly, it won't miss events that last less than a frame. For example, if your game is running at 10 fps due to a slow machine, the user might press and release an important key between two calls of your update routine, and then your system will never register it. This is extremely frustrating.
SDL also sends key events when the key is held down, which allow you to have multiple key down events for each key up. I find this particularly useful when implementing keyboard scrolling through a list of items, e.g. a keyboard-controlled menu.
You should use solution 2.
Why? As SDL_GetKeyState() docs point out, before using it you are expected to call SDL_PumpEvents() to update the state array.
When you are calling SDL_PollEvent(), it implicitly calls SDL_PumpEvents(). So, it basically updates the array for SDL_GetKeyState() anyway. By parsing these events manually, you just create a second array (well, actually a much slower map) holding the same information which SDL already collected for you.
So, I would dare say that first solution means doing the same thing twice. And if you ever decide to support things such as repeated keystrokes (SDL_EnableKeyRepeat()), you'll be reimplementing even a larger part of SDL.
I realize this question is quite old, but my answer could benefit someone. Personally, I use two arrays with SDL_GetKeyState. I store one array holding the current frame's keyboard state, and one array holding that last frame's keyboard state. (With some memcpy commands, it's really easy to update them.) Along with those two arrays, I have a map that converts strings like "A" to the SDL scancode values, but that is optional.
Then, when you need to check if something is released or pressed, you can combine the two arrays to check. (I made this a function.) For example, if you know that the key is pressed this frame, but wasn't pressed last frame, it was clearly just pressed this frame. if (currentFrame["A"] == true && lastFrame["A"] == false) {/*just pressed*/}
You would then do the opposite for the released. I find that method super easy to implement and use.

Dynamically change UIActionSheet buttons and actions

I have a UIActionSheet that I created Dynamically and it can have a number of buttons from 1 to 5 including cancel button. I can get the cancel button to work fine but lets say that only 2 buttons are need to be added onto the UIActionSheet, lets say they buttons 2 and 4 how do I determine which action to carry out. Cause normally I would use something like.
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch(buttonIndex) {
case 0:
// Do something here.
break;
case 1:
// Do something else here.
break;
case 2:
// Do something else again.
break;
case 3:
// Do something else here again.
break;
default:
break;
}
But if I only add two buttons dynamically there only going to use cases 0, 1. But if I add button 4 as one of the two buttons I still want it to use case 3. Is this possible or is there another way of doing it?
Use the buttonTitleAtIndex: method to check against the buttons' titles. You have to take care that your code won't break if you change a button's title in one place, though. It's probably best to save each button's title in an extra variable when you create the buttons and use this variable to compare with the button titles later.
When you create the UIActionSheet, keep a separate array mapping your button indexes to the actual tasks you want to perform (an actions enumeration, for example).
Then switch on tasks[buttonIndex] instead of buttonIndex.

How to properly return a value from a method and have it available immediately after application loads?

first post here so sorry for the length of it. I've been lurking and learning a lot so far but now I have to step in and ask a question. I have read numerous posts here as advised in the FAQs, but I couldn’t find exactly the answer I’m looking for.
Before anything else, let me just say that I'm a total beginner in programming (let alone Objective-C) so please excuse me for any misuse of the terminology. Same goes for any funny english as english not my native language.
I'm building an unit conversion application with a main window containing (among other stuff) two popUpButtons. I'm using indexOfSelectedItem from both popUpButtons in order to calculate a float value (I'm getting the indexes initially in the AwakeFromNib and later in the pop up buttons controller method, when the user change selection).
My problem consists of two parts: first, the code for calculation of that float is pretty massive as I'm comparing every combination of the two indexes of selected items. And second, I would need to have the calculated float value available immediately after launch as the user might want to perform a conversion before using any of the window popUpButtons (otherwise I would put the calculation code in a -(IBAction) method).
So, I'm trying with the following code for calculation of the float value:
#interface MyClass: NSObject
float calculatedFloat;
-(void)setCalculatedFloat:(float)calcFl;
-(float)calculatedFloat;
#implementation MyClass
-(void)setCalculatedFloat:(float)calcFl {
calcFl = 1.0; // I'm simplifying, this is where I'd like to perform calculation
}
-(float)calculatedFloat {
return calculatedFloat;
}
Now, for the first part of my problem, when I use the calculatedFloat in another method, say:
-(void)printIt {
NSLog(#"Calculated float equals: %.2f", calulatedFloat);
}
all I receive in Debugger is 0.00.
First question would be: if this is not working, how do I properly access this value from within another method?
For the second part of the problem, I'm using -(void)AwakeFromNib; to set up popUpButtons etc. right after the launch but I really wouldn't like to put all of the float calculation code in it only to repeat it somewhere else later.
So the second question would be: is this even possible what I'm trying to achieve? Further more, do I need to move this calculation code to another class? If so, how can I make that other class aware of the indexOfSelectedItem from a popUpButton?
Sorry for the lengthy post and possibly confusing and silly questions. I hope you didn't have to cringe your teeth too much while reading! :)
Thanks!
-(void)setCalculatedFloat:(float)calcFl {
calcFl = 1.0; // I'm simplifying, this is where I'd like to perform calculation
}
This doesn't show up when you print it later because you assigned to the variable holding the new value, not the variable for the value of the property. You need to assign to your calulatedFloat instance variable.
(You typo'ed that variable name, BTW.)
You should move the calculating into another method, and send yourself that message from awakeFromNib and from anywhere that needs to cause recalculation. That method should call setCalculatedFloat: with the calculated value—i.e., setCalculatedFloat: should be just a simple setter. Once you make that change, you could replace your custom accessors with a #synthesize statement and let the compiler write the accessors for you.
My problem consists of two parts: first, the code for calculation of that float is pretty massive as I'm comparing every combination of the two indexes of selected items.
You might see whether you can create custom objects to set as the menu items' representedObject properties, in order to cut out this massive comparison tree. It's hard to be more specific about this without knowing what your comparison tree does.