Can I insert a zero-width tagged span in a GtkTextView? - gtk3

I have a GtkTextView in which I would like to have some non-editable spans embedded in an otherwise freely editable document. The problem is, if I delete all the text between two such spans, they "merge together", in the sense that I can no longer insert characters between them. Here's some ruby code demonstrating the problem:
require 'gtk3'
window = Gtk::Window.new("Text view")
window.set_size_request(800, 600)
window.signal_connect("delete-event") { |_widget| Gtk.main_quit }
textview = Gtk::TextView.new
buffer = textview.buffer
buffer.create_tag "locked", {"editable" => false, "background" => "light green"}
iter = buffer.get_iter_at_offset 0
buffer.insert iter, "hello", "locked"
buffer.insert iter, " "
buffer.insert iter, "world", "locked"
window.add(textview)
window.show_all
Gtk.main
Since I have added an editable " " between "hello" and "world", I can insert text between them, but if I delete the space I can no longer add it back, even though "hello" and "world" are two independent locked spans.
Edit: To clarify, by "delete the space" I mean if I click into the text area and hit backspace till the space goes away and the two uneditable spans join together, I can no longer click on the boundary between them and insert text to push them back apart.

You could try replacing the interstitial text with a zero-width space instead of deleting it.

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')

Removing x number of characters from the caret position in tinyMCE

I am working on a project where the user can enter a special character and then tab to auto complete the values. This part is mostly working, but I want to be able to delete x number of characters from before the caret position.
E.g. if | is the caret and I have the following text #chr|.
I want to be able to delete 3 characters before the cursor position, e.g. I would just end up with #.
I have found a way to get the current cursor position using the below code, but I haven't been able to find any way of being able to delete x number of characters from that position.
function getCaretPosition()
{
var ed = tinyMCE.get('txtComment'); // get editor instance
var range = ed.selection.getRng().startOffset; // get range
return range;
}
You can do this by creating a Range ending at the current caret position:
var ed = tinyMCE.get("mce_0"); // get editor instance
var editorRange = ed.selection.getRng(); // get range object for the current caret position
var node = editorRange.commonAncestorContainer; // relative node to the selection
range = document.createRange(); // create a new range object for the deletion
range.selectNodeContents(node);
range.setStart(node, editorRange.endOffset - 3); // current caret pos - 3
range.setEnd(node, editorRange.endOffset); // current caret pos
range.deleteContents();
ed.focus(); // brings focus back to the editor
To use the demo, position the caret somewhere in the text and then click the "Remove 3" button at the top to delete the preceding 3 characters.
Note that my demo is simplified and doesn't do any bounds checking.
Demo: http://codepen.io/anon/pen/dWVWYM?editors=0010
Compatibility is IE9+

How to align a label versus its content?

I have a label (e.g. "A list of stuff") and some content (e.g. an actual list). When I add all of this to a PDF, I get:
A list of stuff: test A, test B, coconut, coconut, watermelons, apple, oranges, many more
fruites, carshow, monstertrucks thing
I want to change this so that the content is aligned like this:
A list of stuff: test A, test B, coconut, coconut, watermelons, apple, oranges, many more
fruites, carshow, monstertrucks thing, everything is startting on the
same point in the line now
In other words: I want the content to be aligned so that it every line starts at the same X position, no matter how many items are added to the list.
There are many different ways to achieve what you want: Take a look at the following screen shot:
This PDF was created using the IndentationOptions example.
In the first option, we use a List with the label ("A list of stuff: ") as the list symbol:
List list = new List();
list.setListSymbol(new Chunk(LABEL));
list.add(CONTENT);
document.add(list);
document.add(Chunk.NEWLINE);
In the second option, we use a paragraph of which we use the width of the LABEL as indentation, but we change the indentation of the first line to compensate for that indentation.
BaseFont bf = BaseFont.createFont();
Paragraph p = new Paragraph(LABEL + CONTENT, new Font(bf, 12));
float indentation = bf.getWidthPoint(LABEL, 12);
p.setIndentationLeft(indentation);
p.setFirstLineIndent(-indentation);
document.add(p);
document.add(Chunk.NEWLINE);
In the third option, we use a table with columns for which we define an absolute width. We use the previously calculated width for the first column, but we add 4, because the default padding (left and right) of a cell equals 2. (Obviously, you can change this padding.)
PdfPTable table = new PdfPTable(2);
table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
table.setTotalWidth(new float[]{indentation + 4, 519 - indentation});
table.setLockedWidth(true);
table.addCell(LABEL);
table.addCell(CONTENT);
document.add(table);
There may be other ways to achieve the same result, and you can always tweak the above options. It's up to you to decide which option fits best in your case.

