How do I change a header cell when the page changes? - itext

I have a PdfPTable in my document being written using iTextSharp. There are some header rows which get repeated whenever the table overflows to another page. One of those rows contains a cell with some text, e.g. "John Doe".
What I want is for that text to change to "John Doe (continued)" on each subsequent page. From what I can tell, I need to do something in the OnEndPage event that somehow manipulates the instance of the header cell for that page, but I'm struggling to find out how exactly to find the cell in the written content and then manipulate it.
How do I achieve this goal?

After some trial and error, I was able to get a working solution. I implemented the IPdfCellEvent which declares a single method, CellLayout. As per the iText documentation, this is called after the cell has been rendered, which means, the first time it is called it has rendered the cell for the very first page of the table. So, I use this call to add the extra text so that all subsequent renderings will include the additional text.
This is my interface implementation:
private class ContinuedCellEvent : IPdfPCellEvent
{
public void CellLayout( PdfPCell cell, Rectangle position, PdfContentByte[] canvases )
{
if ( !_continuationApplied )
{
// This is called AFTER cell rendering so this should set the cell for the next time it is rendered
// which will always be on a continuation.
cell.Phrase.Add( new Chunk( " Continued" ) );
_continuationApplied = true;
}
}
private bool _continuationApplied;
}
It is used when defining the cell:
cell.CellEvent = new ContinuedCellEvent();

