java PrintService, missing MediaSize in getSupportedAttributeValues - java

In the settings of the printer I made a new Format named custom1 with width 57 and height 100. Also I changed the custom format to the same width and height.
With the following routine I tried to figure out the supported mediasizes:
Media[] res = (Media[])printService.getSupportedAttributeValues(Media.class, null, null);
for (Media media : res) {
if (media instanceof MediaSizeName) {
MediaSizeName msn = (MediaSizeName) media;
MediaSize ms = MediaSize.getMediaSizeForName(msn);
float width = ms.getX(MediaSize.MM);
float height = ms.getY(MediaSize.MM);
System.out.println("Class:" + msn.getClass().getName()
+ "; toString:" + msn.toString() + "; width:"
+ width + "; height:" + height);
}
}
But in the list is neither custom nor custom1. Also about the half number of the formats are missing in the list.
What is the problem? Does this printer not support the MediaSizes in Java?
What can I do?
When I test this on another printer the custom MediaSize with the right width and height is supported. Where is the problem with this printer?
Thanks for all answers

Related

How to detect a screen cutout (notch) and get its height?

I need to get the exact coordinates of a point relative to the screen regardless of the app window's dimensions or offsets/insets. The phone I'm developing on has a 1080x2280 resolution and android 9. I tried to find the screen dimensions using getDefaultDisply, but the notch height is getting subtracted from the screen:
// Testing with notch hidden; the screen is pushed down below it
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); // 1080x2062 (-notification bar height!)
getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics); // 1080x2192 (actual window height when notch is hidden)
How do I get the real resolution and the notch heigh when it's hidden?
Solution I found was to use getRealMetrics to get the height of the screen.
getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics)
This calculates the height of the screen by including the height of the notch as well. Works for both Notched Mode ON/OFF also for devices without Notch
I found my own solution that works on rooted devices only (requires Shell library):
public static int getCutoutHeight() {
CommandResult result = Shell.SU.run("dumpsys display | grep mCurrentDisplayRect");
String output = result.getStdout();
String regex = "^\\s+mCurrentDisplayRect=Rect\\(\\d+, (\\d+) - \\d+, \\d+\\)*$";
if (output != null) {
if (output.matches(regex)) {
Pattern patt = Pattern.compile(regex);
Matcher matcher = patt.matcher(output);
if (matcher.find()) {
return Integer.parseInt(matcher.group(1));
}
}
else Log.e(TAG, "Unexpedted outptu: " + output);
}
else Log.e(TAG, "Command failed: " + result.getStderr());
return 0;
}
Hopefully a better answer will come up soon.

Avoid tooltip grabbing mouse focus

How can I spawn a tooltip close to my cursor without the OnMouseExit handler being called. Is there any way to make the tooltip opaque to mouse focus?
A JIRA issue was created several years ago describing a similar situation: https://bugs.openjdk.java.net/browse/JDK-8118199 .
Working with a canvas I attached mouse listener to continuously show a tooltip and update accordingly to the data drawn beneath it.
Tooltip tt = new Tooltip();
tt.setAnchorLocation(AnchorLocation.CONTENT_BOTTOM_RIGHT);
tt.setAutoFix(false);
double offset = 100;
this.setOnMouseMoved((event) -> {
//Position tooltip
if (!tt.isShowing()) {
tt.show(this, event.getScreenX() - offset, event.getScreenY() - offset);
} else {
tt.setX(event.getScreenX() - offset);
tt.setY(event.getScreenY() - offset);
}
//Update text
int xBucket = (int) ((event.getX() - marginLeft - gridXOffset) / (gridWidth / xSections));
int yBucket = (int) ((event.getY() - marginTop) / (gridHeight / ySections));
DoubleSummaryStatistics stat = dat[xBucket][yBucket];
tt.setText("Occurances: " + stat.getCount() + "\n"
+ "Average Fitness: " + df.format(stat.getAverage()) + "\n"
+ "Max Fitness: " + df.format(stat.getMax()) + "\n"
+ "Min Fitness: " + df.format(stat.getMin()));
});
this.setOnMouseExited((event) -> {
if (tt.isShowing()) {
tt.hide();
}
});
As you can see the tooltip is displayed a little bit to the top left due to the defined offset. If the value is set two a smaller value (20-0) the tooltip will grab the focus as soon as it is displayed and the setOnMouseExit handler will be immediately called resulting in a flickering loop.

itextpdf : PdfPTable dont takes height

