How to right align text in ImGui Columns? - c++

Suppose I create a table with the following:
ImGui::Columns(3);
ImGui::Text("Header 1");
ImGui::NextColumn();
ImGui::Text("Header 2");
ImGui::NextColumn();
ImGui::Text("Header 3");
ImGui::NextColumn();
ImGui::Text("1");
ImGui::NextColumn();
ImGui::Text("2");
ImGui::NextColumn();
ImGui::Text("3");
ImGui::NextColumn();
ImGui::Columns(1);
How can I get the text in the second row (1, 2, and 3) to be right aligned in the column? I've seen CalcItemWidth and CalcTextSize, but I can't figure out how they work within a multi-column line.

I received help in the ImGui Discord channel and came up with this solution:
ImGui::NextColumn();
std::string text = "1";
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(text.c_str()).x
- ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x);
ImGui::Text("%s", text);
Edit: #FabriceMollo's answer is better.

Nearly same code than iHowell answer but new x position should be checked against current position value in order to be well window-border aligned (text will then be right-clipped).
In code:
ImGui::NextColumn();
std::string text = "1";
auto posX = (ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(text.c_str()).x
- ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x);
if(posX > ImGui::GetCursorPosX())
ImGui::SetCursorPosX(posX);
ImGui::Text("%s", text);

i think this is better
int your_column = 0;
std::string text = "ID";
auto column1_x = (ImGui::GetCursorPosX() + ImGui::GetColumnWidth(your_column) * 0.5 - ImGui::CalcTextSize(text.c_str()).x);
if (column1_x > ImGui::GetCursorPosX())
ImGui::SetCursorPosX(column1_x);
ImGui::Text("%s", text.c_str());

Related

Aya End Of Verse Symbol in SwiftUI [duplicate]

I'm working on android application and I'm trying to write arabic number inside arabic end of ayah symbol (۝) into textview.
I've tried to write the end of ayah symbol then the arabic number without any space but it didn't work. I'm using uthmani font.
I want to display it like this picture:
This is part of the code
NumberFormat nf = NumberFormat.getInstance(Locale.forLanguageTag("AR"));
temp+=" "+"\u06DD"+String.valueOf(nf.format(count))+" ";
"\u06DD" is the encoding of (۝) in java.
The result became like this:
You can use font named me_quran with these unicodes U+FD3E + numbers + U+FD3F
﴿ ORNATE RIGHT PARENTHESIS Unicode: U+FD3F, UTF-8: EF B4 BF
﴾ ORNATE LEFT PARENTHESIS Unicode: U+FD3E, UTF-8: EF B4 BE
You can download the font file from here
Example of usage:
Try something like this ﴾١٩٦﴿ which looks like ﴾١٩٦﴿
I just reversed the format and it worked
NumberFormat nf = NumberFormat.getInstance(Locale.forLanguageTag("AR"));
textView.setText(String.valueOf(nf.format(285))+"\u06DD");
(font was roboto)
In Flutter, you can use quran package. getVerseEndSymbol(int verseNumber) function will return aya end symbol with the given verse number.
Example:
Text(
quran.getVerse(18, index + 1) + getVerseEndSymbol(index + 1),
textAlign: TextAlign.right,
),
This will return the symbol with the given verse number.
If you are using uthmanic font "KFGQPC Uthmanic Script HAFS Regular", you just enter a number in arabic like this "٤٤" and it will be rendered as end verse symbol with the number:
for swift use this code for quran aya ending code addition:
let arabicAyaStyle = "\u{FD3F}" + "\(getArabicDigitFor(value:verseObj.verseId))" + "\u{FD3E}"
append arabicAyaStyle to end of any aya text.
func getArabicDigitFor(value:Int) -> String
{
let numberToConvert = NSNumber(value: value)
let formatter = NumberFormatter()
let arLocale = Locale(identifier: "ar")
formatter.locale = arLocale
return formatter.string(from: numberToConvert)!
}
You can use ReplacementSpan to alter how the aya number is rendered
for example this is how I did it
public class EndOfAyaSpan extends ReplacementSpan
{
public RoundedBackgroundSpan(Context context)
{
super();
}
#Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)
{
float textSize = paint.getTextSize();
canvas.drawText("\u06dd ", 0, 1, x - textSize / 5, (float) y, paint);
paint.setTextSize(textSize - textSize / 3);
canvas.drawText(text, start, end, x, y - textSize / 5, paint);
paint.setTextSize(textSize);
}
#Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm)
{
return Math.round(paint.measureText(text, start, end));
}
}

