Date   

Re: Add overflow indicator to text

Steve Mills
 

Thanks for the input, everyone. I mentioned that exclusionPaths are used, so the text flows inside arbitrary shapes, mostly comic book balloon type blobs. As such, there's rarely a straight bottom edge, straight right edge, or bottom-right corner. So it seems like the best place is to put the marker after the last visible character. If that happens to be outside the bounds of the parent view, I'll try putting it below the last visible char. And if that happens ti be outside the bottom of the parent view, float it over the last visible char. At that point, it doesn't matter of it obscures the char, since it's overflowed and the user needs to choose a smaller text size.

Years ago I worked for MultiAd. Our page layout app Creator put a fat, red ellipsis below the bottom edge of an overflowed text box when editing was active, and above the bottom edge when it was inactive. While active, it double as a button that allowed the user to add a new text block in sequence. When it didn't look right was when the text block was in a non-rectangular shape, like a right triangle whose right angle is at the top-left, so the marker was left floating in space. Which is why it makes sense for it to be near the last visible char, especially since the app I'm working on now is only a viewer, not an editor.

Thanks for talking through it with me.

--
Steve Mills
Drummer, Mac geek


Re: Add overflow indicator to text

Graham Cox
 



This is what we do in a drawing app, which works well for us. When the text box is selected, it shows the + symbol as part of the frame. If not selected that’s not visible, so the text itself isn’t modified by not fitting. If you have some sort of highlighting or frame around the text, something like this could work for you.

To detect whether this is drawn or not, we ask the layout manager of the text system for the -glyphRangeForTextContainer:, and compare it to the -glyphRangeForCharacterRange: for the entire text. The symbol is displayed when they are unequal. This is simple and reliable, though NSLayoutManagerDelegate has -layoutManager:didCompleteLayoutForTextContainer:atEnd: where the atEnd: part tells you whether it completed the job. 

—Graham



On 10 Nov 2017, at 4:41 am, Steve Mills <sjmills@...> wrote:

I'm using NSTextContainer with exclusionPaths, NSLayoutManager, and UITextView for rendering text into balloons, and the user can control the font size. When overflow occurs, I'd like to show an indicator. Just looking for thoughts on the best way to show that. My first thought is to insert a red ellipsis after that last visible character, although that could certainly cause it to re-wrap and overflow in a different spot. Other thoughts involve drawing something in a new layer at the overflow location, such as an ellipsis in a semi-transparent capsule shape.



Re: Add overflow indicator to text

Alex Zavatone
 


On Nov 9, 2017, at 12:28 PM, Quincey Morris <quinceymorris@...> wrote:

On Nov 9, 2017, at 09:41 , Steve Mills <sjmills@...> wrote:

drawing something in a new layer at the overflow location

In text layout apps that I’ve used, which can flow text through multiple containers, there’s typically a small box outside the top-left and bottom-right corners of the container frame. The boxes contain some indicator if the container is linked to another preceding or following container, and if the last container is overset, the bottom-right box typically shows a red plus sign, which you can click on to go into an add-new-container mode.

Given all that, I think drawing an overflow icon over the bottom corner would be a familiar choice. If you draw an ellipsis in a capsule, you could put it just outside the frame, or float it centered over the frame edge.

Putting it inside the frame inline with the text doesn’t seem like a terrible idea, but it might be easier for the user to miss, and it leaves you open to subtle layout problems where the indicator doesn’t show at all.
_

Quincy, your observation reminds me of how Quark Xpress handled this in circa 1989.  It was a surprisingly nice indicator that “there is more to this text box”.  I think they may have put a small bottom-right box indicator and then added a chain link graphic in the box it the text container was linked to another text container.

Thinking of Steve’s original problem and ideas solution, I am wondering about the red ellipsis as well and thinking just how much of this will already be solved by the NSTextContainer or UITextView.   

What I mean is that a UILabel will display an ellipsis at the end when it has the following settings:

myLabel.adjustsFontSizeToFitWidth = NO;
myLabel.lineBreakMode = NSLineBreakByTruncatingTail;
In that case, the text is already properly truncated for you.  The only thing would be needed would be to change the color of the ellipsis that is displayed at the end or find the position of the last character and draw your own ellipsis over it…

Of course, that’s on iOS with a UILabel.  I’m not sure how a NSTextContainer or UITextView would handle this.  


Thinking about how this might look to the user, a red color often is associated with something being wrong, or a destructive action, like deleting data, as we all know.  