I migrated my publisher core from itext-2.... to itextpdf-5.5.6
In itext-2 I had an image into cell of a PdfPTable an my table's celle had same size that image.
Now, in itextpdf-5.5.6 image have small size like that cell.
For example I use
table.setTotalWidth(450);
and in core itextpdf it calculate height too :
//ITEXTPDF
calculateWidths();
calculateHeights();
calculateHeight call to getRowHeight
getRowHeight(k, true);
and it does not do the same that in itext-2 :
itext returns 400
itextpdf returns 23
I debbuged for itextpdf and found that in pdfLine.getMaxSize(..) there is the following code :
if (chunk.isImage()) {
Image img = chunk.getImage();
if (chunk.changeLeading()) {
float height = chunk.getImageHeight() + chunk.getImageOffsetY() + img.getSpacingBefore();
image_leading = Math.max(height, image_leading);
}
}
and in the case of itext i have no condition like that :
if (chunk.changeLeading()){......}
Is there an average for solve it ?
I found where was problem :
Paragraph para = new Paragraph(new Chunk((Image) element, 0, 0, Boolean.FALSE));
the last parameter of chunk is changeLeading and it just had to change as Boolean.TRUE
Thanks everybody for your responses

Detect orientation using javascript on android devices

Using some code from this question I have set up some code to detect when an android device is rotated. It works great for the asus tablet (4.0.3) and two simulators (4.0.3 and 2.1), but for the kindle fire (2.3.4), and droidx (2.3.4) it switches the width and height.
Code:
<script type="text/javascript">
var supportsOrientationChange = "onorientationchange" in window,orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";
window.addEventListener(orientationEvent, function() {
alert("The rotation is " + window.orientation + " and the resolution is " + screen.width + " x " + screen.height);
modRule();
}, false);
</script>
Output from asus tablet
Holding it in what looks like landscape:
The rotation is 0 and the resolution is 1280 x 800
Portrait
The rotation is -90 and the resolution is 800 x 1280
Output from Kindle Fire
Landscape
The rotation is 90 and the resolution is 600 x 819
Portrait:
The rotation is 0 and the resolution is 1024 x 395
output from droidx
landscape:
The rotation is 90 and the resolution is 320x488
Portrait:
The rotation is 0 and the resolution is 569x239
Is there a way I can
a) Make the javascript detect if it should use height instead of width or width instead of height
OR
b) Make the devices report the correct values for their width and height?
After looking for a while longer I found out that this is a bug with the 2.2 and 2.3 OS. I fixed the bug with 2.3.4 by putting this code in my app.
browser = (WebView)findViewById(R.id.webBrowser);
browser.setBackgroundColor(Color.BLACK);
WebSettings webSettings = browser.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setUserAgentString("Android " + android.os.Build.VERSION.SDK);//this is so the JavaScript knows what version of the OS I'm using
And then for detecting if I'm in landscape mode:
var uagent = navigator.userAgent.toLowerCase();
function isLandscape()
{
var width = screen.width;
var height = screen.height;
if (isBugged())
{
var temp = width;
width = height;
height = temp;
}
var landscape = width > height;
return landscape;
}
function isBugged()
{
return uagent == "android 10"
}
And if that wasn't confusing enough, when the body initially loads, it's right about if it's in landscape mode or not. So I had to bypass my own workaround.
<body onload="if(isBugged()){uagent = 'bypass';}/*code that depends on isLandscape()*/;uagent = navigator.userAgent.toLowerCase();">
It's a real pain, a lot more work than it should be. Especially since it works in 2.1 but not 2.3.4. Really frustrating, but that's what I have. At the moment, I only check for sdk 10, I'm going to add checking for the other bugged versions soon.

Design generic process using template pattern

