I have implemented IDWriteInlineObject interface to draw ID2D1Bitmap as inline object inside a text. Everything works fine except one: my implementation's GetOverhangMetrics method never get called.
I've also tried a sample from DirectWrite SDK samples (PadWrite Layout Sample, https://msdn.microsoft.com/en-us/library/windows/desktop/dd941792%28v=vs.85%29.aspx). And got the same result ('InlineImage::GetOverhangMetrics' in InlineImage.cpp is never called).
Therefore my question is why one's implementation of GetOverhangMetrics method never get called?
I admit I haven't tested this, so just a thought - I think it's possible it's called when you ask for overhang metrics of layout itself, so when layout method GetOverhangMetrics() is called it feels like it would accumulate not only regular text overhang boxes, but inline object boxes too.
GetOverhangMetrics is called for an inline object when the same method is called explicitly on the text layout object containing this inline object.
Related
I'm quite new to xposed module and I would like to know some information.
I managed to hook a method from StatusbarIconView called setShowsConversation(boolean showsConversation)
Changing the parameter to true allows it to show the statusbar's icon on the pixel 6 colored instead of white or black, depending on dark theme.
The problem is that this gets called multiple times a second. I tried to find a more specific method, but no vain.
My question is, is this normal behaviour, will this affect battery life? If so, is there a better method I can hook to achieve similar result?
Thanks
I'm trying to implement a syntax-coloring text editor that also does things like insert whitespace at the start of a new line for you, or replace text with text attachments.
After perusing the docs again after a previous implementation had issues with undoing, it seems like the recommended bottleneck for this is NSTextStorageDelegate's textStorage(_,willProcessEditing:,range:,changeInLength:) method (which states that Delegates can change the characters or attributes., whereas didProcessEditing says I can only change attributes). This works fine, except that whenever I actually change attributes or text, the text insertion mark moves to the end of whatever range of text I modify (so if I change the style of the entire line, the cursor goes at the end of the line).
Does anybody know what additional call(s) I am missing that tell NSTextStorage/NSTextView not to screw up the insertion mark? Also, once I insert text, I might have to tell it to move the insertion mark to account for text I've inserted.
Note: I've seen Modifying NSTextStorage causes insertion point to move to the end of the line, but that assumes I'm subclassing NSTextStorage, so I can't use the solution there (and would rather not subclass NSTextStorage, as it's a semi-abstract subclass and I'd lose certain behaviours of Apple's class if I subclassed it).
I found out the source of the problem.
And the only solution that will work robustly based on reasons inherent to the Cocoa framework instead of mere work-arounds. (Note there's probably at least one other, metastable approach based on a ton of quick-fixes that produces a similar result, but as metastable alternatives go, that'll be very fragile and require a ton of effort to maintain.)
TL;DR Problem: NSTextStorage collects edited calls and combines the ranges, starting with the user-edited change (e.g. the insertion), then adding all ranges from addAttributes(_:range:) calls during highlighting.
TL;DR Solution: Perform highlighting from textDidChange(_:) exclusively.
Details
This only applies to a single processEditing() run, both in NSTextStorage subclasses and in NSTextStorageDelegate callbacks.
The only safe way to perform highlighting I found is to hook into NSText.didChangeNotification or implement NSTextDelegate.textDidChange(_:).
As per #Willeke's comments to the OP's question, this is the best place to perform changes after the layout pass. But as opposed to the comment thread, setting back NSText.selectedRange does not suffice. You won't notice the problem of post-fixing the selection after the caret has moved away until
you highlight whole blocks of text,
spanning multiple lines, and
exceeding the visible (NSClipView) boundaries of the scroll view.
In this rare case, most keystrokes will make the scroll view jiggle or bounce around. But there's no additional quick-fix against this. I tried. Neither preventing sending the scroll commands from private API in NSLayoutManager nor avoiding scrolling by overriding all methods with "scroll" in them from a NSTextView subclass works well. You can stop scrolling to the insertion point altogether, sure, but no such luck getting a solid algorithm out that does not scroll only when you perform highlighting.
The didChangeNotification approach does work reliably in all situations I and my app's testers were able to come up with (including a crash situation as weird as scrolling the text and then, during the animation, replacing the string with something shorter -- yeah, try to figure that kind of stuff out from crash logs that report invalid glyph generation ...).
This approach works because it does 2 glyph generation passes:
One pass for the edited range, in the case of typing for every key stroke with a NSRange of length 1, sending the edited notification with both [.editedCharacters, .editedAttributes], the former being responsible for moving the caret;
another pass for whatever range is affected by syntax highlighting, sending the edited notification with [.editedAttributes] only, thus not affecting the caret's position at all.
Even more details
In case you want to know more about the source of the problem, I put more my research, different approaches, and details of the solution in a much longer blog post for reference. This here, though, is the solution itself. http://christiantietze.de/posts/2017/11/syntax-highlight-nstextstorage-insertion-point-change/
The above accepted answer with the notification center worked for me, but I had to include one more thing when editing text. (Which may be different from selection).
The editedRange of the NSTextStorage was whack after the notification center callback. So I keep track of the last known value myself by overriding the processEditing function and using that value later when I get the callback.
override func processEditing() {
// Hack.. the editedRange property when reading from the notification center callback is weird
lastEditedRange = editedRange
super.processEditing()
}
I don't understand why, even on Xcode 6, I need to click on self, search the property, and only then see the value.
If the object have 100 properties it's very annoying.
I'm searching for simple solution that when I set my mouse cursor on self.someproperty,
above "someproperty" I will see the value of it, in any case, NSString, NSArray, Etc.
Thanks.
That's presumably because the "properties" you're hovering above are not really variables. They are syntactic sugar for accessor methods (that generally reference a backing instance variable, but not necessarily so). These accessor methods, the getter and setter, were either synthesized for you, or you may have manually implemented your own custom methods. For more information about declared properties, see Declared Properties discussion in Apple's Core Competencies document or Properties Encapsulate an Object's Value in the Programming with Objective-C document.
Consider the foo property below. You cannot hover over references to self.foo and see what you were expecting. But, if you hover over the instance variable (ivar) that backs the property, you may:
(As an aside, note that the reference to self.foo = ... above does not reference the foo getter method, but actually calls the setter method setFoo. So, it seems like a non-trivial exercise to have the IDE debugger recognize that by hovering over that "property" while execution is paused there, but realize you want to call the getter to see the value rather than calling the setter that line of code actually references.)
Anyway, back to the IDE, you can also twist open self, you'll see it there, too:
These techniques are imperfect (sometimes the debugger gets confused), but hopefully this illustrates the basic UI.
I gather you would like it to call the accessor method when you hover over the property name. Does that mean you also want it to call any random method that the mouse happens to hover over, too? In a purely functional language, this notion seems a little more plausible, but it seems dangerous in the procedural languages where any method could conceivably change a state variable and have some unintended consequence. I would have thought that if you contemplate a feature like this, it should require some something more affirmative action than merely hovering over it.
Anyway, if you really want this feature, file a "feature request" at http://bugreport.apple.com.
You can use the the logging functionality of lldb right in the console, it's a huge help:
In the right part of your Debug area you have the Console (that's also where all NSLog output goes to).
In the Console you can just use the command po (print object) and print to print the value of a variable.
I'm implementing a Visual Studio Language Service for a custom scripting language used internally at my company, and I've run into an issue with the navigation bar implemented as a subclass of TypeAndMemberDropdownBars. The subclass is created by my LanguageService subclass' LanguageService.CreateDropDownHelper method.
In the OnSynchronizeDropdowns method I'm iterating through the types defined in the file and adding DropDownMembers to the passed-in array to fill out the navigation bar. The issue I'm seeing is that the first item in the array is being duplicated and placed at the end of the listing by code that I don't have access to. This extra item does not behave correctly when selected (nothing happens), but doesn't seem to cause any other issues; the rest of the items in the list work fine. Additionally, this only seems to happen for the type dropdown box - the members dropdown box does not display this behavior.
I'm hoping someone else has seen and resolved this issue and could provide some assistance. Thanks!
Turns out this was caused by me calling LanguageService.SynchronizeDropdowns from my LanguageService.ParseSource method, which was being called on a background thread. I've fixed the problem by setting a flag when ParseSource does a Check parse, and then implementing a check for that flag in my LanguageService.OnIdle function that will call SynchronizeDropdowns. It's now working as expected!
A better solution is to implement the LanguageService.OnParseComplete callback, and call SynchronizeDropdowns from there. OnParseComplete is always called from the main thread, so this prevents any synchronization issues from coming up, and also keeps you from having to keep track of whether or not you need to call SynchronizeDropdowns().
Does anyone have an example of using a QWidget as an editor in a QAbstractTableModel?
I have a column which when edited should create a QCombobox with the list of choices.
The docs seem to suggest I need to write a QAbstractItemDelegate and a custom paint function but that seems overkill to simply pop-up a standard QCombobox in Qt::EditRole.
Note - the combo box contents are the same for every row and it only needs to be shown when somebody clicks in the cell.
I know this should be simple but I can't get it to work. It's easy for a QTableWidget based table - but I need it for a very large data table.
The docs seem to suggest I need to write a QAbstractItemDelegate and a custom paint function but that seems overkill to simply pop-up a standard QCombobox in Qt::EditRole.
You don't need to go that far. One way is to subclass QStyledItemDelegate and then override createEditor() so that it returns your prepopulated combo box. Its setEditorData and setModelData functions will probably already suffice if you`re using basic Qt value types.
If you need something more generic that works across many different models, you can create a QItemEditorFactory that associates your editor with the correct type. This also works well with custom types.
When indicated by your view's EditTrigger, your view will get the delegate specific to the cell on which the edit is being invoked and call delegate->createEditor(...) which can then size the combo box according to the options parameter as well as set the current entry to the value specified by the model, although most of this should be handled by the QStyledItemDelegate. Thus, you won't have to worry about the Qt::EditRole directly as the view will handle that.
Did you try and have a look at the following example from Qt :
Spin Box Delegate Example
Maybe it will give you a much clearer view on the subject !
Hope it helps a bit !