The trick might be getting it to work first, then once you are able to get the character position of the ellipsis, simply figuring out what you want to display there.  

Quincy’s suggestions seem to be pretty user friendly and also more straightforward to implement though.

Good luck.
Alex Zavatone




Re: Cancelling dispatch_after?

Quincey Morris
 

On Nov 9, 2017, at 08:57 , Jens Alfke <jens@...> wrote:

because then blocks would always be copied to the heap, even in common cases where they don’t escape

Yes, that sounds correct. I was thinking that there was a problem for the original caller (the one in whose stack frame the block resides), because the block might have moved after the call returns. But (I presume) this could be handled with one level of indirection in the caller, so that it doesn’t care where the block happens to be, plus the passing of a reference to the pointer, so that the pointer can be updated in the event of a (real) copy.

By contrast, in Swift, block (aka closure) parameters are explicitly annotated as escaping or non-escaping, so this kind of hack is avoidable.


Re: Add overflow indicator to text

Quincey Morris
 

On Nov 9, 2017, at 09:41 , Steve Mills <sjmills@...> wrote:

drawing something in a new layer at the overflow location

In text layout apps that I’ve used, which can flow text through multiple containers, there’s typically a small box outside the top-left and bottom-right corners of the container frame. The boxes contain some indicator if the container is linked to another preceding or following container, and if the last container is overset, the bottom-right box typically shows a red plus sign, which you can click on to go into an add-new-container mode.

Given all that, I think drawing an overflow icon over the bottom corner would be a familiar choice. If you draw an ellipsis in a capsule, you could put it just outside the frame, or float it centered over the frame edge.

Putting it inside the frame inline with the text doesn’t seem like a terrible idea, but it might be easier for the user to miss, and it leaves you open to subtle layout problems where the indicator doesn’t show at all.


Add overflow indicator to text

Steve Mills
 

I'm using NSTextContainer with exclusionPaths, NSLayoutManager, and UITextView for rendering text into balloons, and the user can control the font size. When overflow occurs, I'd like to show an indicator. Just looking for thoughts on the best way to show that. My first thought is to insert a red ellipsis after that last visible character, although that could certainly cause it to re-wrap and overflow in a different spot. Other thoughts involve drawing something in a new layer at the overflow location, such as an ellipsis in a semi-transparent capsule shape.

--
Steve Mills
Drummer, Mac geek


Re: Cancelling dispatch_after?

 



On Nov 8, 2017, at 5:54 PM, Quincey Morris <quinceymorris@...> wrote:

I think that should be an “or”: if you assign it to a non-local variable *or* pass it as a parameter.

No, because then blocks would always be copied to the heap, even in common cases where they don’t escape, like calling NSDictionary’s -enumerateKeysAndValues: method. That would make these a lot more expensive.

A block literal passed to a function/method is uncopied, just a direct pointer to a structure in the caller’s stack frame. The called function has to copy the block if it will keep a reference that lasts after it returns. This used to be manual, but ARC does it automatically if you assign the block to an ivar or global.

—Jens


Re: Cancelling dispatch_after?

Quincey Morris
 

On Nov 8, 2017, at 16:37 , Jens Alfke <jens@...> wrote:

ARC copies the block automatically if you assign it to a variable instead of just having it as a parameter of a function/method call

I think that should be an “or”: if you assign it to a non-local variable *or* pass it as a parameter. That’s because the block is implicitly moved to the heap (which is what a copy does) if the reference to it can escape the current scope:


under the heading “Objects Use Properties to Keep Track of Blocks”.

I think you do have a potential problem, though, if you’re trying to cancel pending invocations when posting a new invocation. If you have an instance property or variable to keep track of the pending block, the logic for cancelling it is not automatically thread safe. (More specifically, the plain logic for testing whether it is still pending is not thread safe.) You’re going to have to figure out a way to make it thread safe. Of course, if you're dispatching these blocks to the main queue, from code executing in the main thread, it’s automatically safe.


Re: Cancelling dispatch_after?

 



On Nov 8, 2017, at 4:15 PM, Graham Cox <graham@...> wrote:

In addition, the documentation for dispatch_after says that the function copies and releases the block on behalf of the caller. Wouldn’t that mean that my reference isn’t the same block, so the cancel wouldn’t work anyway?

I think ARC copies the block automatically if you assign it to a variable instead of just having it as a parameter of a function/method call. (A block really only gets copied once; it’s more like “detached”, so that it can be used after the stack frame that created it has returned. After that, any further copies are no-ops.)

