I have a JEditorPane that displays a link containing an image like so:
<a href='http://somesite.com/'>
<img src='someImage.png' />
</a>
When the JEditorPane display this as HTML, it puts a blue border around the image which I am trying to remove without any luck.
I want it to look like this inside of the jeditorpane:
image: (http://randomcloud.net/img/prob/valid.png)
But this is how the JEditorPane displays it:
image(http://randomcloud.net/img/prob/jeditorpane.png)
This is what I have tried so far, and it still is not working
editorPane = new JEditorPane("http://randomcloud.net/ads/index.php?id=1");
StyleSheet style = ((HTMLDocument)editorPane.getDocument()).getStyleSheet();
style.addRule("a img {text-decoration: none; border: none;}");
Any suggestions or insight ?
-Michel
HTLEditorKit's ImageView source. As you can see borderSize is set to DEFAULT_BORDER (2 pixels). You can replace the ImageView creation in your implementation of ViewFactory and override the method to provide desired border (0 as I understand).
protected void setPropertiesFromAttributes() {
StyleSheet sheet = getStyleSheet();
this.attr = sheet.getViewAttributes(this);
// Gutters
borderSize = (short)getIntAttr(HTML.Attribute.BORDER, isLink() ?
DEFAULT_BORDER : 0);
leftInset = rightInset = (short)(getIntAttr(HTML.Attribute.HSPACE,
0) + borderSize);
topInset = bottomInset = (short)(getIntAttr(HTML.Attribute.VSPACE,
0) + borderSize);
borderColor = ((StyledDocument)getDocument()).getForeground
(getAttributes());
AttributeSet attr = getElement().getAttributes();
// Alignment.
// PENDING: This needs to be changed to support the CSS versions
// when conversion from ALIGN to VERTICAL_ALIGN is complete.
Object alignment = attr.getAttribute(HTML.Attribute.ALIGN);
vAlign = 1.0f;
if (alignment != null) {
alignment = alignment.toString();
if ("top".equals(alignment)) {
vAlign = 0f;
}
else if ("middle".equals(alignment)) {
vAlign = .5f;
}
}
AttributeSet anchorAttr = (AttributeSet)attr.getAttribute(HTML.Tag.A);
if (anchorAttr != null && anchorAttr.isDefined
(HTML.Attribute.HREF)) {
synchronized(this) {
state |= LINK_FLAG;
}
}
else {
synchronized(this) {
state = (state | LINK_FLAG) ^ LINK_FLAG;
}
}
}
I think the blue border is just selection of text. Try to deselect the content or use jEditorPaneInstance.getCaret().setSelectionVisible(false);
#Alien595: On img tags, you can add an attribute named border that is 0.
Example:
<a href="your_link.html">
<img border="0" src="your_image.png"/>
</a>
Related
I'm working with PowerPoint template. I'm trying to fill it with data in specific placeholders. I don't have any problem with placing text:
for (XSLFShape sh : slide.getShapes()) {
String name = sh.getShapeName();
String placeholderName = export.getPlaceholderName();
if (sh instanceof XSLFTextShape && name.equalsIgnoreCase(placeholderName)) {
XSLFTextShape txShape = (XSLFTextShape) sh;
txShape.clearText();
txShape.setText(parsedText);
}
}
I'm not able to add image to existing anchor. What I found is that first I have to collect shape data with anchor
for (XSLFShape sh : slide.getShapes()) {
String name = sh.getShapeName();
String placeholderName = export.getPlaceholderName();
if (sh instanceof XSLFPictureShape) {
XSLFPictureShape shape = (XSLFPictureShape) sh;
String shapeName = shape.getShapeName();
removeShape.setShapeName(shapeName);
removeShape.setAnchor(shape.getAnchor());
removeShape.setShape(shape);
}
}
and then add picture with anchor collected data and remove original.
XSLFPictureData pd = ppt.addPicture(removeShape.getPictureData(), PictureData.PictureType.PNG);
XSLFPictureShape pic = slide.createPicture(pd);
pic.setAnchor(removeShape.getAnchor());
slide.removeShape(removeShape.getShape());
Is there any easier way to add image to placeholder image on template?
I have created a report using dynamic reports and add a page number component and set its horizontal Alignment as right. But in printed report, page number doesn't seem to be fully right aligned.
Check this image to see the alignment issue
Note :- No right padding for page number and no trailing white spaces in page number expression.
versions used :-
dynamicreports - 3.0.2
jasperreports - 4.8.0
After lots of time spent on debugging and checking source code of dynamic reports I found the issue. I am posting this for anyone who find its helpful.
When we add PageXofYBuilder, what dynamic reports actually doing is create two text fields for 'x' and 'y'. If the component is right aligned then text field for 'x' is right aligned and text field for 'y' is left aligned with fixed width. The width of text field for 'y' is calculated as width required for a 6 digit number based on the selected font, font size and horizontal padding.
Check out the below code of pageXofY method in the class ComponentTransform which is responsible for creating the page number field in jasper design for more details :
private DRDesignList pageXofY(DRIPageXofY pageXofY, DefaultStyleType defaultStyleType) throws DRException {
TemplateTransform templateTransform = accessor.getTemplateTransform();
DRIReportStyle pageXofYStyle = pageXofY.getStyle();
if (pageXofYStyle == null) {
pageXofYStyle = accessor.getTemplateTransform().getTextStyle();
}
DRDesignStyle style = accessor.getStyleTransform().transformStyle(pageXofYStyle, true, defaultStyleType);
Integer height = templateTransform.getPageXofYHeight(pageXofY, style);
HorizontalAlignment horizontalAlignment = templateTransform.getPageXofYHorizontalAlignment(pageXofY, style);
DRStyle newStylePageX = new DRStyle();
newStylePageX.setParentStyle(pageXofYStyle);
newStylePageX.getPadding().setRight(0);
DRPen pen = new DRPen();
pen.setLineWidth(0f);
newStylePageX.getBorder().setRightPen(pen);
DRStyle newStylePageY = new DRStyle();
newStylePageY.setParentStyle(pageXofYStyle);
newStylePageY.getPadding().setLeft(0);
newStylePageY.getBorder().setLeftPen(pen);
DRTextField<String> pageXField = new DRTextField<String>();
pageXField.setAnchorNameExpression(pageXofY.getAnchorNameExpression());
pageXField.setBookmarkLevel(pageXofY.getBookmarkLevel());
pageXField.setHyperLink((DRHyperLink) pageXofY.getHyperLink());
pageXField.setPrintWhenExpression(pageXofY.getPrintWhenExpression());
pageXField.setStyle(newStylePageX);
pageXField.setHeight(height);
pageXField.setHeightType(pageXofY.getHeightType());
pageXField.setHorizontalAlignment(HorizontalAlignment.RIGHT);
pageXField.setValueExpression(new PageXofYNumberExpression(pageXofY.getFormatExpression(), 0));
DRTextField<String> pageYField = new DRTextField<String>();
pageYField.setAnchorNameExpression(pageXofY.getAnchorNameExpression());
pageYField.setBookmarkLevel(pageXofY.getBookmarkLevel());
pageYField.setHyperLink((DRHyperLink) pageXofY.getHyperLink());
pageYField.setPrintWhenExpression(pageXofY.getPrintWhenExpression());
pageYField.setStyle(newStylePageY);
pageYField.setHeight(height);
pageYField.setHeightType(pageXofY.getHeightType());
pageYField.setHorizontalAlignment(HorizontalAlignment.LEFT);
pageYField.setValueExpression(new PageXofYNumberExpression(pageXofY.getFormatExpression(), 1));
DRIGroup pageYEvaluationGroup = accessor.getGroupTransform().getFirstResetPageNumberGroup();
if (pageYEvaluationGroup == null) {
pageYField.setEvaluationTime(Evaluation.REPORT);
}
else {
pageYField.setEvaluationTime(Evaluation.GROUP);
pageYField.setEvaluationGroup((DRGroup) pageYEvaluationGroup);
}
int pageXofYWidth = templateTransform.getPageXofYWidth(pageXofY, style);
switch (horizontalAlignment) {
case LEFT:
int pageXWidth = StyleResolver.getFontWidth(style, 4);
int pageYWidth = pageXofYWidth - pageXWidth;
if (pageYWidth <= 0) {
pageYWidth = 10;
}
pageXField.setWidth(pageXWidth);
pageXField.setWidthType(ComponentDimensionType.FIXED);
pageYField.setWidth(pageYWidth);
pageYField.setWidthType(pageXofY.getWidthType());
break;
case RIGHT:
pageYWidth = StyleResolver.getFontWidth(style, 6);
pageXWidth = pageXofYWidth - pageYWidth;
if (pageXWidth <= 0) {
pageXWidth = 10;
}
pageXField.setWidth(pageXWidth);
pageXField.setWidthType(pageXofY.getWidthType());
pageYField.setWidth(pageYWidth);
pageYField.setWidthType(ComponentDimensionType.FIXED);
break;
default:
pageXField.setWidth(pageXofYWidth / 2);
pageXField.setWidthType(pageXofY.getWidthType());
pageYField.setWidth(pageXofYWidth / 2);
pageYField.setWidthType(pageXofY.getWidthType());
break;
}
DRList listPageXofY = new DRList();
listPageXofY.addComponent(pageXField);
listPageXofY.addComponent(pageYField);
return list(listPageXofY, DefaultStyleType.TEXT, null, null);
}
StyleResolver.getFontWidth() method
protected static int getFontWidth(DRDesignStyle style, int columns) {
double width = getFont(style).getStringBounds("m", context).getWidth();
return (int) Math.ceil(width * columns) + getHorizontalPadding(style);
}
How can I split a given paragraph to 2 paragraphs, due to that it fits only partial into canvas. After split, I would like to add the first part into canvas and the second to a new canvas.
public Paragraph addParagraphToPage(PdfDocument pdfDocument, int pageNum, Rectangle rectangle, Paragraph p)
{
PdfPage page = pdfDocument.getPage(pageNum);
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDocument);
Canvas canvas = new Canvas(pdfCanvas, pdfDocument, rectangle);
ParagraphRenderer currentRenderer = (ParagraphRenderer) p.createRendererSubTree();
currentRenderer.setParent(canvas.getRenderer());
result = currentRenderer.layout(new LayoutContext(new LayoutArea(pageNum, rectangle)));
ArrayList<Paragraph> paragraphs = new ArrayList<Paragraph>();
if (result.getStatus() != LayoutResult.FULL)
{
paragraphs = ????? // getNextParagraph(paragraphs, result, pageNum, rectangle, canvas);
if(paragraphs.size() == 2)
{
canvas.add( paragraphs.get(0));
return paragraphs.get(1);
}
}
return null;
}
Your approach is correct in general and layout in iText7 is flexible enough to allow you to do required thing in an easy manner. The only thing I see that is not very clear is that Paragraph is actually an element that cannot split itself and no classes in layout framework facilitate element splitting. You could do it manually, but there is no need to. Instead you should work with IRenderer, and ParagraphRenderer in particular, directly.
IRenderer can split itself as a result of layout operation and represents the necessary portion of data only compared to the Paragraph which contains full data.
You can add an IRenderer to the CanvasRenderer:
canvas.getRenderer().addChild(rendererToAdd.setParent(canvas.getRenderer()));
And you can access the partial renderers (the portion that fit the passed area and overflow part) from LayoutResult#getSplitRenderer() and LayoutResult#getOverflowRenderer().
In general, your code can be adapted like follows:
public ParagraphRenderer addParagraphToPage(PdfDocument pdfDocument, int pageNum, Rectangle rectangle, ParagraphRenderer renderer) {
PdfPage page = pdfDocument.getPage(pageNum);
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDocument);
Canvas canvas = new Canvas(pdfCanvas, pdfDocument, rectangle);
renderer.setParent(canvas.getRenderer());
LayoutResult result = renderer.layout(new LayoutContext(new LayoutArea(pageNum, rectangle)));
IRenderer rendererToAdd = result.getStatus() == LayoutResult.FULL ? renderer : result.getSplitRenderer();
canvas.getRenderer().addChild(rendererToAdd.setParent(canvas.getRenderer()));
return result.getStatus() != LayoutResult.FULL ? (ParagraphRenderer) result.getOverflowRenderer() : null;
}
And then for adding paragraph to sequential pages until all the content is placed you basically need only two lines of code:
ParagraphRenderer renderer = (ParagraphRenderer) p.createRendererSubTree();
while ((renderer = addParagraphToPage(pdfDocument, pageNum++, rectangle, renderer)) != null);
Using OnEndPage, I add a footer to my PDF created with iTextSharp. The footer font gets progressively bolder with each page.
How can I create consistent NORMAL fonts in my footer?
Here is my code:
public override void OnEndPage(PdfWriter writer, Document doc)
{
iTextSharp.text.Image gif = null;
if (FooterImage)
{
if (File.Exists(PathImages))
{
gif = iTextSharp.text.Image.GetInstance(PathImages);
gif.ScaleToFit(75f, 75f);
gif.SetAbsolutePosition(0, 0);
}
}
string sFooter = string.Empty;
if (FooterURL != null && FooterURL.Length > 0)
{
sFooter = FooterURL + " ";
}
if (FooterDate != null && FooterDate.Length > 0)
{
sFooter += FooterDate + " ";
}
if (FooterPage)
{
sFooter += "Page " + doc.PageNumber.ToString();
}
PdfPTable footerTbl = new PdfPTable(1);
footerTbl.TotalWidth = 900;
footerTbl.HorizontalAlignment = Element.ALIGN_CENTER;
Phrase ph = new Phrase(sFooter, FontFactory.GetFont(FontFactory.TIMES, 10, iTextSharp.text.Font.NORMAL));
PdfPCell cell = new PdfPCell(ph);
cell.Border = 0;
cell.PaddingLeft = 10;
footerTbl.AddCell(cell);
if (FooterImage)
{
PdfContentByte cbfoot = writer.DirectContent;
PdfTemplate tpl = cbfoot.CreateTemplate(gif.Width / 5, gif.Height / 5);
tpl.AddImage(gif);
cbfoot.AddTemplate(tpl, doc.PageSize.Width - 100, 10);
}
footerTbl.WriteSelectedRows(0, -1, 10, 30, writer.DirectContent);
}
In the old days, when there wasn't as much choice as today regarding fonts, people used workarounds to create bold fonts. One way to make a font bold, was by adding the same text over and over again at the same position. I think that this is happening to you.
When you use page events correctly, the onEndPage() method is triggered automatically each time a page ends. My guess is that you're doing something very wrong that triggers the onEndPage() many times. Maybe you are called the onEndPage() from your code, maybe you're adding the page event to the writer more than once (and page events are cumulative).
If I have to guess, I would guess that you are doing the latter. My guess is based on the fact that you are using variables such as FooterImage in your onEndPage() method. How are you setting that variable. If you are setting it in the constructor of the page event and you're adding the new page event over and over again to the writer, then you're doing it wrong.
I have made a Xcode project for a tabbed application that displays images of color swatches in a Scrollview. How do I link One of the images in my scrollview to go to the next View Controller? Below is my code and pictures. So when you click on one of the images or swatch color in the scrollview it links to the New Controller.
I have multiple images that scroll down the page of the iPhone, Do I have to loop the images cause there are 24 images. I was able to make one button and link it to the next scene with the interface builder, But I can fit 5 images on the screen..
DecorsViewController_iPhone.h
#import <UIKit/UIKit.h>
#interface DecorsViewController_iPhone : UIViewController
{
IBOutlet UIScrollView *scrollViewDecors;
}
#property (nonatomic, retain) UIView *scrollViewDecors;
#end
DecorsViewController_iPhone.m
#import "DecorsViewController_iPhone.h"
#interface DecorsViewController_iPhone ()
#end
#implementation DecorsViewController_iPhone
#synthesize scrollViewDecors;
const CGFloat kScrollObjHeight = 81.5;
const CGFloat kScrollObjWidth = 320.0;
const NSUInteger kNumImages = 24;
- (void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [scrollViewDecors subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curXLoc = 0;
CGFloat curYLoc = 0;
CGFloat curYSpace = 1;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, curYLoc);
view.frame = frame;
curYLoc += (curYSpace + kScrollObjHeight);
}
}
// set the content size so it can be scrollable
[scrollViewDecors setContentSize:CGSizeMake(([scrollViewDecors bounds].size.width), (kNumImages * kScrollObjHeight))]; // Vertical Option
}
- (void)viewDidLoad
{
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
// 1. setup the scrollview for multiple images and add it to the view controller
//
// note: the following can be done in Interface Builder, but we show this in code for clarity
[scrollViewDecors setBackgroundColor:[UIColor blackColor]];
[scrollViewDecors setCanCancelContentTouches:NO];
scrollViewDecors.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollViewDecors.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
scrollViewDecors.scrollEnabled = YES;
// pagingEnabled property default is NO, if set the scroller will stop or snap at each photo
// if you want free-flowing scroll, don't set this property.
// scrollView1.pagingEnabled = YES;
// load all the images from our bundle and add them to the scroll view
NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"Artwork_iPhone_Decors_Scrollview_%d.png", i];
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[scrollViewDecors addSubview:imageView];
//[imageView release];
}
[self layoutScrollImages]; // now place the photos in serial layout within the scrollview
}
//- (void)dealloc
//{
// [scrollViewDecors release];
//
// [super dealloc];
//}
//- (void)viewDidLoad
//{
// [super viewDidLoad];
// // Do any additional setup after loading the view, typically from a nib.
//}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
#end
Firstly, you need to add a gesture recogniser to your view with something like:
UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(flipView:)];
[singleTapGestureRecognizer setNumberOfTapsRequired:1];
[self.view addGestureRecognizer:singleTapGestureRecognizer];
You then need to implement the 'flipView' method:
- (void)flipView:(UIPanGestureRecognizer *)recognizer {
[self performSegueWithIdentifier:#"textView" sender:self];
}
As you can see in my case, when the method is triggered I perform a segue (see below):
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"textView"])
{
//---Pass text to view
CGRect visibleRect;
visibleRect.origin = scrollView.contentOffset;
visibleRect.size = scrollView.bounds.size;
int number;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
number = visibleRect.origin.x / 768;
}
else {
number = visibleRect.origin.x / 320;
}
TextViewController *textViewController = segue.destinationViewController;
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
textViewController.text = [appDelegate.textArray objectAtIndex:number];
}
}
The 'number' variable is used to decide which image has been clicked, I divide the visible rects origin by the width of the screen in pixels to calculate which image has been pressed and therefore what data to send to my new view.
In your case, you would use the Y coordinate to perform a calculation to decide which colour has been pressed, possibly something like:
int number;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
number = visibleRect.origin.y / <height of each image on iPad in pixels>;
}
else {
number = visibleRect.origin.y / <height of each image on iPhone in pixels>;
}
Alternatively, you could use a UITableView and just populate the cells with the appropriate colour and then display the new view based on which cell was pressed.
EDIT
Use a UITableView, and populate each cell with your image using custom tableview cells. This is a much easier approach than what you are suggesting.
See these links:
adding images to UItableView
If using iOS 5 -
http://kurrytran.blogspot.co.uk/2011/10/ios-5-storyboard-uitableview-tutorial.html
if not -
http://www.iosdevnotes.com/2011/10/uitableview-tutorial/
You are overcomplicating this task massively, follow the above tutorials and you'll be done in no time. If this answer helped you, please mark it as correct.
You can customize your UIImageView. For example, MyImageView. Set its delegate to your main ScrollView and add UITapGestureRecognizer and TapDetecting Delegate methods.
You can implement in the MyImageView:
- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer {
// single tap
if ([_delegate respondsToSelector:#selector(myImageViewWasSingleTapped:)])
[_delegate myImageViewWasSingleTapped:self];
}
then in your main ScrollView(delegate of MyImageView):
- (void)myImageViewWasSingleTapped:(MyImageView *)miv {
AnotherViewController *asv = [[AnotherViewController alloc] initWithImage: miv];
[self.navigationController pushViewController: asv animated:YES];
[asv release];
}
You can use a button instead of a UIImageView, and set the button's image to your image. Your loop in viewDidLoad would be like this:
// load all the images from our bundle and add them to the scroll view
NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"Artwork_iPhone_Decors_Scrollview_%d.png", i];
UIImage *image = [UIImage imageNamed:imageName];
UIButton *imageButton = [[UIButton alloc] init];
[imageButton setImage:image forState:UIControlStateNormal];
[imageButton addTarget:self action:#selector(pushNextViewController:) forControlEvents:UIControlEventTouchUpInside];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = CGRectMake(0, 0, kScrollObjWidth, kScrollObjHeight);
imageButton.frame = rect;
imageButton.tag = i; // tag our images for later use when we place them in serial fashion
[scrollViewDecors addSubview:imageButton];
// Release imageButton unless you're using ARC
}
And then you'd need to define an action for imageButton, in this case I called it pushNextViewController:
- (void)pushNextViewController:(id)sender
{
UIViewController *yourNextViewController = // initialise your next view controller here
[self.navigationController pushViewController:yourNextViewController animated:YES];
}