I am using the ITextSharp for creating a PDF document. As part of creating a document, I have to render a HTML block in a window of a particular page. I am using the below code to render the HTML. Surprisingly it is not rendering the HTML.
I have attached the HTML Here
public override Rectangle Draw(Rectangle curRectangle)
{
try
{
var column = new ColumnText(this.DocRenderer.PdfDocContentByte);
string css = "p {font-family:HELVETICA; font-style:normal; color:black; font-size:10px}"
+ " li {font-family:HELVETICA; font-style:normal; color:black;font-size:10px}";
foreach (var element in XMLWorkerHelper.ParseToElementList(FileContents of guide.html, css))
{
column.AddElement(element);
}
curRectangle = this.SimulateHeight(curRectangle, column);
column.SetSimpleColumn(curRectangle);
column.Go(false);
}
catch (Exception ex)
{
Logger.LogError(ex.Message, ex);
}
return curRectangle;
}
private Rectangle SimulateHeight(Rectangle curRectangle,ColumnText column)
{
float top = 15;
column.SetSimpleColumn(curRectangle.Left, curRectangle.Bottom, curRectangle.Right, top);
int status = column.Go(true);
top = column.YLine-1;
return new Rectangle(curRectangle.Left, curRectangle.Bottom, curRectangle.Right, top);
}
Even if it only is simulating, your line
int status = column.Go(true);
swallows all composite content added to column if all that content fits into the rectangle. (This allows to easily simulate drawing yet more composite content to the same ColumnText.)
Thus, if the status value is ColumnText.NO_MORE_TEXT, you'll have to add it again, e.g. like this:
private iTextSharp.text.Rectangle SimulateHeight(iTextSharp.text.Rectangle curRectangle, ColumnText column)
{
var compositeContent = new List<IElement>(column.CompositeElements);
float top = 15;
column.SetSimpleColumn(curRectangle.Left, curRectangle.Bottom, curRectangle.Right, top);
int status = column.Go(true);
if (ColumnText.NO_MORE_TEXT == status)
{
foreach (var element in compositeContent)
{
column.AddElement(element);
}
}
top = column.YLine - 1;
return new iTextSharp.text.Rectangle(curRectangle.Left, curRectangle.Bottom, curRectangle.Right, top);
}
Actually even for other status values that list may be partially emptied of the top level elements that did fit. In your case, though, there is but one top level element, the div, so if that does not fit completely, it remains.
As an aside, you use a top value located near to the actual bottom of the page, so it actually is the bottom y coordinate. Such a naming is quite misleading.
Related
Just starting out hope this isn’t too noob a question
For the game I’m working on I want to have different tabs, the effect of which would be similar to an iOS bottom tab controller as pictured:
Where I’m at a loss is how to create this? Should this all be on one Scene with different layers being turned on and off? Should I be using multiple Scenes?
Seems like keeping this in one scene wouldn’t really scale. How is this normally done, does cocos2d-x have some sort of concept of containers or something?
I would suggest that you have 2 layers:
The first layers will deal with the images. I guess you can use
ImageView. and position them with the size that you want.
The second part is a tab menu that can be implemented with a second
layer in which you will add the buttons and the background. for the
buttons use the Button class.
I hope that helps.
bool ScreenController::init(){
if(Layer::init())
{
footer = Footer::create();
footer->setDelegate(this);
this->addChild(footer,3);
auto homeLayer= HomeView::create(psize,this);
homeLayer->setPosition(Point(0,footer->getBoundingBox().getMaxY()));
// homeLayer->setAllApiFireTo(this);
auto rakeLayer = RakeView::create(psize);
rakeLayer->setPosition(Point(0,footer->getBoundingBox().getMaxY()));
rakeLayer->setDelegate(this);
Tablayers = LayerMultiplex::create();
Tablayers->addLayer(homeLayer);
Tablayers->addLayer(rakeLayer);
this->addChild(Tablayers);
}
}
void ScreenController::TabControllerAction(ViewDisplayType type) {
Tablayers -> switchTo(index);
}
bool Footer::init(){
if(Layer::init())
{
this->setContentSize(Size(constantDeviceSize.width,108*gamescaleY));
// auto btlayer = LayerColor::create(Color4B::RED,this->getContentSize().width,this->getContentSize().height);
//
// this->addChild(btlayer);
SubButton*sb1 = SubButton::create(Size(this->getContentSize().width/5,this->getContentSize().height),"Home.png","Home.png",CC_CALLBACK_2(Footer::callMenuItem, this) );
sb1->setAnchorPoint(Point(0,0));
sb1->setPosition(Point(0,0));
sb1->addTitleText("Home", SFUI_Regular.c_str());
sb1->colorEfact(true);
sb1->setColorbtn(Color3B::WHITE,colorSkyBlue3B);
this->addChild(sb1);
SubButton*sb2 = SubButton::create(Size(this->getContentSize().width/5,this->getContentSize().height),"Balance.png","Balance.png",CC_CALLBACK_2(Footer::callMenuItem, this));
sb2->setAnchorPoint(Point(0,0));
sb2->setPosition(Point(sb2->getBoundingBox().size.width,0));
sb2->addTitleText("Rake", "arial.ttf");
sb2->colorEfact(true);
sb2->setColorbtn(Color3B::WHITE,colorSkyBlue3B);
this->addChild(sb2);
sb1->setDisplayType(myHomeView);
sb2->setDisplayType(myRakeView);
}
void Footer::selectionByController(int tab)
{
auto tmpbar = dynamic_cast<SubButton *>(this -> getChildren().at(tab-1));
callMenuItem(tmpbar, TouchBegan);
}
void Footer::callMenuItem(Ref *sender, TouchEvent event)
{
if(event==TouchBegan)
{
auto sbitem = (SubButton*)sender;
if(event==TouchBegan)
{
sbitem->selected();
if(this->getDelegate())
{
this->getDelegate()->TabControllerAction(sbitem->getDisplayType());/*call to parant*/
}
CCLOG("CLICKED!->%d",sbitem->getTag());
}
for (int i = 0; i < this->getChildren().size(); i++)
{
auto tmpbar = dynamic_cast<SubButton *>(this -> getChildren().at(i));
if (tmpbar != NULL && tmpbar -> getTag() != sbitem -> getTag())
{
tmpbar ->unSelected();
}
}
}
}
I have a responsive app for desktop and mobile.
In the app i have a div which randomly shows texts of all kinds of lengths.
I want to do the following:
If the line breaks because the length of the text is too wide for the width of that div, i want the font-size to reduce itself (I am using em's in my app).
Is it something i need to build directive for it? is it something that was built and used wildly?
Writing a robust solution for this problem is going to be non-trivial. As far as I know, there's no way to tell whether a line of text breaks. However, we do know the criteria for line breaking is the width of the text being wider than the element, accounting for padding.
The Canvas API has a method called measureText which can be used to measure a string, using a given context with a font and size set. If you spoof the settings of the element with a canvas, then you can measure the text with the canvas and adjust the size until it fits without overflowing.
I've written up a rough implementation of the way I would tackle this.
function TextScaler(element) {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
var scaler = {};
scaler.copyProps = function() {
var style = element.style.fontStyle,
family = element.style.fontFamily,
size = element.style.fontSize,
weight = element.style.fontWeight,
variant = element.style.fontVariant;
context.font = [style, variant, weight, size, family].join(' ');
};
scaler.measure = function(text) {
text = text || element.innerText;
return context.measureText(text);
};
scaler.overflows = function() {
var style = window.getComputedStyle(element),
paddingLeft = style['padding-left'],
paddingRight = style['padding-right'],
width = style.width - paddingLeft - paddingRight;
return scaler.measure() > width;
};
scaler.decrease = function() {
// decrease font size by however much
};
scaler.auto = function(retries) {
retries = retries || 10;
if(retries <= 0) {
scaler.apply();
console.log('used all retries');
}
if(scaler.overflows()) {
scaler.decrease();
scaler.auto(retries - 1);
} else {
console.log('text fits');
scaler.apply();
}
};
scaler.apply = function() {
// copy the properties from the context
// back to the element
};
return scaler;
}
After you've sorted out some of the blank details there, you'd be able to use the function something like this:
var element = document.getElementById('');
var scaler = TextScaler(element);
scaler.auto();
If it doesn't manage to decrease it within 10 retries, it will stop there. You could also do this manually.
while(scaler.overflows()) {
scaler.decrease();
}
scaler.apply();
You'd probably want some fairly fine tuned logic for handling the decrease function. It might be easiest to convert the ems to pixels, then work purely with integers.
This API could quite trivially be wrapped up as a directive, if you want to use this with Angular. I'd probably tackle this with two attribute directives.
<div text-scale retries="10">Hello world</div>
Of course, if it's not important that all the text is there onscreen, then you can just use the text-overflow: ellipsis CSS property.
I'm trying to make a custom GTK widget in Vala, but I'm already failing at the very first basic attempt, so I'd like some help in knowing where I'm going wrong. I feel like I must be missing something painstakingly obvious, but I just can't see it.
I have three files with the following contents:
start.vala:
using Gtk;
namespace WTF
{
MainWindow main_window;
int main(string[] args)
{
Gtk.init(ref args);
main_window = new MainWindow();
Gtk.main();
return 0;
}
}
main_window.vala:
using Gtk;
namespace WTF
{
public class MainWindow : Window
{
public MainWindow()
{
/* */
Entry entry = new Entry();
entry.set_text("Yo!");
this.add(entry);
/* */
/*
CustomWidget cw = new CustomWidget();
this.add(cw);
/* */
this.window_position = WindowPosition.CENTER;
this.set_default_size(400, 200);
this.destroy.connect(Gtk.main_quit);
this.show_all();
}
}
}
custom_widget.vala:
using Gtk;
namespace WTF
{
public class CustomWidget : Bin
{
public CustomWidget()
{
Entry entry = new Entry();
entry.set_text("Yo");
this.add(entry);
this.show_all();
}
}
}
As you can see, in main_window.vala, I have two sets of code. One that adds the Entry widget directly, and one that adds my custom widget. If you run the one that adds the Entry widget directly, you get this result:
If you run the one with the custom widget, however, you get this result:
Just for the record, this is the complication command I use:
valac --pkg gtk+-2.0 start.vala main_window.vala custom_widget.vala -o wtf
EDIT:
Following user4815162342's suggestion, I implemented the size_allocate method on my custom Bin widget, like so:
public override void size_allocate(Gdk.Rectangle r)
{
stdout.printf("Size_allocate: %d,%d ; %d,%d\n", r.x, r.y, r.width, r.height);
Allocation a = Allocation() { x = r.x, y = r.y, width = r.width, height = r.height };
this.set_allocation(a);
stdout.printf("\tHas child: %s\n", this.child != null ? "true" : "false");
if (this.child != null)
{
int border_width = (int)this.border_width;
Gdk.Rectangle cr = Gdk.Rectangle()
{
x = r.x + border_width,
y = r.y + border_width,
width = r.width - 2 * border_width,
height = r.height - 2 * border_width
};
stdout.printf("\tChild size allocate: %d,%d ; %d, %d\n", cr.x, cr.y, cr.width, cr.height);
this.child.size_allocate(cr);
}
}
It writes the following in the console:
Size_allocate: 0,0 ; 400,200
Has child: true
Child size allocate: 0,0 ; 400, 200
And the window renders thusly:
GtkBin is an abstract single-child container, typically intended to decorate the child widget in some way, or change its visibility or size. Without some added value, a single-child container would be indistinguishable from the widget it contains and therefore not very useful.
Since GtkBin doesn't know what kind of decorations you will draw around the child, it expects you to implement your own size_allocate. A simple implementation is available in gtk_event_area_size_allocate, a more complex one in gtk_button_size_allocate.
This answer shows a minimal size_allocate implementation in PyGTK which should be straightforward to port to Vala. If you do anything more complex than that, you will need to also implement expose, and possibly other methods, but this will get you started.
I am using Flex 4 with Spark components to build a mobile application and I have a HGroup that I am using to contain all of my elements. When the screen loads it pulls in a small amount of text that will be displayed and loops through all the words to see if any of them are a keyword. While it is looping I am putting each word into its own label element and if the word is a keyword it changes a few styles and adds a click event to show a description about the word.
Everything runs fine but when everything is appended to the HGroup, there ends up being only one line and most of the text completely cut off because it will not wrap the content.
My Question is - Is there a way to set or extend the HGroup to allow content wrapping on its child elements?
Below are some code snippets of what I have:
MXML containers:
<s:VGroup id="answerData" width="580" height="700" horizontalAlign="center" paddingTop="5">
<s:HGroup id="theLabel" color="white" width="580" fontSize="25" paddingBottom="20" />
<s:HGroup id="theText" color="white" width="580" fontSize="25" maxWidth="580" />
</s:VGroup>
AS to create labels:
public static function setKeyWords(someText:String, theGroup:Group, theDictionary:Array, theView:Object):void {
theGroup.removeAllElements();
var textArray:Array = someText.split(' ');
for(var i:int = 0, l:int = textArray.length; i < l; i++) {
if(checkForWord(theDictionary, textArray[i].toString())) {
var theLink:Label = new Label();
theLink.text = textArray[i].toString();
theLink.setStyle("color", "0xFFFF00");
theLink.setStyle("fontWeight", "bold");
theLink.maxWidth = 580;
var tmpDescrip:String = theDescription;
theLink.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
showToolTip(tmpDescrip, theView);
});
theGroup.addElement(theLink);
} else {
var someLabel:Label = new Label();
someLabel.maxWidth = 580;
someLabel.text = textArray[i].toString();
theGroup.addElement(someLabel);
}
}
}
The issue that I was having is, I had multiple lables in a VGroup and needed them to wrap instead of extending past the containers set width. I was trying to integrate keywords into a dynamic paragraph of text. I could not use mx:Text because I needed each word to be its own component that allowed custom styling plus a mouse click even if the word was a keyword. Also the label max lines solution would not work because I am dealing with multiple lables in a VGroup and the VGroup needed to wrap its children not the label tags. I also could not use a TileGroup because it does not look right breaking a paragraph into a table looking component where each word is in its own column/row.
The solution I used was to count each character in the label being generated and add it to a variable to determine when I need to create a new HGroup that holds the labels and sits in a VGroup. I had to do this because I cannot determine the labels width until it renders because it is generated dynamically. This could not be done because as its render point is too late for me to move everything because the user can see all of this happening which is definitely not the desired effect.
Below is the code I used to solve this issue incase anyone else runs into this issue:
public static function setKeyWords(someText:String, theGroup:Group, theDictionary:Array, theView:Object):void {
theGroup.removeAllElements();
var textArray:Array = someText.split(' ');
var theCount:int = 0;
var theHGroup:HGroup = new HGroup();
var breakNum:int = 40;
theHGroup.percentWidth = 100;
for(var i:int = 0, l:int = textArray.length; i < l; i++) {
theCount += textArray[i].toString().length;
if(theCount >= breakNum) {
theGroup.addElement(theHGroup);
theHGroup = new HGroup();
theHGroup.percentWidth = 100;
theCount = 0;
}
if(checkForWord(theDictionary, textArray[i].toString())) {
theCount += 1;
var theLink:Label = new Label();
theLink.text = textArray[i].toString();
theLink.setStyle("color", "0xFFFF00");
theLink.setStyle("fontWeight", "bold");
theLink.maxWidth = 580;
//theLink.includeInLayout = false;
var tmpDescrip:String = theDescription;
theLink.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
showToolTip(tmpDescrip, theView, 'keywords');
});
theHGroup.addElement(theLink);
} else {
theCount += 1;
var someLabel:Label = new Label();
someLabel.maxWidth = 580;
someLabel.text = textArray[i].toString();
//someLabel.includeInLayout = false;
theHGroup.addElement(someLabel);
}
}
if(theCount > 0)
theGroup.addElement(theHGroup);
}
This may not be the most effecient way to do this but it does work and takes little time to execute on the Iphone which is what I was aiming for.
Not fully sure I understand your question.
If you mean the Label's are truncated, you might want to set a percentWidth and wrap Labels with maxDisplayedLines:
someLabel.maxDisplayedLines = 10;
If you mean you want columns and rows to your Group layout, use TileGroup / TileLayout.
If the children of your group contain composite content that must float, some kind of includeInLayout=false might help.
If you want text to show in block of several lines, use mx:Text with width set.
To display something above HGroup, easiest way is to leave HGroup alone and just make transparent container (Canvas) above it. There you'll be free to display anything (just do the math to position it correctly.)
I've got a flash vertical menu which has auto-scroll but it scrolls too fast and the only way to slow it down is to increase the height of the button.
I would like to replace the code with a scrollpane so I can control the menu:
Code chunk I need to remove then add the additional scrollpane code
menu_mc_Europe.onEnterFrame = function() {
if (_ymouse>10 && _ymouse<boundry_mc._height && _xmouse>0 && _xmouse<boundry_mc._width) {
ratio = (menu_mc_Europe._height-boundry_mc._height)/(boundry_mc._height);
if (_ymouse>boundry_mc._height/2) {
destScroll = -(_ymouse)*ratio-menu_mc_Europe.bttn_mc._height*ratio;
} else {
destScroll = -(_ymouse)*ratio
}
menu_mc_Europe._y += Math.round((destScroll-menu_mc_Europe._y)/5);
if (menu_mc_Europe._y<-(totalBttns*menu_mc_Europe.bttn_mc._height-boundry_mc._height)) {
menu_mc_Europe._y = -(totalBttns*menu_mc_Europe.bttn_mc._height-boundry_mc._height);
}
} else {
destScroll = 1;
menu_mc_Europe._y += Math.round((destScroll-menu_mc_Europe._y)/5);
}
};
hard to read that code w/out line breaks - what does 'ratio' represent above? is it a variable you can set? if not, just a wild guess, but try changing the divisor (the 5) in the '_y)/5' sections above?