—Jens


Re: Cancelling dispatch_after?

Graham Cox
 

Makes sense, but there’s a bit of a problem.

To do that I’m going to have to create the block and keep a reference to it. That doesn’t seem to be how the GCD dispatch code snippet works - it just declares the block anonymously as part of the function call. OK, I get how to fix that. But the cancel would have to happen from a different method of the enclosing class, which means that the block reference is going to have to be an ivar (or property). That’s where it gets confusing because it’s unclear how to do that properly. Do I have to copy the block or retain it or what? When it’s just a local variable I don’t have to think about these issues.

In addition, the documentation for dispatch_after says that the function copies and releases the block on behalf of the caller. Wouldn’t that mean that my reference isn’t the same block, so the cancel wouldn’t work anyway?


—Graham

On 9 Nov 2017, at 9:13 am, Quincey Morris <quinceymorris@...> wrote:

On Nov 8, 2017, at 14:03 , Graham Cox <graham@...> wrote:

Is there a way to cancel a scheduled block used with dispatch_after(…)?
If you mean “cancel” in the sense of “prevent it from starting”, then the answer is yes, you can use “dispatch_block_cancel”:

https://developer.apple.com/documentation/dispatch/1431058-dispatch_block_cancel?language=objc

The original GCD didn’t have this ability, but it was added a few years ago.

You can’t cancel it once it’s started running, except by means of setting a flag as you mentioned earlier.


Re: Opening File in Finder

Quincey Morris
 

Oops, sorry, that was weird. Mail sent that message when I just closed the window, which wasn’t what I intended to happen.

I was in the process of composing an extremely witty response, but it wasn’t coming out witty at all. Luckily I succeeded in deleting the extremely unwitty text before Mail decided to send the rest of the message.

On Nov 8, 2017, at 14:27 , Quincey Morris <quinceymorris@...> wrote:

On Nov 8, 2017, at 11:05 , Andy Lee <aglee@...> wrote:

perhaps because my code predated 10.6. :)

Perhaps. :)

Feel free to insert your own extremely witty response here.


Re: Opening File in Finder

Quincey Morris
 

On Nov 8, 2017, at 11:05 , Andy Lee <aglee@...> wrote:

perhaps because my code predated 10.6. :)

Perhaps. :)



Re: Opening File in Finder

Andy Lee
 

Oh wow, I didn't know about that method -- perhaps because my code predated 10.6. :)

--Andy

On Nov 8, 2017, at 2:03 PM, Quincey Morris <quinceymorris@...> wrote:

So, doesn’t NSWorkspace’s activateFileViewerSelecting method do that?

On Nov 8, 2017, at 10:54 , Gerriet M. Denkmann <g@...> wrote:

But I do *not* want to open “someThing”, I just want it selected in Finder.


Re: Cancelling dispatch_after?

Quincey Morris
 

On Nov 8, 2017, at 14:03 , Graham Cox <graham@...> wrote:

Is there a way to cancel a scheduled block used with dispatch_after(…)?

If you mean “cancel” in the sense of “prevent it from starting”, then the answer is yes, you can use “dispatch_block_cancel”:


The original GCD didn’t have this ability, but it was added a few years ago.

You can’t cancel it once it’s started running, except by means of setting a flag as you mentioned earlier.


Re: Opening File in Finder

Andy Lee
 

Hi Gerriet,

Try this:

BOOL didSelect = [[NSWorkspace sharedWorkspace] selectFile:filePath
inFileViewerRootedAtPath:containingDirPath];

-Andy

On Nov 8, 2017, at 1:54 PM, Gerriet M. Denkmann <g@...> wrote:

I want to have a Finder window with “/a/hugeFolder/someThin"g selected.