Copying certain rows to duplicated sheet using macro

I've got a google sheet which I'm using as a monthly handover sheet with a to-do list at the bottom.
The to-do list has a checkbox then a couple of columns of information (a date, the task and who it's assigned to)
To-Do List
I've created a button that runs a macro to duplicate the sheet to create a copied sheet at the end of the month.
I'd like to copy over any tasks in the to-do list which haven't been 'ticked' as completed but I'm not very good at logic in google apps script.
Could anyone help me write the if statement to either copy unticked rows to the duplicated sheet or do duplicate all rows then delete the ticked ones.
Thanks, Joe
UPDATE: after playing around for a couple of hours, this is what I've got:
function ToDoCopy() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var duplicateSheet = ss.getSheetByName("JUNE");
var originalSheet = ss.getSheetByName("MAY");
var lastRow = originalSheet.getLastRow() + 1;
for(var j = 24; j < lastRow; j++)
{
if(originalSheet.getRange(j,2).getValue() ==false && originalSheet.getRange(j,3).getValue() != 4)
{
var nextRow = duplicateSheet.getLastRow() +1;
var getCopyRange = originalSheet.getRange('B' + j + ':P' + j);
getCopyRange.copyTo(duplicateSheet.getRange(nextRow, 2));
}
}
}
It's almost working but it adds the copied items underneath the to-do table on the new sheet rather than adding them to the top. I can't work out how to fix this!
(p.s. the && originalSheet.getRange(j,3).getValue() != 4 part is a hidden row which I use for auto-sorting the table, '4' means it's empty basically.
function ToDoCopy() {
const ss = SpreadsheetApp.getActive();
const ssh = ss.getSheetByName("MAY");//source sheet
const sshsr = 24;//start row
const srg = ssh.getRange(sshsr, 1, ssh.getLastRow() - sshsr + 1, ssh.getLastColumn());
const svs = srg.getDisplayValues();//useful for me when using checkboxes
const dsh = ss.getSheetByName("JUNE");//destination sheet
if (dsh.getLastRow() - sshsr + 1 > 0) {
dsh.getRange(sshsr, 1, dsh.getLastRow() - sshsr + 1, dsh.getLastColumn()).clearContent().setDataValidation(null);//Clear destination range if not already cleared
}
let a = 0;//row add counter
svs.forEach((r, i) => {
if (r[1] == 'FALSE' && r[2] != 4) {
ssh.getRange(sshsr + i, 1, 1, ssh.getLastColumn()).copyTo(dsh.getRange(sshsr + a++, 1));
}
});
}

Libreoffice API (UNO) : text and data from xTextField

How can I get xTextFields from .odt document properly?
I tried something like that, but it doesn't work (Any returns a nullptr address):
Reference <XTextFieldsSupplier> xTextFieldsSupplier (xTextDoc, UNO_QUERY);
if (!xTextFieldsSupplier.is())
return { };
Reference<XNameAccess> xTextFieldsInfo = xTextFieldsSupplier->getTextFieldMasters();
if (!xTextFieldsInfo.is())
return { };
Sequence<OUString> xTextFieldsNames = xTextFieldsInfo->getElementNames();
Any any;
for (::rtl::OUString* field = xTextFieldsNames.begin();
field != xTextFieldsNames.end();
field++) {
std::stringstream field_string;
field_string << *field;
QString fieldName = QString::fromStdString(field_string.str());
any = xTextFieldsInfo->getByName(*field);
Reference< XTextField > xField(any, UNO_QUERY);
// other code to work with xField
}
UPD:
I got a solution that helped me here:
Libreoffice API (UNO): need to change user's xTextField text
XTextFieldsSupplier has two methods, and it looks like you chose the wrong one. The method to get text fields is getTextFields().
Example code:
Reference< XEnumerationAccess > xFieldsEnumAccess = xTextFieldsSupplier->getTextFields();
Reference< XEnumeration > xFieldsEnum = xFieldsEnumAccess->createEnumeration();
Reference< XTextRange > xTextRange;
while ( xFieldsEnum->hasMoreElements() )
{
Any aNextElement = xFieldsEnum->nextElement();
Reference< XTextField > xField(aNextElement, UNO_QUERY);
OUString presentation = xField->getPresentation(true);
xTextRange = xText->getEnd();
xTextRange->setString(presentation + OUString::createFromAscii("\n"));
}
If you want to deal with text field masters instead, then your code is mostly correct.
Any aFieldMaster;
aFieldMaster = xNamedFieldMasters->getByName(*field);
EDIT:
Here is where xText comes from.
Reference < XTextDocument > xTextDocument (xComponent,UNO_QUERY);
Reference< XText > xText = xTextDocument->getText();
EDIT 2:
Here is an example of changing a text field. Start with a new Writer document and go to Insert -> Field -> More Fields. Under the Functions tab, double-click Input Field. Enter "hello" in the text box area and press OK.
Then, run the following code.
Reference< XServiceInfo > xInfo (xField, UNO_QUERY);
OUString sContent;
if (xInfo->supportsService("com.sun.star.text.TextField.Input"))
{
Reference< XPropertySet > xProps (xField, UNO_QUERY);
Any aContent = xProps->getPropertyValue(OUString::createFromAscii("Content"));
aContent >>= sContent;
sContent += OUString::createFromAscii(" there");
aContent <<= sContent;
xProps->setPropertyValue(OUString::createFromAscii("Content"), aContent);
Reference< XRefreshable > xRefreshable (xFieldsEnumAccess, UNO_QUERY);
xRefreshable->refresh();
}
Now, the field contains "hello there".
For more information, please review Andrew's Macro Document section 5.18 User Fields.

How to load from memory stream to firemonkey (FMX) memo component in C++ Builder Berlin?

I used to use below code to load plenty of text to VCL Memo.
LogMemo->Lines->BeginUpdate();
LogMemo->SelStart = LogMemo->GetTextLen();
LogMemo->SelLength = 0;
LogMemo->SelText = AnsiString((char *)LogMemoBufPtr->Memory, LogMemoBufPtr->Size);
LogMemo->SelStart = LogMemo->GetTextLen();
LogMemo->Perform(EM_SCROLLCARET, 0, 0);
LogMemo->Lines->EndUpdate();
But in FMX Memo component, I can't use "LogMemo->SelText = AnsiString(strFromMemStream)" anymore.
And I also can't use "GetTextLen" method to set selection start.
I tried to modify the code in below but it still didn't work. It always overwrite original content and can't append new text.
LogMemo->Lines->BeginUpdate();
LogMemo->GoToTextEnd();
LogMemo->SelStart = LogMemo->Text.Length();
LogMemo->SelLength = 0;
LogMemo->Text = AnsiString((char *)LogMemoBufPtr->Memory, LogMemoBufPtr->Size);
LogMemo->GoToTextEnd();
LogMemo->SelStart = LogMemo->Text.Length();
LogMemoBufPtr->Clear();
LogMemo->Lines->EndUpdate();
Is there any one know how to do it in FMX Memo component or just to display plenty of text smoothly?
Thanks!
Use the SetText function or Lines property.
In both cases I think you will have to convert the ASCII text to Unicode first.
Solution 1 - Based to the second source code provided, here is a solution to append a text in the TMemo object in FMX/FireMonkey Library.
Step 1 - Instead of trying to place the cursor and select the end of the text.
Before:
LogMemo->GoToTextEnd();
LogMemo->SelStart = LogMemo->Text.Length();
LogMemo->SelLength = 0;
Select all the text and store it in a temporary string.
After:
System::UnicodeString suTemp;
LogMemo->Lines->BeginUpdate();
LogMemo->GoToTextEnd();
LogMemo->SelStart = 0;
LogMemo->SelLength = LogMemo->Text.Length();
suTemp = LogMemo->SelText;
Step 2 - Then append the new text to the temporary string and update the Memo
suTemp += AnsiString((char *)LogMemoBufPtr->Memory, LogMemoBufPtr->Size);
LogMemo->Text = suTemp;
LogMemo->GoToTextEnd();
LogMemo->SelStart = LogMemo->Text.Length();
LogMemoBufPtr->Clear();
LogMemo->Lines->EndUpdate();
Solution 2 - Simple and faster solution when add the text at the end.
Store the current text into a temporary string and add the new text
then update the memo.
System::UnicodeString suTemp;
LogMemo->Lines->BeginUpdate();
suTemp = LogMemo->Text;
suTemp += AnsiString((char *)LogMemoBufPtr->Memory, LogMemoBufPtr->Size);
LogMemo->Text = suTemp;
LogMemo->GoToTextEnd();
LogMemoBufPtr->Clear();
LogMemo->Lines->EndUpdate();
TMemo in FireMonkey has a GoToTextEnd() method:
Moves the cursor to the end of the text in the memo control.
You can't use AnsiString in mobile platforms (without a compiler patch), nor should you anyway since TMemo holds Unicode text (same as VCL's TMemo in Delphi 2009 and later). If your TMemoryStream contains 8bit characters, you need to convert them to Unicode, such as with TEncoding, before appending them to the TMemo. The TEncoding::GetString() methods take a TBytes as input, so you could use TBytesStream instead of TMemoryStream. TBytesStream wraps a TBytes and has a public Bytes property.
Try something like this:
LogMemo->Lines->BeginUpdate();
try
{
LogMemo->GoToTextEnd();
LogMemo->SelLength = 0;
LogMemo->SelText = TEncoding::Default->GetString(LogMemoBufPtr->Bytes, 0, LogMemoBufPtr->Size);
/* or:
TEncoding *enc = TEncoding::GetEncoding(L"desired charset here");
try {
LogMemo->SelText = enc->GetString(LogMemoBufPtr->Bytes, 0, LogMemoBufPtr->Size);
}
__finally {
delete enc;
}
*/
LogMemo->GoToTextEnd();
LogMemo->SelLength = 0;
// not sure if this is the best replacement for EM_SCROLLCARET...
LogMemo->VScrollBar->Value = LogMemo->VScrollBar->Max;
}
__finally {
LogMemo->Lines->EndUpdate();
}
Update: I didn't realize that SelText is read-only in FireMonkey, unlike in VCL. In that case, you have no choice but to append to the Text property, which is not as efficient, especially for large text.
LogMemo->Lines->BeginUpdate();
try
{
LogMemo->Text = LogMemo->Text + TEncoding::Default->GetString(LogMemoBufPtr->Bytes, 0, LogMemoBufPtr->Size);
/* or:
TEncoding *enc = TEncoding::GetEncoding(L"desired charset here");
try {
LogMemo->Text = LogMemo->Text + enc->GetString(LogMemoBufPtr->Bytes, 0, LogMemoBufPtr->Size);
}
__finally {
delete enc;
}
*/
LogMemo->GoToTextEnd();
LogMemo->SelLength = 0;
// not sure if this is the best replacement for EM_SCROLLCARET...
LogMemo->VScrollBar->Value = LogMemo->VScrollBar->Max;
}
__finally {
LogMemo->Lines->EndUpdate();
}