Using onEndPage() could work, but I would implement the PdfPTableEventSplit interface if I were you. I'd use a membervariable cellContent and set it to "John Doe" upon creating the event instance. I would draw the content of cellContent in the tableLayout() method and change its content to "John Doe (continued)" in the splitTable() method.
Try it out and share your code. If it works, others will be helped; if it doesn't, I'll take a look to see what goes wrong (but please understand that I'm not a C# developer; I wrote iText in Java; I had to hire people to port it to C#).

Related

Best approach getting answer from multiplay text boxes

I've created multiple text fields where each text field accepts only 1 character and then moves to the next box. I would like to check users answer when all the text fields are filled but I'm a bit confused as to how to do so.
My first approach was to create an answer String and every time textFieldDidChange is called I add to the String the textfield.text but how can I know when all the boxes been filled and call the checkAnswer function another issue is that if the user decides to fill the boxes in a different order then when I compare the user answer to the correct answer it obviously comes incorrect as the order is different.
[here's a pic of the boxes every game round it generates a different number of boxes depending on the answer
If you know how many number of textFields you have then, you can add a property observer to yourAnswerString and as soon as the value of yourAnswerString becomes equal to numberOfTextFields, it will call the check Answer function automatically.
var yourAnswerString = "" {
didSet {
if yourAnswerString.count == numberOfTextFields {
self.checkAnswer()
}
}
}

Do I have to create a reference for each text I have in a panel, if I want to access them to modify?

I have a panel with 8 text field, 4 are used as descriptive field (what a label would do, basically), while the other 4 are modified with values.
I am creating a GameObject variable for every element that I have in the panel, using find to find the specific text element. I can leverage on the fact that each text object has only one text object attached to it, so I can address to it directly with GetComponent
panel_info = GameObject.Find("infopanel");
textfield1 = GameObject.Find("text_name");
textfield2 = GameObject.Find("text_age");
textfield3 = GameObject.Find("text_role");
textfield4 = GameObject.Find("text_field");
textfield1.GetComponent<Text>().text = "joe";
textfield2.GetComponent<Text>().text = "22";
textfield3.GetComponent<Text>().text = "striker";
textfield4.GetComponent<Text>().text = "attack";
While this works, I can't foresee myself creating 20-30 objects if a panel has more info to display.
Since I have the reference to the object Panel, is there a way to address directly the text field which is a child of the panel, using the text field name for example?
So if a panel has 4 text field, I can modify each of it addressing directly by name, and then using GetComponent<Text>().textto change the value.
You MUST NOT call GetComponent<Text>() each time you want to access/modify text.
This is an extremely basic fact about Unity.
It is immediately mentioned in the relevant manual entries.
Since you have 8 textbox and I don't know how long you update each one. It would be good if you cache all of them in the beginning of the game then use them later on without GetComponent<Text>(). This will improve performance a lot and make your frame-rate happy.
Array looks good for something like this. And you need to comment each one too.
public Text[] textBoxArray;
On the editor, Expand the "Text Box Array" and change the array Size to 8.
Now drag each GameObject with the text to the arrays in order. If you do it in order, you can easily remember their names and be able to access them in order.
For example, if the first text gameobecjt you dragged to the array is called text_name, the access it, you use textBoxArray[0]. The second text which is text_age can be accessed with textBoxArray[1]. .....
To make it easier for you later on, you should have multiple line comment that describes which array points to what.You do this so that when you return to modify your code months after, you won't have to look around in the Editor to find what points to what. For example:
/*
textBoxArray[0] = text_name
textBoxArray[1] = text_age
textBoxArray[2] = text_role
textBoxArray[3] = text_field
*/
No performance lost and that decreases the amount of code in your game.
Initializing the arrays by code instead of the Editor
Assuming you want to initialize the arrays by code instead of the Editor. You can do it in the start function like below.
public Text[] textBoxArray;
void Start()
{
//Create arrays of 8
textBoxArray = new Text[8]; //8 texts
//Cache all the Text GameObjects
textBoxArray[0] = GameObject.Find("/infopanel/text_name").GetComponent<Text>();
textBoxArray[1] = GameObject.Find("/infopanel/text_age").GetComponent<Text>();
textBoxArray[2] = GameObject.Find("/infopanel/text_role").GetComponent<Text>();
textBoxArray[3] = GameObject.Find("/infopanel/text_field").GetComponent<Text>();
}
You should notice that GameObject.Find() starts with "/" and that increases performance too as it will only search for Texts under "infopanel" instead of searching in the whole scene.
Assuming that your hierarchy is setup that all your TextMeshes are children of the panel, you could use the Transform.Find method to get each child, then it's TextMesh, and assign a value.
So, for example, if you wanted to assign the value "Joe" to the TextMesh attached to "text_name", which in turn is a child of "infopanel", you could do the following
panel_info = GameObject.Find("infopanel");
panel_info.transform.Find("text_name").GetComponent<TextMesh>().text = "Joe";

NSTableView with custom cell view and NSArrayController bindings drawing a blank string

It took me forever to figure out how to set up editing on a custom cell view for an NSTableView. Thanks to StackOverflow I figured that much out. P.S. I was doing all of this in Interface Builder.
I have a single column table in which the cell is a custom multi-control NSTableCellView, with:
name (in bold)
description
detail
It's all text. Set up editability on the name only. The table is sorted by the name.
When I edit the name, it has the effect on the bound model that I expect. The table even re-sorts correctly. However, it's displaying incorrectly. The description and detail (not editable) still show up correctly, but the name (which was edited) is a blank. When I inspect the model, it has the correct updated value. But the cell view itself is incorrect.
This doesn't happen all the time--it typically happens if the cell is re-sorted to the top or bottom of the table, but that may be a red herring and may instead have to do with NSTableView cell caching or something.
I hacked up a workaround in which I assign a delegate to the NSTextField (automatically generated for the NSTableCellView) and intercept the textShouldEndEditing event. For some reason this event is getting triggered twice for a given edit (after I press "enter" in the text field)--once for the actual edit where fieldEditor.string is different from the model name, followed by another event where fieldEditor.string is the same as the model name. If I return false for my textShouldEndEditing handler in the latter case, then the cell contents end up being drawn correctly. That's the hack.
I feel like I'm doing something wrong here though, and that shouldn't be necessary.
Is the textShouldEndEditing event supposed to be fired twice?

Create words starting with sign '#' Clickable in ios

I have a table view in which each row contains various information like name, picture, message etc.
This message may contain some words starting with '#' or '#'. I want to make these words clickable and on click i want to open another view controller instead of browser.
I know we can set UIDataDetector type on textview for links but that only works for links.
Is there any way so that I can tell textview to detect text matching some regular expression and then make that text clickable ?
EDIT:
Finally I am able to achieve this, for those who are still dealing with this issue, I have written a blog post:
http://www.uditagarwal.com/2013/10/make-different-words-in-uitextview.html
Answer : GLTapLabel
There is a method named -drawTextInRect in class named GLTapLabel which contains one line of code :
BOOL hot = [word hasPrefix:#"#"] || [word hasPrefix:#"#"];
You just have to change the prefix values here and you will have your desired result.
There is one delegate method named -labledidSelectedHotWord. You can write here the code about the action you want to perform when the word with desired prefix is clicked. In your case, you can write your navigation code in this method.
Here is the Screenshot :

GWT ClickableTextCell

I am a newbie to GWT ... need some help in understanding the below class -
What is the use of GWT ClickableTextCell ??
Is there something specific use of it. It uses something called FieldUpdater, why is that used ?
Think of a ClickableTextCell as hot spot. It looks like a regular bit of screen real estate with text in it, but it responds to clicks. What happens when you click it? The click "updates" the field. An update to a field calls the method update(). What does update() do? Whatever you want it to. You provide it by specifying the FieldUpdater. FieldUpdater is an interface, so you can construct one anonymously. Say you have a CellTable, and you have a Column that displays a String inside a ClickableTextCell. You provide your FieldUpdater to the Column:
Column<DataType, String> myIntegerColumn
= new Column<DataType, String>(new ClickableTextCell());
myIntegerColumn.setFieldUpdater(new FieldUpdater<DataType, String>(){
#Override
public void update(int index, DataType object, String value){
// execute code that reacts to a click on this hot spot
}
});
Now whenever the cell gets clicked, that code in update() fires.
A ClickableTextCell is a specific kind of cell. You can see a demo of all the different kinds of cells in this GWT showcase.
This GWT documentation explains what cell widgets are for, goes over all of the different types, and also has examples of how to use them and the ValueUpdater type.