insert GlyphProperty.null in shouldGenerateGlyphs causes cursor misplacement problem - uitextview

I am hiding the character * by inserting GlyphProperty.null then calling setGlyphs(_:properties:characterIndexes:font:forGlyphRange:) inside layoutManager(_:shouldGenerateGlyphs:properties:characterIndexes:font:forGlyphRange:) as described in the answer in https://stackoverflow.com/a/57697139/9568961, it works but after a certain sequence of text editing, the cursor starts to misplace, as shown in the gif https://github.com/dzAtZJU/Demos/blob/master/cursor_misplace.GIF?raw=true
GIF Description: When the second line becomes qq, I try to move the cursor to the end of first line, but it move directly to the beginning. I then try to delete characters, then the cursor move to the end correctly.
The sample project is here https://github.com/dzAtZJU/HideText.
Is it a bug? Have anyone run into this? How can I work around this?

This is a year-old question, but for anyone struggling with the same problem, here's a solution.
My Markdown-like parser knows the ranges for both the line on which the cursor is now, and where it was previously. I'm calling hideAndShowMarkup whenever text view selection changes.
You need to invalidate current glyphs for both of the ranges, and then redraw them synchronously before updating insertion point. The most crucial step is invalidating layout for the range where you want to show Markdown symbols. Without that, your caret gets drawn into the wrong position.
Code is in Objective C, but should be easy to implement in Swift, too.
-(void)hideAndShowMarkup {
// Just for reference
Line* line = currentLine;
Line* prevLine = previouslySelectedLine;
[self.layoutManager invalidateGlyphsForCharacterRange:line.range changeInLength:0 actualCharacterRange:nil];
[self.layoutManager invalidateGlyphsForCharacterRange:prevLine.range changeInLength:0 actualCharacterRange:nil];
[self.layoutManager invalidateLayoutForCharacterRange:line.range actualCharacterRange:nil];
if (NSGraphicsContext.currentContext) {
[self.layoutManager drawGlyphsForGlyphRange:line.range atPoint:self.frame.origin];
[self.layoutManager drawGlyphsForGlyphRange:prevLine.range atPoint:self.frame.origin];
}
[self updateInsertionPointStateAndRestartTimer:NO];
}

Related

JTextPane, second word must not go to new line when typing and exceeding width

I'm using JTextPane because I need to markup text.
When typing into the JtextPane the second word always goes to new line. Then also when making the second word longer (after it went to a new line) the scroll bar appears and the JTextPane resizes. If I start typing in a new row then second word in that line does not go to a new line (as long the second word does not exceed width)
I tried adding a blank string that is very long in the first line and seems to do the trick, but this blank line is not really what I want to have.
Also tried adding it to after the text but it gives more problems
Is there something else that I can do to make the text only go to new line when I press enter? I can do it without a blank string using jtextarea, but then I can't markup text as I type.
I found the answer:
JTextPane textPane = new JTextPane()
{
public boolean getScrollableTracksViewportWidth()
{
return getUI().getPreferredSize(this).width
<= getParent().getSize().width;
}
};
We can overite the getScrollableTracksViewportWidth method to have a no wrapping text pane.
Website for more info: Here

Included files after list not rendered correctly

main.asc:
== Items
include::foo.asc[]
include::bar.asc[]
foo.asc
=== Foo Title
==== List of things
* thing one
* thing two
bar.asc
=== Bar Title
this is a summary of bar
When main.asc is rendered, the following text is displayed:
Items
Foo Title
thing one
thing two === Bar Title
this is a summary of bar
I've also tried adding a simple paragraph at end of foo.asc after the list to see if that will fix the problem--it didn't.
Is there a way to fix this?
Adding a line between the two include statements seems to fix the issue:
== Items
include::foo.asc[]
include::bar.asc[]
You should always end all asciidoc files with a blank line, I actually keep a comment at the end of all my files to remember me:
////
Always end a file with a blank line to avoid include problems.
////
When you don't have a blank line the second file is included at end of previews line, and the result will be:
thing two === Bar Title

Whenever I type colon in insert mode it moves my text to the very beginning of line