docx4j create unnumbered / bullet list

I would like to create an unnumbered list with bullets using docx4j in my Word document. I have found the following code that is supposed to do the work. But whatever I try, the generated list is a numbered list! I use Word 2010, German version and docx4j-2.8.1.
wordMLPackage = WordprocessingMLPackage.createPackage();
ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
P p = factory.createP();
org.docx4j.wml.Text t = factory.createText();
t.setValue(text);
org.docx4j.wml.R run = factory.createR();
run.getContent().add(t);
p.getContent().add(run);
org.docx4j.wml.PPr ppr = factory.createPPr();
p.setPPr(ppr);
// Create and add <w:numPr>
NumPr numPr = factory.createPPrBaseNumPr();
ppr.setNumPr(numPr);
// The <w:ilvl> element
Ilvl ilvlElement = factory.createPPrBaseNumPrIlvl();
numPr.setIlvl(ilvlElement);
ilvlElement.setVal(BigInteger.valueOf(0));
// The <w:numId> element
NumId numIdElement = factory.createPPrBaseNumPrNumId();
numPr.setNumId(numIdElement);
numIdElement.setVal(BigInteger.valueOf(1));
wordMLPackage.getMainDocumentPart().addObject(p);
Can someone help me to generate a real unordered, buletted list?!
Hope this helps you.
import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.NumberingDefinitionsPart;
import org.docx4j.wml.*;
import javax.xml.bind.JAXBException;
import java.io.File;
import java.math.BigInteger;
public class GenerateBulletedList {
private static final String BULLET_TEMPLATE ="<w:numbering xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">" +
"<w:abstractNum w:abstractNumId=\"0\">" +
"<w:nsid w:val=\"12D402B7\"/>" +
"<w:multiLevelType w:val=\"hybridMultilevel\"/>" +
"<w:tmpl w:val=\"AECAFC2E\"/>" +
"<w:lvl w:ilvl=\"0\" w:tplc=\"04090001\">" +
"<w:start w:val=\"1\"/>" +
"<w:numFmt w:val=\"bullet\"/>" +
"<w:lvlText w:val=\"\uF0B7\"/>" +
"<w:lvlJc w:val=\"left\"/>" +
"<w:pPr>" +
"<w:ind w:left=\"360\" w:hanging=\"360\"/>" +
"</w:pPr>" +
"<w:rPr>" +
"<w:rFonts w:ascii=\"Symbol\" w:hAnsi=\"Symbol\" w:hint=\"default\"/>" +
"</w:rPr>" +
"</w:lvl>" +
"</w:abstractNum>"+
"<w:num w:numId=\"1\">" +
"<w:abstractNumId w:val=\"0\"/>" +
"</w:num>" +
"</w:numbering>";
public static void main(String[] args) throws Exception{
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
createBulletedList(wordMLPackage);
wordMLPackage.save(new File("Output.docx"));
}
private static void createBulletedList(WordprocessingMLPackage wordMLPackage)throws Exception{
NumberingDefinitionsPart ndp = new NumberingDefinitionsPart();
wordMLPackage.getMainDocumentPart().addTargetPart(ndp);
ndp.setJaxbElement((Numbering) XmlUtils.unmarshalString(BULLET_TEMPLATE));
wordMLPackage.getMainDocumentPart().addObject(createParagraph("India"));
wordMLPackage.getMainDocumentPart().addObject(createParagraph("United Kingdom"));
wordMLPackage.getMainDocumentPart().addObject(createParagraph("France"));
}
private static P createParagraph(String country) throws JAXBException {
ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
P p = factory.createP();
String text =
"<w:r xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">" +
" <w:rPr>" +
"<w:b/>" +
" <w:rFonts w:ascii=\"Arial\" w:cs=\"Arial\"/><w:sz w:val=\"16\"/>" +
" </w:rPr>" +
"<w:t>" + country + "</w:t>" +
"</w:r>";
R r = (R) XmlUtils.unmarshalString(text);
org.docx4j.wml.R run = factory.createR();
run.getContent().add(r);
p.getContent().add(run);
org.docx4j.wml.PPr ppr = factory.createPPr();
p.setPPr(ppr);
// Create and add <w:numPr>
PPrBase.NumPr numPr = factory.createPPrBaseNumPr();
ppr.setNumPr(numPr);
// The <w:numId> element
PPrBase.NumPr.NumId numIdElement = factory.createPPrBaseNumPrNumId();
numPr.setNumId(numIdElement);
numIdElement.setVal(BigInteger.valueOf(1));
return p;
}
}
The code you have posted says "use list number 1, level 0".
Evidently that list is a numbered list.
Have a look in your numbering definitions part for a bulleted list, and use that one.
If you don't have a bulleted list there, you'll need to add it. You can upload a sample docx to the docx4j online demo, to have it generate appropriate content for you. Or see ListHelper for an example of how it can be done.
private static P getBulletedParagraph(Text text, int i) {
ObjectFactory objCreator = Context.getWmlObjectFactory(); // Object used to
create other Docx4j Objects
P paragraph = objCreator.createP(); // create Paragraph object
PPr ppr = objCreator.createPPr(); // create ppr
NumPr numpr = objCreator.createPPrBaseNumPr();
PStyle style = objCreator.createPPrBasePStyle();// create Pstyle
NumId numId = objCreator.createPPrBaseNumPrNumId();
numId.setVal(BigInteger.valueOf(6));
numpr.setNumId(numId);
R run = objCreator.createR();
Br br = objCreator.createBr();
run.getContent().add(text);
Ilvl iLevel = objCreator.createPPrBaseNumPrIlvl(); // create Ilvl Object
numpr.setIlvl(iLevel);
iLevel.setVal(BigInteger.valueOf(i)); // Set ilvl value
ppr.setNumPr(numpr);
style.setVal("ListParagraph"); // set value to ListParagraph
ppr.setPStyle(style);
paragraph.setPPr(ppr);
paragraph.getContent().add(run);
// paragraph.getContent().add(br); Adds line breaks
return paragraph;
}
I believe this is what you're looking for. This method will return you a paragraph object that has bullets. If you uncomment out the last line before returning paragraph, your paragraph object will also contain line breaks. If you didn't know, "Ilvl", or "eye-level" means indentation. Its the same as clicking the tab button when typing to a document the conventional way. Setting the ilvl element to 1 is the same as clicking tab 1 time. Setting it to 2 is the same as clicking the tab button 2 times, and so on. So it doesn't matter what number you give it. Although it will change the type of bullet you get. What really matters is the numid. Setting the numid to 6 will give you bullets instead of numbers. You will also need to set the PPr style to "ListParagraph". I hope this helps.