[ NSWorkspace.sharedWorkspace openFile: @“/a/hugeFolder/someThing” withApplication: @“Finder" ]

results in an AlertPanel: “There is no application to open “someThing””.

But I do *not* want to open “someThing”, I just want it selected in Finder.

How to do this?

AppleScript comes to mind; but I am terrible bad at AppleScript.

Gerriet.


Cancelling dispatch_after?

Graham Cox
 

Hi all,

Is there a way to cancel a scheduled block used with dispatch_after(…)?

While I’m finding the functionality it offers really useful, it seems like as soon as you use it you have to commit to that code being run, even if circumstances change before it does so. As a result I’m having to use flags and other awkward means to prevent the ‘meat’ of the block running. If not I may have to go back to the -performSelector:afterDelay:.. approach which can be cancelled.

—Graham


Re: Observing changes in TableView

Gerriet M. Denkmann
 

On 9 Nov 2017, at 01:36, Quincey Morris <quinceymorris@...> wrote:

On Nov 8, 2017, at 01:47 , Gerriet M. Denkmann <g@...> wrote:

So I gave the Button a target and action, but this never results in a message sent.
This ought to work, so I think you should focus on finding out why it isn’t. What are you specifying for the target? It should be something that doesn’t depend on the cell itself, like the view controller or the app delegate.
I just tried it again, and now Xcode told me that: “ Action ‘boxClicked:' sent by 'Check Box' is connected to 'File's Owner,' an invalid target (Objects inside view based table views may only be connected to the table view's delegate.)"

So I made the ‘File’s Owner’ the table view’s delegate and now it works as expected.

Kind regards,

Gerriet.


Re: Opening File in Finder

Gerriet M. Denkmann
 

On 9 Nov 2017, at 02:03, Quincey Morris <quinceymorris@...> wrote:

So, doesn’t NSWorkspace’s activateFileViewerSelecting method do that?
It does indeed. Thanks very much for telling me.

On Nov 8, 2017, at 10:54 , Gerriet M. Denkmann <g@...> wrote:

But I do *not* want to open “someThing”, I just want it selected in Finder.
Kind regards,

Gerriet.


Re: Observing changes in TableView

Alex Zavatone
 

Though in concept, I love the idea of KV observers, in practice, I’ve found that they lead to too many crashes.

I’ve switched over to sending notifications and it’s much less to worry about and much less wasted time. FWIW.

Alex Zavatone

On Nov 8, 2017, at 12:48 PM, Gerriet M. Denkmann <g@...> wrote:


On 9 Nov 2017, at 01:36, Quincey Morris <quinceymorris@...> wrote:

On Nov 8, 2017, at 01:47 , Gerriet M. Denkmann <g@...> wrote:

So I gave the Button a target and action, but this never results in a message sent.
This ought to work, so I think you should focus on finding out why it isn’t. What are you specifying for the target? It should be something that doesn’t depend on the cell itself, like the view controller or the app delegate.
It was the app delegate.

I found another solution:
The contentArray contains only a few dictionaries - less than a dozen.
So I decided to observe all of them:

for( NSDictionary *d in self.contentArray )
{
[ d addObserver: self
forKeyPath: kKeyPath // “Flag”
options: 0
context: (__bridge void * _Nullable)(kKeyPath)
];
};

Kind regards,

Gerriet.






Re: Observing changes in TableView

Alex Zavatone
 

Gerriet, I am doing the same thing now on iOS.

Here’s what I am doing and am open to better approaches.

Being able to do this requires a special set up where the cell contents are retrieved from a data set based on indexPath.

All my data is in a dictionary that is keyed off of indexPath row and section, so displaying the data is simply a case of getting the proper index and using the section and row to retrieve the correct data from the data source.

I have subclassed UITableViewCell but I don’t think you need to do this. A cell has access to its indexPath, but you can set the indexPath of the clicked/tapped item in another object if you wish.

Once this is done, I send a notification of processTappedCellItem to the tableViewController and it checks the indexPath of what was tapped.

Since everything is keyed off of the item’s indexPath, we know the item for which the button was clicked/tapped.

Does this approach work for you?

I’m using this to manage editable fields in a tableViewController for data entry.

Cheers.
Alex Zavatone

On Nov 8, 2017, at 3:47 AM, Gerriet M. Denkmann <g@...> wrote:

macOS 12.6

I have an ArrayController which has ContentArray bound to AppDelegate.contentArray
The contentArray contains MutableDictionaries with a key “Flag”, value: boxed BOOL.

And a TableView which has Content bound to ArrayController arrangedObjects.

The TableView (View based) has a TableColumn which has s Button in Table Cell View.
Its Value is bound to: Table Cell View.objectValue.Flag

Everything works fine, but now I want to get notified when the user clicks on some Button in the TableView (and thus changes Flag in some dictionary inside contentArray).

I seem to remember that on can not observe changes inside contentArray.

So I gave the Button a target and action, but this never results in a message sent.

How can I accomplish this?

The best (not very good) I can think of is a timer which every half second checks all dictionaries in contentArray.
Very wasteful indeed.

There surely must be a better way.


Gerriet.