iText7 html to pdf cannot break long words - word-wrap

I am using iText7 to convert html to pdf. I have issue with breaking long words. (Only breaking up words if they don't fit).
<td>The labrado is jumping over the fence tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt</td>
I have tried to override IsSplitCharacter to always return true, but that causes it to break words at unwanted places like image below (breaking the word "jump-ing").
public class CustomSplitCharacters : DefaultSplitCharacters
{
public override bool IsSplitCharacter(GlyphLine text, int glyphPos)
{
return true;
}
}
I apology if this question is similar to other posts. But i can't seem to find the right solution. And i don't have enough reputations to follow up on those posts with comments.
Thank you in advance for your help.

I have created a temporary solution
public class CustomSplitCharacters : DefaultSplitCharacters
{
public override bool IsSplitCharacter(GlyphLine text, int glyphPos)
{
bool baseResult = base.IsSplitCharacter(text, glyphPos);
bool myResult = IsSpecialCharacter((char)text.Get(glyphPos).GetUnicode());
return baseResult || myResult;
}
private bool IsSpecialCharacter(char c)
{
Regex regexItem = new Regex("[a-zA-Z0-9]");
return !regexItem.IsMatch(c.ToString());
}
}
This would work for the most cases. But it still cannot break a long word. I am still hoping to get an answer for the extreme case. Your reply is much appreciated.

Related

How to get the number of lines written in IText 7

I'm upgrating from IText 5 to IText 7. The code below is from version 5 which has a method to get the actual number of lines written. How can I accomplish the same using IText 7?
Paragraph p = new Paragraph(veryLongText, font);
ColumnText column1 = new ColumnText(writer.DirectContent);
column1.SetSimpleColumn(bottomX, bottomY, topX, 100);
column1.AddElement(p);
column1.Go(true);
noOfLines = column1.LinesWritten; <---- No of Lines
Layout mechanism in iText 7 is much more complex and feature-rich than mechanism in iText 5, and notion of written lines might be very much opinion-based in many complex layout cases. That's why the number of written lines is not maintained by the layout engine and is not available for query. However, it's very easy to extend your elements/renderers to support calculating the number of written lines. Here is how to do it. First, you need to override a Paragraph to aggregate the number of lines and ParagraphRenderer to provide the info of the lines written back to Paragraph:
private static class LineCountingParagraph extends Paragraph {
private int linesWritten = 0;
public LineCountingParagraph(String text) {
super(text);
}
public void addWrittenLines(int toAdd) {
linesWritten += toAdd;
}
public int getNumberOfWrittenLines() {
return linesWritten;
}
#Override
protected IRenderer makeNewRenderer() {
return new LineCountingParagraphRenderer(this);
}
}
private static class LineCountingParagraphRenderer extends ParagraphRenderer {
public LineCountingParagraphRenderer(LineCountingParagraph modelElement) {
super(modelElement);
}
#Override
public void drawChildren(DrawContext drawContext) {
((LineCountingParagraph)modelElement).addWrittenLines(lines.size());
super.drawChildren(drawContext);
}
#Override
public IRenderer getNextRenderer() {
return new LineCountingParagraphRenderer((LineCountingParagraph) modelElement);
}
}
Now, just use the customized classes instead of the standard ones and query the information after an element was added to a Document or Canvas:
LineCountingParagraph p = new LineCountingParagraph("text");
document.add(p);
System.out.println(p.getNumberOfWrittenLines());
Note that this mechanism also allows you to calculate the number of lines written that satisfy some condition. You can analyze elements in lines list.

A algorithm to track the status of a number

To design a API,
get(), it will return the random number, also the number should not duplicate, means it always be unique.
put(randomvalue), it will put back the generated random number from get(), if put back, get() function can reuse this number as output.
It has to be efficient, no too much resource is highly used.
Is there any way to implement this algorithm? It is not recommended to use hashmap, because if this API generate for billions of requests, saving the generated the random number still use too much space.
I could no work out this algorithm, please help give a clue, thanks in advance!
I cannot think of any solution without extra space. With space, one option could be to use TreeMap, firstly add all the elements in treeMap with as false. When element is accessed, mark as true. Similarly for put, change the value to false.
Code snippet below...
public class RandomNumber {
public static final int SIZE = 100000;
public static Random rand;
public static TreeMap<Integer, Boolean> treeMap;
public RandomNumber() {
rand = new Random();
treeMap = new TreeMap<>();
}
static public int getRandom() {
while (true) {
int random = rand.nextInt(SIZE);
if (!treeMap.get(random)) {
treeMap.put(random, true);
return random;
}
}
}
static public void putRandom(int number) {
treeMap.put(number, false);
}
}

How to write an extension that displays different text than the underlying file? (like the parameter names)

I want to write an extension for Visual Studio that replaces the "var" keyword with the explicit type, but only visually and not in the code itself.
After some MSDN and web resarches, I tried using the VisualBuffer (the projection buffer) of the ITextViewModel, but it also changes the code in the file.
Here for example I tried it the other way around by replacing "int" with "var"
[Export(typeof(ITextViewCreationListener))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]
internal class TestViewCreationListener : ITextViewCreationListener
{
private ITextBuffer _buffer;
public void TextViewCreated(ITextView textView)
{
ITextViewModel textVM = textView.TextViewModel;
_buffer = textVM.VisualBuffer;
string text = _buffer.CurrentSnapshot.GetText();
int index = text.IndexOf("int ");
while (index > 0)
{
_buffer.Replace(new Span(index, 3), "var");
index = text.IndexOf("int ", index + 4);
}
}
}
Thanks in advance :)
Ah, I found a solution by myself. Using an IntraTextAdornmentTagger did it :)