Whenever I type a : (colon) it moves all the text on the current line to the beginning of the line, ignoring spaces and tabs.
So if I type
var combo = new Ext.form.ComboBox({
typeAhead //I'm about to type a colon, but right now it looks fine
})
Then I type the colon it moves the text and it now looks like
var combo = new Ext.form.ComboBox({
typeAhead: //text is no longer indented
})
This is a javascript file, so that might be causing the problem?
How can I stop my text from being moved to the beginning of the line when I type a colon?
Adding a colon to the end of a token is causing vim to interpret it as a jump label for C-indenting purposes. :set cino+=L0 should cause it to stay in the current column.
Also, doesn't the JSON syntax allow you to quote the thing that precedes the colon? That should prevent vim from thinking it's a label too.
var combo = new Ext.form.ComboBox({
"typeAhead": "foo" // this isn't a jump label
});

Any way to get a HaxeFlixel group to clear out?

There is a too long, didn't read version down below.
So I've been making a little game in which the player has to click on a grid of bricks that matches the color of the needed brick in the upper right hand corner of the screen. After they click on the needed color, the bricks explode and the bricks of the same color next to them explode as well creating combos. That leaves holes in the grid so I have to somehow reset the grid itself without resetting the gamestate itself. I've got something working right now which is this:
private function ResetNow():Void
{
if (Restter == 1) Restter = 0;
//if this block is up here, same results
/*
wantedBricks.kill();
wantedBrik._changeColor = FlxMath.rand(0, 2);
bricks.autoReviveMembers = true;
bricks.revive();
*/
Restter = 0;
//Removes stray detectors so the neverending combo bug won't occur
for (stray in dets.members) stray.kill();
if (Restter == 0)
{
wantedBricks.kill();
wantedBrik._changeColor = FlxMath.rand(0, 2);
bricks.autoReviveMembers = true;
bricks.revive();
wantedBricks.autoReviveMembers = true;
wantedBricks.revive();
for (zgem in bricks.members) zgem.EQUITYCHECK = FlxMath.rand(0, 2);
}
//add(bricks);
Restter = 1;
}
So, again, I have a grid of blocks set up at create, that is group bricks. And I have a sprite in the upper right corner which is wantedBrik. What happens during gameplay, is the player clicks on the bricks that matches the wanted bricks to clear them out of the grid. When there are no more wantedBricks(a group), it is supposed to reset the grid, and change the color of the wantedBrik. I also have it somewhere else in the code that if a member of the big grid's EQUITYCHECK(basic object hacked in value) is equal to the wantedBrik, add it to the wantedBricks(which, is why I'm checking for no more of them). So, what happens?
Well, if the color of the wantedBrik doesn't change, everything's fine and resets like normal. the wantedBricks group acurately counts the bricks that actually match the wantedBrik's color. And when it does change, for some reason, gameplay is normal. BUT, wantedBricks not only thinks that the old color is still needed, but it also thinks the new color is still needed too. So when the player clicks the new needed color bricks, they do explode, but because wantedBrik thinks the old color is still wanted, it doesn't hit null and the grid won't reset.
What can I do to make sure that wantedBricks behaves correctly after a color change?
TL;DR version: I need to get a Haxe array to forget or lose old numbers. How can I do this?
The "Pirate Pig" sample may be useful to you. Since it is a puzzle game, there may be some similar problems that were solved there. You can find it using openfl create or nme create depending on which you are currently using.
You can create a simple array like this:
var myArray = [];
You can also type arrays, like this:
var numbers = new Array<Float>();
Then you can use push(), concat() and other array methods.

Is there a way to get the cursor position in a mfc application?

I'm using the OnKeyDown handler to detect for an Enter key press:
void CShortestPathFinderView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if( nChar == VK_RETURN) //Enter key is pressed
{
CClientDC aDC(this);
rubberbanding = 0;
m_pTempElement->vertices[i++]= /*cursor position??*/;
mSecondPoint=m_pTempElement->vertices[0];
m_pTempElement->Draw(&aDC);
}
In the 3rd line of the if statement I need to store the cursor position in an array, but how do I acquire that point? Does the handler provide me with it? or is there a separate function to do so?
To get the current cursor position, you can call GetCursorPos. I don't believe MFC provides a wrapper for this, so it'll just be the Win32 ::GetCursorPos. It returns the point in screen coordinates, so you'll (almost certainly) want to use ScreenToClient to convert that to client area coordinates before storing it.
Note, however, that GetCursorPos will return the position of the cursor when you call it. That may or may not be quite the same as the position the cursor was at when the key was pressed (though it will normally be at least quite close).
Usually, to add a cursor position like this, you'd want to react to the user clicking the mouse button (e.g., WM_LBUTTONDOWN). That message will tell you the position of the mouse when the button was clicked.

Resources