I have a routine that I repeatedly doing for many projects and I want to generalized it. I used iText for PDF manipulation.
Let say that I have 2000 PDFs inside a folder, and I need to zip these together. Let say the limit is 1000 PDFs per zip. So the name of the zip would follow this rule: job name + job sequence. For example, the zip name of the first 1000 PDF would be XNKXMN + AA and the second zip name would be XNKXMN + AB. Before zipping these PDFs, I need to add some text to each PDF. Text look something like this job name + job sequence + pdf sequence. So the first PDF inside the first zip will have this text XNKXMN + AA + 000001, and the one after that is XNKXMN + AA + 000002. Here is my attempt
First I have abstract clas GenericText that represent my text.
public abstract class GenericText {
private float x;
private float y;
private float rotation;
/**
* Since the text that the user want to insert onto the Pdf might vary
* from page to page, or from logical document to logical document, we allow
* the user to write their own implementation of the text. To give the user enough
* flexibility, we give them the reference to the physical page index, the logical page index.
* #param physcialPage The actual page number that the user current looking at
* #param logicalPage A Pdf might contain multiples sub-documents, <code>logicalPage</code>
* tell the user which logical sub-document the system currently looking at
*/
public abstract String generateText(int physicalPage, int logicalPage);
GenericText(float x, float y, float rotation){
this.x = x;
...
}
}
JobGenerator.java: my generic API to do what I describe above
public String generatePrintJob(List<File> pdfList, String outputPath,
String printName, String seq, List<GenericText> textList, int maxSize)
for (int currentPdfDocument = 0; currentPdfDocument < pdfList.size(); currentPdfDocument++) {
File pdf = pdfList.get(currentPdfDocument);
if (currentPdfDocument % maxSize != 0) {
if(textList != null && !textList.isEmpty()){
for(GenericText gt : textList){
String text = gt.generateText(currentPdfDocument, currentPdfDocument)
//Add the text content to the PDF using PdfReader and PdfWriter
}
}
...
}else{
//Close the current output stream and zip output stream
seq = Utils.getNextSeq(seq);
jobPath = outputPath + File.separator + printName + File.separator + seq + ".zip"
//Open new zip output stream with the new <code>jobPath</code>
}
}
}
So now in my main class I would just do this
final String printName = printNameLookup.get(baseOutputName);
String jobSeq = config.getPrintJobSeq();
final String seq = jobSeq;
GenericText keyline = new GenericText(90, 640, 0){
#Override
public String generateText(int physicalPage, int logicalPage) {
//if logicalPage = 1, Utils.right(String.valueOf(logicalPage), 6, '0') -> 000001
return printName + seq + " " + Utils.right(String.valueOf(logicalPage), 6, '0');
}
};
textList.add(keyline);
JobGenerator pjg = new JobGenerator();
pjg.generatePrintJob(...,..., printName, jobSeq, textList, 1000);
The problem that I am having with this design is that, even though I process archive the PDF into two zip correctly, the text is not correctly reflect. The print and the sequence does not change accordingly, it stay XNKXMN + AA for 2000 PDF instead of XNKXMN + AA for the first 1000 and change to XNKXMN + AB for the later 1000. There seems to be flawed in my design, please help
EDIT:
After looking at toto2 code, I see my problem. I create GenericText with the hope of adding text anywhere on the pdf page without affecting the basic logic of the process. However, the job sequence is by definition depending on the logic,as it need to increment if there are too many PDFs for one ZIP to handle (> maxSize). I need to rethink this.
When you create an anonymous GenerateText, the final seq which you use in the overridden generateText method is truly final and will always remain the value given at creation time. The update you carry on seq inside the else in generatePrintJob does nothing.
On a more general note, your code looks very complex and you should probably take a step back and do some major refactoring.
EDIT:
I would instead try something different, with no template method pattern:
int numberOfZipFiles =
(int) Math.ceil((double) pdfList.size() / maxSize);
for (int iZip = 0; iZip < numberOfZipFiles; iZip++) {
String batchSubName = generateBatchSubName(iZip); // gives AA, AB,...
for (int iFile = 0; iFile < maxSize; iFile++) {
int fileNumber = iZip * maxSize + iFile;
if (fileNumber >= pdfList.size()) // can happen for last batch
return;
String text = jobName + batchSubName + iFile;
... add "text" to pdfList.get(fileNumber)
}
}
However, you might also want to maintain the template pattern. In that case, I would keep the for-loops I wrote above, but I would change the generating method to genericText.generateText(iZip, iFile) where iZip = 0 gives AA and iZip = 1 gives AB, etc:
for (int iZip = 0; iZip < numberOfZipFiles; iZip++) {
for (int iFile = 0; iFile < maxSize; iFile++) {
int fileNumber = iZip * maxSize + iFile;
if (fileNumber >= pdfList.size()) // can happen for last batch
return;
String text = genericText.generateText(iZip, iFile);
... add "text" to pdfList.get(fileNumber)
}
}
It would be possible also to have genericText.generateText(fileNumber) which could itself decompose the fileNumber in AA000001, etc. But that would be somewhat dangerous because maxSize would be used in two different places and it might be bug prone to have duplicate data like that.

Categories

Resources