Truncating NSString to fit a particular width - objective-c

I've got a variable-width-font NSString that has to fit inside a fixed size UIView. Currently, the string gets truncated and rendered.
I want to obtain the visible substring so I can append an elipsis (…) to it.

If you're using a UILabel, you can set the lineBreakMode to one of
UILineBreakModeHeadTruncation
UILineBreakModeTailTruncation
UILineBreakModeMiddleTruncation
The different positions refer to where the ... goes. You want UILineBreakModeTailTruncation.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UILabel_Class/Reference/UILabel.html#//apple_ref/occ/instp/UILabel/lineBreakMode

Related

How do I get the current font/font size at cursor in NSTextView?

Clarification: First, cursor = the insertion point cursor, not the mouse cursor.
Ok, I would like to return the font / font size / font color wherever the cursor is in the NSTextView. I tried using attribute:atIndex:effectiveRange:, but I failed because I got my variables all mixed up. I think it is what I need. Some example code would just be appreciated, returning the font. I think it will work the same for font size/color, I'll just have to substitute NSFontAttributeName for something else, right? Thanks in advance!
NSFont *font = [textView.textStorage attribute:NSFontAttributeName atIndex:textView.selectedRange.location effectiveRange:nil];
Should work for all getting the name.
What have you tried?
NSTextView has a method selectedRanges which returns the current selection(s) - just one of zero-length if there is just an insertion point.
NSTextView also has a property textStorage which returns back the instance of NSTextStorage which holds the text. An NSTextStorage inherits from NSMutableAttributedString, which inherits from NSAttributedString, and that has methods to obtain the attributes of the text.
Combined those two and you have your answer.
HTH

How to accomplish resizing NSTableCellView based on the size of its NSTextField?

I know that in a view-based table view, the row class NSTableCellView subclasses from NSView. This class contains two properties, an NSTextField and an NSImageView. I am only using the NSTextField without an image view. However, some cells in my table view must contain multiple lines of text, while others may only contain one or two lines. I need to be able to resize individual NSTableCellView views depending on the size of their NSTextField textField property.
Therefore, I needed to do the following:
Get the frameSize of the NSTextField in the table cell view.
Set the frameSize of the NSTableCellView to the frameSize of the NSTextField (the one we got in set one)
However, this approach hasn't been working. I have begun to think that my approach to resize the NSTableCellView is incorrect. Here is the code that I have been using:
[tableCellView setFrameSize:[[tableCellView textField] frame].size];
[tableCellView setNeedsDisplay:YES];
Is there a problem with this approach? I would expect the cell to resize, but it doesn't? What is going wrong?
Thanks.
[edit] I should have started by commenting that the size of the textField has little to do with how large it would need to be to display all of its content.
I use this code to determine the height of a string based on the width of a table cell:
- (CGFloat) displayStringHeightWithWidth:(CGFloat)width
{
CGSize size = NSMakeSize(width,0);
NSRect bounds = [self.displayString boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading];
return bounds.size.height;
}
Ideally you can adapt that to finding the height of the textField.stringValue or textField.attributedStringValue. Not that the above is also from OSX, not iOS, so YMMV on some of the fluff.
So that changes your algorithm to:
Get the width of the table column
Get the height of the required bounding rect for the textfield's text
Tell the tableView that the row height is whatever you found in 2
Now. Regarding #3. I believe that you have to use the tableView:heightOfRow: in NSTableViewDelegate protocol as well as call the table's noteHeightOfRowsWithIndexesChanged: to have row heights change. The tableView's not otherwise aware that the height of your cell has changed. Note the discussion in the documentation. It could be your method would work without the delegate and just telling the table that the row heights for the rows that you are changing are dirty... but I wouldn't really expect it.

Dynamic UITable Cell height

