Find coordinates of a substring in UILabel - iphone

I have a string coming from server which I am displaying on UILabel. It is within that string, I am identifying some particular substring. I want to place a button on that substring(button will be a subview of UILabel). For this I require substring coordinates. I went through this Gist but I am not able to understand it.
Suppose my complete string is abc, 567-324-6554, New York. I want 567-324-6554 to be displayed on button, for which I need its coordinates. How can I use above link to find coordinates of substring?

Might be you can calculate using-
CGSize stringSize = [string sizeWithFont:myFont
constrainedToSize:maximumSize
lineBreakMode:self.myLabel.lineBreakMode];
Now New position-
x = self.myLabel.frame.origin.x + stringSize.width
and for y similarly you need to have code with consideration of x.

Related

Unmerge and Assign Values Only Vertically or Horizontally Openpyxl

Using the answer provided by aka863 here: How to split merged Excel cells with Python?
I can unmerge, fill values and copy the styling. My questions is how to make the value assigning/filling process configurable.
I want the user to be able to choose whether the values will be filled vertically/horizontally.
I have tried changing the last loop where we assign the top_left_cell_values to unmerged cells. However I couldn't find a way to make it horizontal/vertical configurable. (I'm planning to use radio buttons and tkinter for this)
Its certainly possible to have the code de-merge cells and fill cells in whichever direction, vertically or horizontally regardless of which way the merge was originally. Or not fill at all, so only the top left cell retains the 'value' of the previously merged cells, which is default on unmerge.
Changing the direction of the fill requires some change and re-calculation on the max row and column values in the iter_rows loop, but is simple enough.
However it seems in your last comment you just want to give the user the option to fill or not fill on horizontal merges. In that case you just need to ask the question, and then run the iter_rows loop only if the response is yes.
The code sample below is based on the answer referenced question.
I'm assuming only single line horizontal merges since you dont mention what if anything should be done with vertical merges in the comment.
The code does initially check and indicate the merge direction either vertically or horizontally so it can be included take some action if a merge is vertical.
On code run after displaying the range and direction of the merge, the question is asked to fill, yes or no. If yes the cells are de-merged and all cells filled with the top left cell value using the iter_rows loop. If answer no then the cells are just de-merged.
from openpyxl import load_workbook
from openpyxl.utils.cell import range_boundaries
wb = load_workbook(filename='foo.xlsx')
st = wb['Sheet1']
mcr_coord_list = [mcr.coord for mcr in st.merged_cells.ranges]
direction_dict = {'v': 'vertical', 'h': 'horizontal'}
for mcr in mcr_coord_list:
print('---------------------------------------------------\n')
merge_direction = ''
min_col, min_row, max_col, max_row = range_boundaries(mcr)
top_left_cell_value = st.cell(row=min_row, column=min_col).value
if min_col == max_col:
merge_direction = 'v'
elif min_row == max_row:
merge_direction = 'h'
print(f"The cell range {mcr} is merged {direction_dict[merge_direction]}ly with the data '{top_left_cell_value}'")
while True:
demerge_fill = input('Do you want the de-merge to fill all cells(y|n)? ')
if demerge_fill.lower() in ["y", "n"]:
break
else:
print('Invalid response')
st.unmerge_cells(mcr)
if demerge_fill == 'y':
for row in st.iter_rows(min_col=min_col, min_row=min_row, max_col=max_col, max_row=max_row):
for cell in row:
cell.value = top_left_cell_value
else:
print(f"Only the top left cell {mcr.split(':')[0]} will contain the data!")
wb.save('merged_tmp.xlsx')

Swift fit annotations