How do i scroll a UITable view down until i see a cell with label "Value" in Calabash

How do i scroll a UITableView down until i see a cell with label "Value" in Calabash/Cucumber.
I've been trying to do it using:
Then I swipe down until I see "Value"
and using:
Then I scroll down until I see "Value"
but none of them seem to work. Thanks!
The message I get when I try with the above is obviously:
You can implement step definitions for undefined steps with these
snippets:
Then(/^I swipe down until I see "(.*?)"$/) do |arg1| pending #
express the regexp above with the code you wish you had end
add step definitions
Then /^I scroll to cell with "([^\"]*)" label$/ do |name|
wait_poll(:until_exists => "label text:'#{name}'", :timeout => 20) do
scroll("tableView", :down)
end
end
to the ProjectName/features/step_definitions/my_first_steps.rb ruby file and
In your calabash script add
Then I scroll to cell with "AAA" label
its working fine for me.
Every cucumber framework has a set of predefined steps. Of course, these steps don't cover all the possibilites. If you need additional functionality, you have to define your own steps:
When /^I scroll (up|down) until I see "([^\"]*)"$/ do |direction, something_to_see|
#implement the step here
end
I can't help you with the exact implementation (what is "Value"?) but you can find the core functions here
Probably you'll need function
scroll(uiquery, direction)
(where uiquery will be tableView)
If you take this function and element_is_not_hidden you can create a while cycle which will scroll down until you see the "Value".
Maybe something similar to the following (I don't know Calabash but I know Frank a little)
When /^I scroll (up|down) until I see "([^\"]*)"$/ do |direction, something_to_see|
max_scroll_tries = 10
[0..max_scroll_tries].each do
break if element_is_not_hidden("view marked:'#{something_to_see}'")
scroll("tableView", direction)
end
check_element_exists_and_is_visible("view marked:'#{something_to_see}'")
end
table have rows and sections, based how your code is organized use rows or sections in below code
def scroll_side_panel(text)
section=0
scroll_to_cell(:row => 0, :section => 0) # scroll to top of view
sleep 1 # wait for a second
#Scroll to each element and compare text, if there is a match break
each_cell(:animate => false, :post_scroll => 0.2) do |row, sec|
puts "#{query("tableViewCell indexPath:#{row},#{sec} label", :text)} #{text}"
if query("tableViewCell indexPath:#{row},#{sec} label", :text).first==text
break
end
section=section+1
end
puts "table view text found at element number:#{section}"
end
following should also work
Then(/^I scrolldown until "(.*?)" is visible$/) do |arg1|
until query("lable text:'#{arg1}'").length > 0
scroll("tableView", :down)
end
end
Call this by following
Then I scrolldown until "XY" is visible

How to set UIButton titlelabel topdown

will like to know how to set the text in UIButton title Label in top down.
the text is "Press Me" across
will like to show
"
p
r
e
s
s
m
e
"
i did this
CGAffineTransform newTransform = CGAffineTransformMakeRotation(90 * (M_PI / 180));
self.activeButton.transform = newTransform;
but it only changed the button direction not the text
Rotating text to be vertical is different than writing each letter on a separate line, which is what I gathered to be your intention from your question.
To do that, you need to actually write each letter on a separate line! You can create new lines in UIButton text by holding Alt/Option while pressing enter in the text field in Interface Builder. Note that this has to be the text field property in the Utilities panel, you can't add new lines if you're editing the text by double clicking the button.
Once you've done this, change the "Line Break" mode to either Character Wrap or Word Wrap in order for it to display multiple lines.
Edit: I realised that you may be trying to work with your button in code, so I wrote this piece that should convert a regular button's text to be spaced vertically, letter by letter:
// Create a temporary NSString to store the new formatted text string
// Set it to the first character so we can have a simple loop from the second to the last character
NSString *newText = [NSString stringWithFormat:#"%C",[button.titleLabel.text characterAtIndex:0]];
for(int i=1;i<button.titleLabel.text.length;i++) {
// Format newText to include a newline and then the next character of the original string
newText = [NSString stringWithFormat:#"%#\n%C",newText,[button.titleLabel.text characterAtIndex:i]];
}
// We must change the word wrap mode of the button in order for text to display across multiple lines.
button.titleLabel.lineBreakMode = NSLineBreakByCharWrapping;
// .. and for an unknown reason, the text alignment needs to be reset. Replace this if you use something other than center alignment.
button.titleLabel.textAlignment = NSTextAlignmentCenter;
// newText now contains the properly formatted text string, so we can set this as the button label
[button setTitle:newText forState:UIControlStateNormal];