Using FormFlow Bots Framework Quiz Program

Our bot build does a ‘personality quiz’ for the user. Think Buzzfeed.
I have a variety of attributes I want to increase, just integers, based on the user’s selections on a form, then return an end result.
Using Sandwichbot as a template, this is asking something like (paraphrased):
Do you like to help other people? Yes No
Code is like:
.Confirm(async (state) =>
{
switch (state.HelpYesNo)
{
case true: HelpfulValue++; break;
case false: HurtfulValue++; break;
}
return new PromptAttribute("Thanks, choose OK to continue.");
It works fine, but I hate that I have to make the user ‘Confirm’ by typing OK. It’s an extra step, especially if they have to do it after each question.
I tried writing this with a validate instead, eg validate: async (state, response) =>
Which gives a better user experience, but doesn’t actually run the switch-case. I think the formatting of the switch is in the wrong place for a validate? I'm not sure of the syntax here to get 'validate' to process the case.
What’s the right way to do something like this in FormFlow?
Try something like this. Boolean fields also result in a Yes/No question.
[Serializable]
public class QuizForm
{
public int HelpfulValue;
public int HurtfulValue;
[Prompt("Do you like to help people? {||}")]
public bool HelpPeople;
public static IForm<QuizForm> BuildForm()
{
return new FormBuilder<QuizForm>()
.Message("Let the quiz begin...")
.Field(nameof(HelpPeople), validate: ValidateBool)
// other fields
.Build();
}
private static async Task<ValidateResult> ValidateBool(QuizForm state, object value)
{
var TrueOrFalse = (bool) value;
switch (TrueOrFalse)
{
case true: state.HelpfulValue++; break;
case false: state.HurtfulValue++; break;
}
return new ValidateResult{IsValid = true, Value = value};
}
}

SubSonic 3 ActiveRecord generated code with warnings

While using SubSonic 3 with ActiveRecord T4 templates, the generated code shows many warnings about CLS-compliance, unused items, and lack of GetHashCode() implementation.
In order to avoid them, I did the following modifications:
// Structs.tt
[CLSCompliant(false)] // added
public class <#=tbl.CleanName#>Table: DatabaseTable
{ ...
// ActiveRecord.tt
[CLSCompliant(false)] // added
public partial class <#=tbl.ClassName#>: IActiveRecord
{
#region Built-in testing
#pragma warning disable 0169 // added
static IList<<#=tbl.ClassName#>> TestItems;
#pragma warning restore 0169 // added
...
public override Int32 GetHashCode() // added
{
return this.KeyValue().GetHashCode();
}
...
Is there a better way to get rid of the warnings? Or a better GetHashCode() implementation?
Currently, the only way to get rid of the warnings is to update your t4 templates and submit a bug/fix to Rob. Or wait until somebody else does.
As for the GetHashCode implementation, I don't think you're going to find a good way to do this through templates. Hash code generation is very dependent on what state your object contains. And people with lots of letters after their name work long and hard to come up with hash code algorithms that are fast and return results with low chances of collision. Doing this from within a template that may generate a class with millions of different permutations of the state it may hold is a tall order to fill.
Probably the best thing Rob could have done would be to provide a default implementation that calls out to a partial method, checks the result and returns it if found. Here's an example:
public partial class Foo
{
public override int GetHashCode()
{
int? result = null;
TryGetHashCode(ref result);
if (result.HasValue)
return result.Value;
return new Random().Next();
}
partial void TryGetHashCode(ref int? result);
}
public partial class Foo
{
partial void TryGetHashCode(ref int? result)
{
result = 5;
}
}
If you compile this without the implementation of TryGetHashCode, the compiler completely omits the call to TryGetHashCode and you go from the declaration of result to the check to see if it has value, which it never will, so the default implementation of the hash code is returned.
I wanted a quick solution for this as well. The version that I am using does generate GetHashCode for tables that have a primary key that is a single int.
As our simple tables use text as their primary keys this didn't work out of the box. So I made the following change to the template near line 273 in ActiveRecord.tt
<# if(tbl.PK.SysType=="int"){#>
public override int GetHashCode() {
return this.<#=tbl.PK.CleanName #>;
}
<# }#>
<# else{#>
public override int GetHashCode() {
throw new NotImplementedException();
}
<# }#>
This way GetHashCode is generated for all the tables and stops the warnings, but will throw an exception if called (which we aren't).
We use this is for a testing application, not a website or anything like that, and this approach may not be valid for many situations.

Resources