I have a few locations in parse which I'm query-ing. It shows all annotations but it only zoom the last one. How can I find max and min latitudes and longitudes and make them fit ?
There is plenty of these on stackoverflow but they're almost all in objective-c.
The examples in Objective-C are still essentially valid since the underlying SDK/API is still the same -- just being called using a different language (and there's always the documentation).
To show all annotations, there are essentially two ways to do it:
Use the convenient showAnnotations method. You pass it an array of annotations and it will automatically calculate a reasonable region to display. You call it after adding all the annotations (after your for loop). In fact, showAnnotations will even add the annotations itself if they aren't already on the map. To show all annotations that are already on the map, just pass it the map's own annotations array. Example:
self.mapView.showAnnotations(self.mapView.annotations, animated: true)
If you are not happy with the default region calculated by showAnnotations, you can calculate one yourself. Instead of calculating minimum/maximum latitudes and longitudes, etc, I prefer to use the built-in MKMapRectUnion function to create an MKMapRect that fits all annotations and then call setVisibleMapRect(mapRect,edgePadding,animated) which lets one conveniently define padding in screen points around the fitted map rect. This technique was originally found in a very early map view sample app from Apple. Example:
var allAnnMapRect = MKMapRectNull
for object in objects! {
//existing code that creates annotation...
//existing code that calls addAnnotation...
let thisAnnMapPoint = MKMapPointForCoordinate(annotation.coordinate)
let thisAnnMapRect = MKMapRectMake(thisAnnMapPoint.x, thisAnnMapPoint.y, 1, 1)
allAnnMapRect = MKMapRectUnion(allAnnMapRect, thisAnnMapRect)
}
//Set inset (blank space around all annotations) as needed...
//These numbers are in screen CGPoints...
let edgeInset = UIEdgeInsetsMake(20, 20, 20, 20)
self.mapView.setVisibleMapRect(allAnnMapRect, edgePadding: edgeInset, animated: true)

Relative UILabel in a game object

I created a game object which acts as a repeating item for a UIGrid which I populate dynamically. The gameobject (RowItem) has couple of UILabel whose text can change on runtime depending on the content. The content of these UILabels overlap when the text is bigger. Can anybody help me in how to make UILabel expand relative to the adjacent UILabel when the text is more/less?
You can use transform.localScale property of the UILabel's property to scale it. Just make them bigger when the text is bigger than let's say 20 characters. Try with arbitrary values.
Also when you change the scale, run a re-align method, which aligns other labels so that they don't overlap.
you can get the text length in pixel by this:
UILabel label;
float width = label.relativeSize.x * label.transform.localScale.x;
float height = label.relativeSize.y * label.transform.localScale.y;
Let's say that you want to set you max length to 100, you can do this:
if (width > 100)
{
label.localScale = new Vector3(100 / label.relativeSize.x, 100/ label.relativeSize.x, 1);
}
the second param for Vector3 is also based on relativeSize.x is not a typo, that makes sure your text will not become thin.
Hope this works.

Split String at specific line for NSString

Hello ist there a way to split a String for UITableView at a specific line to put the "rest" (the second part of the data) in an own cell
NSString *data;
CGsize *size = [data sizeOfStringWithFont:[UIFont systemFontOfSize:14] constrainToWidth:280.0];
if the size.height e.g. is greater than 1500 i want to split the string at this line position!
thank you
Use "constrainedToSize" (instead of just to width) and render as much as you can.
If you really want to take exactly the text that would not fit, you're going to have to do essentially a search, adding a word at a time and then doing the size check to see how high you have gotten. You could start out with a rough estimate by doing the whole string constrained to something only one line high with boundless width (say 999999) and then divide up the width into however many rows you are wishing to allow to get a rough starting point for adding/removing words from the string (it will not be exact because of word wrapping).
Fundamentally though it seems wierd to take the leftover text and put it in another cell. Are you really sure you don't simply want to change the height of the cell with the text to allow it to fit the whole thing?
I think Kendall has the right idea, but the constrained sizes should be reversed to get the exact height based on word wrapping. Take a sample CGSize that is the same width as your cell, but with a height larger than the max height you expect. In the sample code below, textSize will contain the height of your string as it would appear in your cell with an unbounded height.
CGSize sz = CGSizeMake (
yourCellWidth,
999999.0f );
CGSize textSize = [yourString sizeWithFont:yourCellfont
constrainedToSize:sz
lineBreakMode:UILineBreakModeWordWrap];
If the height is greater than 1500, you could start picking off substrings (substringWithRange) from the end and measuring them like above until you get something >= the remainder above 1500 that was returned by textSize.

Wrap text in a UILabel with quotes?

By default, UILabels truncate text and then put an ellipsis on the end.
How might I wrap all the text, including the ellipse, in double quotes?
Use two UILables, the first holds the text (plus an open-quote), and the second just holds a close-quote:
["text that is lon…]["]
UILabel *label;
label.lineBreakMode = UILineBreakModeMiddleTruncation;
Unless there's an even better convenience method on the iPhone that I don't know about, I think the easiest and most flexible thing to do would be to subclass UILabel and implement your own drawing and truncation, using the various sizeWithFont extensions to determine the width of the string and each set of quotes individually.
Is your label text predictably going to result in truncation (and thus always have the ellipse)? I doubt it, but in case it does, you know the content is going to basically fill the width, so you can make the quote marks other UILabels (or even images). This would give you font and color control as well.
There is a correct way to do this, but it won't be the simplest thing ever. You need to do the following:
Determine the max height and max width of your label, with quotes. Determine the actual size of the label. You can use sizeWithFont:constrainedToSize:lineBreakMode: to do this. If the first is smaller than the second, strip the last word from your text, add ellipsis, and try again. That will look something like:
NSString *nextLine = rawTextWithoutQuotes;
NSRange range = [nextLine rangeOfString: #" " options: NSBackwardsSearch];
if (range.location == NSNotFound) {
return nextLine;
} else {
nextLine = [nextLine substringToIndex: range.location];
}
Keep doing this until you have manually truncated your string, then add the quotes and ellipsis, put it in your label, and you're done.