I have a UITableView with custom cells. I need to display Title, Address, Zip, Phone, Email, Website and Description in a Cell. All this information is coming from webserver. I am able to display the contents from the webserver. However, if any of the content is empty, there is a gap where that content should be, and if description is too long I am not able to display all the content. How can I change the height of cell according to the content from server? Please help.
For example : the contents is printing like:
Title
Address
Zip
Phone...
but, if Address is nil then it looks like:
Title
Zip
Phone...
I have the tableview:heightForRowAtIndexPath method but I am not able to update the cell height according to the cell contents.
Sorry for bad question format
Cells resizing can get pretty complicated, so I suggest you simply use a table view framework such as "Sensible TableView", where all the cells are automatically resized to fit contents. I believe they also now have a free version.
you can set the height of every cell with this delegate method
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *text = [yourArray objectAtIndex:indexPath.row];// here just use your data array which you get from server
CGSize mTempSize = [text sizeWithFont:[UIFont fontWithName:fontName size:fontSize] constrainedToSize:constrainedToSize lineBreakMode:UILineBreakModeWordWrap];
return mTempSize.height ;
}
i hope this help you...
Firstly you need to set the size of your labels according to it's text length. There are a number of sizeWithFont methods available to get size for a string. See Apple Developer Documentation
If you have single line labels you can use simplest of them – sizeWithFont:. But if you have multiline labels you should use – sizeWithFont:constrainedToSize:. This method lets you specify the maximum size you want the label be.
Secondly you have to return calculated height for your cell using tableView:heightForRowAtIndexPath:
Hope this helps you.
Your tableView:heightForRowAtIndexPath: call will need to tabe into account the missing data and how all the rest of the cell will be re-laid out to close the gap it leaves. So, your actual call will be non-trivial here.
The new facebook app does a neat trick here, though, to save you calling it every time. It calculates all of the cell heights in the background, just after downloading it, and before rendering the content to the user, storing it in the data store alongside the data itself. This means that the actual table cell rendering is really fast and slick as you don't need to re-layout/recalculate the cell height and layout on each app run/cell reuse.

Check if UIImage is on the top of view

I have a small question, I have a code to generate 200 UIImages in random positions and rotations.
I need to detect the touch event on these images, but I need to check if the touched UIImage is not covered by any other image (even if they intersect in a small area).
Can anybody help me on this?
BTW : I'm trying to do something similar to this game : http://www.dressup247.com/game/1014/Bank-Note-Stack.html
I would suggest to make all images as UIButton's with background image and set for all buttons one action. One more advise - set tag order for every button from most low-lying to most high-lying (and store biggest tag in some iVar). You can do it when layout is generated. It allows you to detect how many views lay over tapped view.
Use CGRectIntersectsRect intersecting views.
-(IBAction)banknotTapped:(UIButton*)sender{
int tag = sender.tag
NSMutableArray *highestViews = [NSMutableArray array];
for (int i=sender.tag; i < biggestTag; ++i){
UIView *v = [self.view viewWithTag:i];
if (CGRectIntersectsRect(sender.frame, v.frame) ) // it allows to find intersecting views
[highestViews addObject:v];
}
}
Now highestViews will contain all highest views that intersect with sender.
Note: tags allow you to detect views, but if you will delete images from superview then it can lead to problems since tag order will broken. Hide views instead of deleting or follow #Costique method in order to determine views order.
You can use the following snippet to determine the order of a subview in its parent view:
NSUInteger order = [containerView.subviews indexOfObjectIdenticalTo: subview];
The less the order, the "higher" the subview is. The topmost subview will have zero order.
While I'd suggest that it would be faster to do this mathematically, defining the banknotes as rectangles and testing for overlap using something like the separating axes theorem, that's obviously not what you're asking and not suitable for general case images.
So I'd suggest that you create a CGBitmapContext the same size as your play area and that when seeding your play area, for each note you place you do something like:
assign new, as yet unused colour to the bank note
draw it to the bitmap context at its destination position, but as a solid object of the assigned colour — so you preserve the outline of the original shape but at each pixel you draw either the solid, assigned colour or no colour at all
count how many pixels in the entire context are now the assigned colour, store that with your object representing the note
Subsequently, when the game starts run through the buffer and count how many of each assigned colour. All notes that have the same number stored as are currently visible are on top. Whenever a note is removed, redraw all the others in order and do the colour count once.
Note that you're not doing the colour count on the total buffer once per note, just once in total. So it's a fixed cost and probably occurs less often than once per tap.
Probably the easiest way to do the drawing as a single colour is to create a mask version of each graphic when it's loaded and then to draw that with a suitable tint. There's an introduction to alpha masks here; you'll probably want to create a custom bitmap image context rather than using the implicit one returned by UIGraphicsGetCurrentContext and to post filter to test the output alpha — pushing down to 0 if its less than some threshold, up to 255 otherwise.

UILabel and right to left text

I have a collection of NSString objects that contain arabic text. However, when I try to display any of them using a UILabel, the text shows left-to-right instead of right-to-left (NSLog shows the strings properly)
I am thinking about a work-around, applying a transform to the UILabel to make a y-axis symmetry, but how can I detect if a NSString contains a RTL string?
Try prepending the unicode character 0x200F to the beginning of each string. This character is an invisible marker character that indicates text directionality.
Have you tried setting your region to Arabic? I would have thought this type of thing would be handled automatically.