Command a2ps and Cups - Chineses Characters - linux

Good day.
I have a problem to print files with Chinese characters directly of linux.
We use CUPS to manage your printers on linux and send the print command by a2ps.
Our files are in the encode/unicode (UTF-8 and ISO-8859), but the physical printing is not seeing the Chinese characters
example:
¸£ÌØÆû³µ½ðÈÚ£¨Öйú£©ÓÐÏÞ¹«Ë¾/
Has anyone been through this and know how I can change the unicode of the a2ps command or cups to be able to convert the files?

As a solution, I adopted perform a conversion to pdf with the correct encode and send the converted PDF to CUPS via PrintJob.java file.
public class PDFPrintService {
/**
* Printer Job.
*/
private PrinterJob printerJob = null;
/**
* File to printer.
*/
private InputStream file;
/**
* Class that represents the file to be printed.
*/
private PDFFilePrint pdfFilePrint;
/**
* File converted to PDF for printed.
*/
private PDFFile pdfFile;
/**
* Temporary directory used in the conversion to postscript used in prints.
*/
private String temporaryDirectoryPostscriptFiles;
/**
* Default Temporary Directory of Files.
*/
private String defaultTemporaryDirectoryFiles;
/**
* java.io.tmpdir
*/
private static final String JAVA_IO_TEMPDIR = "java.io.tmpdir";
/**
* Constructs the print job based on the PDFFilePrint class.
*
* #param inputStream
* #param jobName
* #throws IOException
* #throws PrinterException
*/
public PDFPrintService(PDFFilePrint pdfFilePrint) throws IOException, PrinterException {
this.pdfFilePrint = pdfFilePrint;
loadFile(pdfFilePrint.getFileName());
byte[] pdfContent = new byte[this.file.available()];
this.file.read(pdfContent, 0, this.file.available());
initialize(pdfContent, this.pdfFilePrint.getJobName());
}
/**
* Method responsible to load the file for print.
*
* #param fileName
* #throws FileNotFoundException
*/
private void loadFile(final String fileName) throws FileNotFoundException{
try {
this.file = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new FileNotFoundException("The File : " + fileName);
}
}
/**
* Initializes the job
*
* #param pdfContent
* #param jobName
* #throws IOException
* #throws PrinterException
*/
private void initialize(byte[] pdfContent, String jobName)
throws IOException, PrinterException {
ByteBuffer bb = ByteBuffer.wrap(pdfContent);
this.pdfFile = new PDFFile(bb);
PDFPrintPage pages = new PDFPrintPage(pdfFile);
this.printerJob = PrinterJob.getPrinterJob();
loadPrinterDestination();
PageFormat pageFormat = PrinterJob.getPrinterJob().defaultPage();
Book book = new Book();
book.append(pages, pageFormat, pdfFile.getNumPages());
printerJob.setPageable(book);
printerJob.setJobName(jobName);
Paper paper = new Paper();
paper.setImageableArea(0, 0, paper.getWidth(), paper.getHeight());
pageFormat.setPaper(paper);
}
/**
* Method responsible to get the printer.
*
* #throws PrinterException
*/
private void loadPrinterDestination() throws PrinterException {
String printerName = new String();
try {
PrintService[] services = PrinterJob.lookupPrintServices();
for (PrintService printService : services) {
printerName = printService.getName();
if (printerName.equalsIgnoreCase(this.pdfFilePrint.getPrinterName())) {
printerJob.setPrintService(printService);
break;
}
}
} catch (PrinterException e) {
e.printStackTrace();
throw new PrinterException("Printer not found : printerName " + printerName);
}
}
/**
* Method responsible to printer.
*
* #throws PrinterException
*/
public void print() throws PrinterException {
try {
loadNewTemporaryDirectoryPostscriptFiles();
this.printerJob.print(getPrinterPageSettings());
} finally {
loadDefaultTemporaryDirectoryPostscriptFiles();
closeFile();
}
}
/**
* Method responsible to load a new area for a temporary converted files in
* server.
*/
private void loadNewTemporaryDirectoryPostscriptFiles() {
this.defaultTemporaryDirectoryFiles = System.getProperty(JAVA_IO_TEMPDIR, null);
if(!temporaryDirectoryPostscriptFiles.trim().isEmpty()){
System.setProperty(JAVA_IO_TEMPDIR, temporaryDirectoryPostscriptFiles);
}
}
/**
* /**
* Method responsible to load a default temporary area of files.
*/
private void loadDefaultTemporaryDirectoryPostscriptFiles() {
String currentDirectoryUsed = System.getProperty(JAVA_IO_TEMPDIR, null);
if(!currentDirectoryUsed.equalsIgnoreCase(defaultTemporaryDirectoryFiles)){
System.setProperty(JAVA_IO_TEMPDIR, defaultTemporaryDirectoryFiles);
}
}
/**
* Method responsible to load settings of printer.
*
* #return PrintRequestAttributeSet
*/
private PrintRequestAttributeSet getPrinterPageSettings() {
PrintRequestAttributeSet printRequestAttribute = new HashPrintRequestAttributeSet();
loadPageRange(printRequestAttribute);
loadSide(printRequestAttribute);
loadOrientationPortrait(printRequestAttribute);
printRequestAttribute.add(NORMAL);
return printRequestAttribute;
}
/**
* Method responsible to close the file after the printer.
*/
private void closeFile() {
try {
this.file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Method responsible to load the orientation Portrait.
*
* #param printRequestAttribute
*/
private void loadOrientationPortrait(PrintRequestAttributeSet printRequestAttribute) {
printRequestAttribute.add(PORTRAIT);
}
/**
* Method responsible to load the Side of printer(ONE_SIDED or DUPLEX).
*
* #param printRequestAttribute
*/
private void loadSide(PrintRequestAttributeSet printRequestAttribute) {
if (!this.pdfFilePrint.isDuplexSidet()) {
printRequestAttribute.add(ONE_SIDED);
} else {
printRequestAttribute.add(DUPLEX);
}
}
/**
* Method responsible to load the page range of print.
*
* #param printRequestAttribute
*/
private void loadPageRange(PrintRequestAttributeSet printRequestAttribute) {
int lowerBound = pdfFilePrint.getLowerBound();
int upperBound = pdfFilePrint.getUpperBound();
if ((lowerBound < 1) && (upperBound < 1)) {
lowerBound = 1;
upperBound = pdfFile.getNumPages();
} else {
if ((lowerBound < 1) && (upperBound > 0)) {
lowerBound = 1;
} else {
if ((lowerBound > 0) && (upperBound < 1)) {
upperBound = pdfFile.getNumPages();
}
}
}
if (upperBound < lowerBound) {
upperBound = lowerBound;
}
if (lowerBound > pdfFile.getNumPages()) {
lowerBound = pdfFile.getNumPages();
}
if (upperBound > pdfFile.getNumPages()) {
upperBound = pdfFile.getNumPages();
}
PageRanges pageRanges = new PageRanges(lowerBound, upperBound);
printRequestAttribute.add(pageRanges);
}
/**
* Set temporaryDirectoryPostscriptFiles.
*
* #param temporaryDirectoryPostscriptFiles
*/
public void setTemporaryDirectoryPostscriptFiles(
String temporaryDirectoryPostscriptFiles) {
this.temporaryDirectoryPostscriptFiles = temporaryDirectoryPostscriptFiles;
}
}

Related

Call to a member function format() on string symfony 3.4

I'm trying to register a new appointment in my database, after sending an email, but it shows me an error: Call to a member function format() on string,
in vendor\doctrine\dbal\lib\Doctrine\DBAL\Types\DateTimeType.php
,
because in the booking entity, there is the date and time I need to register which are datetime types.
Here is the booking entity :
<?php
namespace Doctix\FrontBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Booking
*
* #ORM\Table(name="booking")
*
class Booking
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
*
*#ORM\Column(name="date_rdv", type="datetime", nullable=true)
*/
private $dateRdv;
/**
* #var \DateTime
*
*#ORM\Column(name="heure_rdv", type="datetime", nullable=true)
*/
private $heureRdv;
/**
* #var bool
*
*#ORM\Column(name="valider_rdv", type="boolean", nullable=true)
*/
private $validerRdv;
/**
* #ORM\ManyToOne(targetEntity="Doctix\MedecinBundle\Entity\Medecin")
* #ORM\JoinColumn(nullable=true)
*/
private $medecin;
/**
* #ORM\ManyToOne(targetEntity="Doctix\PatientBundle\Entity\Patient")
* #ORM\JoinColumn(nullable=true)
*/
private $patient;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set dateRdv
*
* #param \DateTime $dateRdv
*
* #return Booking
*/
public function setDateRdv($dateRdv)
{
$this->dateRdv = $dateRdv;
return $this;
}
/**
* Get dateRdv
*
* #return \DateTime
*/
public function getDateRdv()
{
return $this->dateRdv;
}
/**
* Set heureRdv
*
* #param \DateTime $heureRdv
*
* #return Booking
*/
public function setHeureRdv($heureRdv)
{
$this->heureRdv = $heureRdv;
return $this;
}
/**
* Get heureRdv
*
* #return \DateTime
*/
public function getHeureRdv()
{
return $this->heureRdv;
}
/**
* Set validerRdv
*
* #param boolean $validerRdv
*
* #return Booking
*/
public function setValiderRdv($validerRdv)
{
$this->validerRdv = $validerRdv;
return $this;
}
/**
* Get validerRdv
*
* #return bool
*/
public function getValiderRdv()
{
return $this->validerRdv;
}
/**
* Set medecin
*
* #param \Doctix\MedecinBundle\Entity\Medecin $medecin
* #return Booking
*/
public function setMedecin(\Doctix\MedecinBundle\Entity\Medecin $medecin)
{
$this->medecin = $medecin;
return $this;
}
/**
* Get medecin
*
* #return \Doctix\MedecinBundle\Entity\Medecin
*/
public function getMedecin()
{
return $this->medecin;
}
/**
* Set patient
*
* #param \Doctix\PatientBundle\Entity\Patient $patient
* #return Booking
*/
public function setPatient(\Doctix\PatientBundle\Entity\Patient $patient)
{
$this->patient = $patient;
return $this;
}
/**
* Get patient
*
* #return \Doctix\PatientBundle\Entity\Patient
*/
public function getPatient()
{
return $this->patient;
}
}
Here is the controller:
public function patientHandleBookingAction(Request $request){
$id = $request->query->get('id');
$date = $request->query->get('date');
$time = $request->query->get('time');
// $user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$repoPatient = $em->getRepository('DoctixPatientBundle:Patient');
$patient = $repoPatient->findOneBy(array(
'user' => $this->getUser()
));
$repoMedecin = $em->getRepository('DoctixMedecinBundle:Medecin');
$medecin = $repoMedecin->findOneBy(array(
'id' => $request->query->get("idMedecin")));
$mailer = $this->get('mailer');
$message = (new \Swift_Message('Email de Confirmaton'))
->setFrom("medmamtest#gmail.com")
->setTo($patient->getUser()->getUsername())
->setBody(
$this->renderView(
// app/Resources/views/Emails/registration.html.twig
'Emails/registration.html.twig',
array('name' => 'mam')
),
'text/html'
);
$mailer->send($message);
if($mailer){
$booking = new Booking();
$booking->setMedecin($medecin);
$booking->setPatient($patient);
$booking->setDateRdv('date');
$booking->setHeureRdv('time');
$booking->setValiderRdv(0);
}
$em->persist($booking);
$em->flush();
// A remplacer par un contenu plus approprié
return $this->render('DoctixPatientBundle:Patient:confirm.html.twig',array(
'time' => $request->query->get("time"),
'date' => $request->query->get("date"),
'medecin' => $medecin,
'patient' => $patient,
// 'date' => $date,
// 'time' => $time
));
}
Thanks
This error is happening because you are trying to set the date and time as strings on your booking entity.
$booking->setDateRdv('date');
$booking->setHeureRdv('time');
Try to change it to:
$booking->setDateRdv(new \DateTime($date));
$booking->setHeureRdv(new \DateTime($time));

XPages Make Dynamic .property Resources File on the Fly using JAVA with UTF-8 output

This post is a carryover from a previous Using .properties Resource File ResourceBundle in an XPage. All Kudos goes to Sean Cullm, Matt White,
Julian Robichaus in this post Creating an Xpage resource file via DXL without a temporary file using LotusScript.
I ran into the error: **Base64 byte stream contains invalid data or is too large to store in a single note item** with some of the key:value pairs being realllly big. To get around the problem of having strings chopped or the error above thrown, I shifted over a JAVA solution to solve what seems to be a LotusScript problem.
Java Solution:
JavaAgent extends AgentBase:
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Vector;
import lotus.domino.AgentBase;
import lotus.domino.AgentContext;
import lotus.domino.Database;
import lotus.domino.DateTime;
import lotus.domino.DxlImporter;
import lotus.domino.Log;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.Stream;
import lotus.domino.View;
import lotus.domino.ViewEntry;
import lotus.domino.ViewEntryCollection;
public class JavaAgent extends AgentBase {
public Database db;
public View view;
static DxlImporter importer = null;
Log log;
DateTime dt;
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// Document contextDoc = agentContext.getDocumentContext();
log = session.createLog("Agent Log");
log.openAgentLog();
this.db = agentContext.getCurrentDatabase();
this.view = db.getView("dojoprivotdatadocs");
importer = session.createDxlImporter();
importer.setReplaceDbProperties(true);
importer.setReplicaRequiredForReplaceOrUpdate(false);
importer.setAclImportOption(DxlImporter.DXLIMPORTOPTION_IGNORE);
importer
.setDesignImportOption(DxlImporter.DXLIMPORTOPTION_REPLACE_ELSE_CREATE);
importer
.setDocumentImportOption(DxlImporter.DXLIMPORTOPTION_IGNORE);
// importer.importDxl(generateDXL("", "", db.getReplicaID()), db);
importer.importDxl(generateDXL("", "", ""), db);
view.setAutoUpdate(true);
view.recycle();
db.recycle();
} catch (Exception e) {
e.printStackTrace();
System.out.println("end__" + e.getMessage());
} finally {
try {
System.out.println(importer.getLog());
} catch (Exception e) {
e.printStackTrace();
System.out.println("final: " + e.getMessage());
}
}
}
public Stream generateDXL(String data, final String libName,
final String dbReplicaId) throws NotesException {
Session session = getSession();
Stream dxlStream = session.createStream();
//NOTE: I left the raw DXL generated by an NotesNoteCollection export
//the import DXL is not verbose like the exported DXL, the DXL exported is commented out
try {
this.view.refresh();
this.view.setAutoUpdate(false);
dxlStream.writeText("<?xml version='1.0' encoding='utf-8'?>");
dxlStream
.writeText("<!DOCTYPE database SYSTEM 'xmlschemas/domino_9_0_1.dtd'>");
/**
* dxl .append("<database xmlns='http://www.lotus.com/dxl' version='9.0' maintenanceversion='1.0' replicaid='"
* + dbReplicaId +"' path='CN=dom001/OU=SERVER/O=PC!!SSH\\ESA\\PolarColFileData.nsf' title='Polar Col File Data'>"
* );
**/
dxlStream
.writeText("<database xmlns='http://www.lotus.com/dxl' replicaid='882580D6006A6F64'>");
/**
* dxl .append("<fileresource name='base64.properties' noreplace='false' publicaccess='false' designerversion='9.0.1'>"
* );
**/
dxlStream
.writeText("<fileresource name='dojoPivotData.properties' noreplace='false' publicaccess='false' charset='ISO-8859-1'>");
// dxlStream
// .writeText("<created><datetime dst='true'>20171214T101814,59-07</datetime></created>");
dxlStream.writeText("<filedata>");
// Base64 base64 = new Base64();
dxlStream.writeText(Base64.encode(getViewEntires().readText()));
dxlStream.writeText("</filedata></fileresource></database>");
} catch (NotesException ne) {
ne.printStackTrace();
System.out.println("generateDXL:: " + ne.getMessage());
} catch (Exception e) {
e.printStackTrace();
System.out.println("generateDXL:: " + e.getMessage());
}
return dxlStream;
}
public Stream getViewEntires() throws NotesException {
Stream base64Stream = getSession().createStream();
String eString = "";
try {
ViewEntryCollection vec = this.view.getAllEntries();
ViewEntry tmpentry;
ViewEntry entry = vec.getFirstEntry();
while (entry != null) {
Vector colvals = entry.getColumnValues();
base64Stream
.writeText(colvals.get(0).toString(), Stream.EOL_CR);
tmpentry = vec.getNextEntry();
entry.recycle();
entry = tmpentry;
}
dt = getSession().createDateTime("Today");
dt.setNow();
base64Stream.writeText("#generated=" + dt.getDateOnly() + " "
+ dt.getTimeOnly() + " TZ:" + dt.getTimeZone(),
Stream.EOL_CR);
dt.recycle();
base64Stream.setPosition(0);
} catch (NotesException ne) {
ne.printStackTrace();
System.out.println("getViewEntires:: " + eString + ": "
+ ne.getMessage());
} catch (Exception e) {
e.printStackTrace();
System.out.println("getViewEntires:: " + eString + ": "
+ e.getMessage());
}
return base64Stream;
}
/**
* converts a integer to a byte array in little endian order
*
* #param i
* integer to convert
* #return byte array
*/
static byte[] toBytes(final int i) {
ByteBuffer b = ByteBuffer.allocate(4);
b.order(ByteOrder.LITTLE_ENDIAN);
b.putInt(i);
return b.array();
}
}
Ascii.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* Ascii constants.
* <p>
* Some useful constants.
* </p>
*
* #ibm-not-published
*/
public interface Ascii {
public static final byte CASE_OFFSET = 32;
public static final byte A = 65;
public static final byte B = 66;
public static final byte C = 67;
public static final byte D = 68;
public static final byte E = 69;
public static final byte F = 70;
public static final byte G = 71;
public static final byte H = 72;
public static final byte I = 73;
public static final byte J = 74;
public static final byte K = 75;
public static final byte L = 76;
public static final byte M = 77;
public static final byte N = 78;
public static final byte O = 79;
public static final byte P = 80;
public static final byte Q = 81;
public static final byte R = 82;
public static final byte S = 83;
public static final byte T = 84;
public static final byte U = 85;
public static final byte V = 86;
public static final byte W = 87;
public static final byte X = 88;
public static final byte Y = 89;
public static final byte Z = 90;
public static final byte a = 97;
public static final byte b = 98;
public static final byte c = 99;
public static final byte d = 100;
public static final byte e = 101;
public static final byte f = 102;
public static final byte g = 103;
public static final byte h = 104;
public static final byte i = 105;
public static final byte j = 106;
public static final byte k = 107;
public static final byte l = 108;
public static final byte m = 109;
public static final byte n = 110;
public static final byte o = 111;
public static final byte p = 112;
public static final byte q = 113;
public static final byte r = 114;
public static final byte s = 115;
public static final byte t = 116;
public static final byte u = 117;
public static final byte v = 118;
public static final byte w = 119;
public static final byte x = 120;
public static final byte y = 121;
public static final byte z = 122;
public static final byte ZERO = 48;
public static final byte ONE = 49;
public static final byte TWO = 50;
public static final byte THREE = 51;
public static final byte FOUR = 52;
public static final byte FIVE = 53;
public static final byte SIX = 54;
public static final byte SEVEN = 55;
public static final byte EIGHT = 56;
public static final byte NINE = 57;
public static final byte TAB = 9;
public static final byte LF = 10;
public static final byte FF = 12;
public static final byte CR = 13;
public static final byte SPACE = 32;
public static final byte PERIOD = 46;
public static final byte SLASH = 47;
public static final byte BACK_SLASH = 92;
public static final byte COLON = 58;
public static final byte SEMICOLON = 59;
public static final byte EQUALS = 61;
public static final byte QUOTE = 34;
public static final byte LT = 60;
public static final byte GT = 62;
public static final byte OP = 40;
public static final byte CP = 41;
public static final byte AT = 64;
public static final byte UNDERSCORE = 95;
public static final byte STAR = 42;
public static final byte PERCENT = 37;
public static final byte HYPHEN = 45;
public static final byte PLUS = 43;
public static final byte OPEN_CURLY = 123;
public static final byte CLOSE_CURLY = 125;
public static final byte OPEN_ANGLE = 60;
public static final byte CLOSE_ANGLE = 62;
/** The CR/LF pair. */
public static final byte[] CRLF = { CR, LF };
}
Base64OutputStream.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* A Base64 content transfer encoding filter stream.
* <p>
* From RFC 2045, section 6.8:
* <p>
* The Base64 Content-Transfer-Encoding is designed to represent arbitrary
* sequences of octets in a form that need not be humanly readable. The encoding
* and decoding algorithms are simple, but the encoded data are consistently
* only about 33 percent larger than the unencoded data.
*
* #ibm-api
*/
public class Base64OutputStream extends FilterOutputStream {
private final byte[] _buffer;
private int _buflen;
private int _count;
private final int _lineLength;
/**
* Default constructor.
*
* #param out
* the underlying output stream to encode
* #pre out != null
* #post out != null
*/
public Base64OutputStream(OutputStream out) {
this(out, Integer.MAX_VALUE);
}
/**
* Constructor.
*
* #param out
* the underlying output stream to encode
* #param lineLength
* the line length
* #pre out != null
* #pre lineLength > 0
* #post out != null
*/
public Base64OutputStream(OutputStream out, int lineLength) {
super(out);
_buflen = 0;
_count = 0;
_buffer = new byte[3];
_lineLength = lineLength;
}
/**
* Writes the specified byte to this output stream.
*
* #param ch
* character to write/encode
* #throws IOException
* IO Exception occurred
* #pre out != null
* #post out != null
*/
public void write(int ch) throws IOException {
_buffer[_buflen++] = (byte) ch;
if (_buflen == 3) {
encode();
_buflen = 0;
}
}
/**
* Writes <code>b.length</code> bytes from the specified byte array to this
* output stream.
*
* #param b
* buffer to write/encode
* #throws IOException
* IO Exception occurred
* #pre out != null
* #post out != null
*/
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
/**
* Writes <code>len</code> bytes from the specified byte array starting at
* offset <code>off</code> to this output stream.
*
* #param b
* buffer to write/encode
* #param off
* offset to start of buffer to write/encode
* #param len
* number of bytes from buffer to write/encode
* #throws IOException
* IO Exception occurred
* #pre off < b.length
* #pre off+len < b.length
* #pre out != null
* #post out != null
*/
public void write(byte[] b, int off, int len) throws IOException {
for (int i = 0; i < len; i++) {
write(b[off + i]);
}
}
/**
* Flushes this output stream and forces any buffered output bytes to be
* written out.
*
* #throws IOException
* IO Exception occurred
* #pre out != null
* #post _buflen == 0
*/
public void flush() throws IOException {
if (_buflen > 0) {
encode();
_buflen = 0;
}
out.flush();
}
/**
* Closes this output stream and releases any system resources associated
* with this stream.
*
* #throws IOException
* IO Exception occurred
* #pre out != null
* #post $none
*/
public void close() throws IOException {
flush();
out.close();
}
/**
* Encode current buffer bytes
*
* #throws IOException
* IO Exception occurred
* #pre out != null
*/
private void encode() throws IOException {
if ((_count + 4) > _lineLength) {
out.write(Ascii.CR);
out.write(Ascii.LF);
_count = 0;
}
if (_buflen == 1) {
byte b = _buffer[0];
int i = 0;
out.write(IoConstants.B64_SRC_MAP[b >>> 2 & 0x3f]);
out
.write(IoConstants.B64_SRC_MAP[(b << 4 & 0x30)
+ (i >>> 4 & 0xf)]);
out.write(Ascii.EQUALS);
out.write(Ascii.EQUALS);
} else if (_buflen == 2) {
byte b1 = _buffer[0], b2 = _buffer[1];
int i = 0;
out.write(IoConstants.B64_SRC_MAP[b1 >>> 2 & 0x3f]);
out.write(IoConstants.B64_SRC_MAP[(b1 << 4 & 0x30)
+ (b2 >>> 4 & 0xf)]);
out.write(IoConstants.B64_SRC_MAP[(b2 << 2 & 0x3c)
+ (i >>> 6 & 0x3)]);
out.write(Ascii.EQUALS);
} else {
byte b1 = _buffer[0], b2 = _buffer[1], b3 = _buffer[2];
out.write(IoConstants.B64_SRC_MAP[b1 >>> 2 & 0x3f]);
out.write(IoConstants.B64_SRC_MAP[(b1 << 4 & 0x30)
+ (b2 >>> 4 & 0xf)]);
out.write(IoConstants.B64_SRC_MAP[(b2 << 2 & 0x3c)
+ (b3 >>> 6 & 0x3)]);
out.write(IoConstants.B64_SRC_MAP[b3 & 0x3f]);
}
_count += 4;
}
}
Base64.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import java.io.IOException;
/**
* Encodes and decodes to and from Base64 notation.
*
* #ibm-api
*/
public class Base64 {
/**
* Decode a base64 string to an ascii string.
*
* #param base64str
* the string to decode
* #return
* #ibm-api
*/
public static String decode(String base64str) {
try {
StringInputStream bais = new StringInputStream(base64str);
Base64.InputStream b64 = new Base64.InputStream(bais);
StringBuffer buf = new StringBuffer();
int byt;
while ((byt = b64.read()) >= 0) {
buf.append((char) byt);
}
return buf.toString();
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
}
/**
* Encode a string to base64.
*
* #param str
* the string to encode
* #return
* #ibm-api
*/
public static String encode(String str) {
try {
StringBuidlerOutputStream baos = new StringBuidlerOutputStream(str
.length() * 3 / 2);
Base64.OutputStream b64 = new Base64.OutputStream(baos);
int len = str.length();
for (int i = 0; i < len; i++) {
int c = (str.charAt(i)) & 0x00FF;
b64.write(c);
}
b64.flushBuffer();
return baos.builder.toString();
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
}
public static class StringInputStream extends java.io.InputStream {
private final String str;
private int ptr;
public StringInputStream(String str) {
this.str = str;
}
public int read() throws IOException {
if (ptr < str.length()) {
return str.charAt(ptr++);
}
return -1;
}
}
public static class StringBufferOutputStream extends java.io.OutputStream {
private final StringBuffer buffer;
public StringBufferOutputStream(int size) {
this.buffer = new StringBuffer(size);
}
public StringBuffer getStringBuffer() {
return buffer;
}
public void write(int b) throws IOException {
buffer.append((char) b);
}
}
public static class StringBuidlerOutputStream extends java.io.OutputStream {
private final StringBuilder builder;
public StringBuidlerOutputStream(int size) {
this.builder = new StringBuilder(size);
}
public StringBuilder getStringBuilder() {
return builder;
}
public void write(int b) throws IOException {
builder.append((char) b);
}
}
public static class OutputStream extends Base64OutputStream {
public OutputStream(java.io.OutputStream out) {
super(out);
}
public void flushBuffer() throws IOException {
flush();
}
}
public static class InputStream extends Base64InputStream {
public InputStream(java.io.InputStream in) {
super(in);
}
}
}
Base64InputStream.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* A Base64 content transfer encoding filter stream.
* <p>
* From RFC 2045, section 6.8:
* <p>
* The Base64 Content-Transfer-Encoding is designed to represent arbitrary
* sequences of octets in a form that need not be humanly readable. The encoding
* and decoding algorithms are simple, but the encoded data are consistently
* only about 33 percent larger than the unencoded data.
*
* #ibm-api
*/
public class Base64InputStream extends FilterInputStream {
private final byte[] _buffer;
private int _buflen;
private int _index;
private final byte[] _decodeBuf;
/**
* Constructs an input stream that decodes an underlying Base64-encoded
* stream.
*
* #param in
* the Base64-encoded stream
* #ibm-api
*/
public Base64InputStream(InputStream in) {
super(in);
_buflen = 0;
_index = 0;
_decodeBuf = new byte[4];
_buffer = new byte[3];
}
/**
* Reads the next byte of data from the input stream.
*
* #throws IOException
* IO Exception occurred
* #return next byte in data stream
*/
public int read() throws IOException {
if (_index >= _buflen) {
decode();
if (_buflen == 0) {
return -1;
}
_index = 0;
}
return _buffer[_index++] & 0xFF;
}
/**
* Reads up to len bytes of data from the input stream into an array of
* bytes.
*
* #param b
* buffer to put data
* #param off
* offset to start of buffer
* #param len
* number of bytes from buffer
* #throws IOException
* IO Exception occurred
* #return number of bytes read
*/
public int read(byte[] b, int off, int len) throws IOException {
try {
int l = 0;
for (; l < len; l++) {
int ch = read();
if (ch == -1) {
if (l == 0) {
return -1;
} else {
break;
}
}
b[off + l] = (byte) ch;
}
return l;
} catch (IOException ioe) {
return -1;
}
}
/**
* Returns the number of bytes that can be read (or skipped over) from this
* input stream without blocking by the next caller of a method for this
* input stream.
*
* #throws IOException
* IO Exception occurred
* #return number of bytes that can be read
*/
public int available() throws IOException {
return (in.available() * 3) / 4 + (_buflen - _index);
}
/**
* Decode Base64 encoded buffer
*
* #throws IOException
* IO Exception occurred
*/
private void decode() throws IOException {
_buflen = 0;
// Loop until we hit EOF or non-line-termination char
int ch = Ascii.LF;
while (ch == Ascii.LF || ch == Ascii.CR) {
ch = in.read();
if (ch == -1) {
return;
}
}
_decodeBuf[0] = (byte) ch;
int j = 3, l;
for (int k = 1; (l = in.read(_decodeBuf, k, j)) != j; k += l) {
if (l == -1) {
throw new IOException("Base64 encoding error"); // $NLS-Base64InputStream.Base64encodingerror-1$
}
j -= l;
}
byte b0 = IoConstants.B64_DST_MAP[_decodeBuf[0] & 0xFF];
byte b2 = IoConstants.B64_DST_MAP[_decodeBuf[1] & 0xFF];
_buffer[_buflen++] = (byte) (b0 << 2 & 0xfc | b2 >>> 4 & 0x3);
if (_decodeBuf[2] != Ascii.EQUALS) {
b0 = b2;
b2 = IoConstants.B64_DST_MAP[_decodeBuf[2] & 0xFF];
_buffer[_buflen++] = (byte) (b0 << 4 & 0xf0 | b2 >>> 2 & 0xf);
if (_decodeBuf[3] != Ascii.EQUALS) {
byte b1 = b2;
b2 = IoConstants.B64_DST_MAP[_decodeBuf[3] & 0xFF];
_buffer[_buflen++] = (byte) (b1 << 6 & 0xc0 | b2 & 0x3f);
}
}
}
}
IoConstants.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* Useful constants for base64 package.
*
* #ibm-not-published
*/
public class IoConstants {
/**
* RFC822 requires that header lines are limited to 998 octets (excluding
* CRLF)
*/
public static final int MAX_RFC822_LINE_LENGTH = 998;
/**
* RFC 2822 requires that body content lines can never be more than 998
* octets (excluding CRLF)
*/
public static final int MAX_RFC2822_LINE_LENGTH = 998;
/**
* Map used for Base64 encoding
*/
public static final char[] B64_SRC_MAP = { 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', '+', '/' };
/**
* Map used for Base64 decoding
*/
public static final byte[] B64_DST_MAP = new byte[256];
/**
* Char array used in decimal to hexidecimal conversion.
*/
public static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/** Construct mapping from source to destination maps */
static {
for (int i = 0; i < B64_DST_MAP.length; i++) {
B64_DST_MAP[i] = -1;
}
for (int i = 0; i < B64_SRC_MAP.length; i++) {
B64_DST_MAP[B64_SRC_MAP[i]] = (byte) i;
}
}
}

Symfony2 - Using controller security for user and category

I am trying to restrict user access from accessing the CRUD access in the controller.
I have a bi-directional OneToOne relationship with User and Category. It's setup to only allow 1 user to be able to access 1 blog.
I am testing this by logging in as another user that is not related to this category. And upon clicking on new, the form loads by-passing any security I have setup.
Speculating that the problem is with the $title parameter being passed in, (trying to pass this in as the route variable) as I don't think I'm setting this up correctly.
Can someone guide me on what I'm doing wrong?
Controller code
/**
* Post controller.
*
* #Route("/category")
*/
/**
* Creates a new Post entity.
*
* #Route("/", name="category_create")
* #Method("POST")
* #Template("AcmeDemoBundle:Page:new.html.twig")
*/
public function createAction(Request $request, $title)
{
// User security
$em = $this->getDoctrine()->getManager();
$categoryRepository = $em->getRepository('AcmeDemoBundle:Category');
$category = $categoryRepository->findOneBy(array(
'title' => '$title',
));
$owner = $category->getUser();
$currentUser = $this->get('security.context')->getToken()->getUser();
if ($owner != $currentUser) {
throw new AccessDeniedException('You do not have access for this');
}
// Form creation
$post = new Post();
$form = $this->createCreateForm($post);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($post);
$em->flush();
return $this->redirect($this->generateUrl('category_show', array('id' => $post->getId())));
}
return array(
'post' => $post,
'form' => $form->createView(),
);
}
Category entity
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #Gedmo\Slug(fields={"title"}, unique=false)
* #ORM\Column(length=255)
*/
private $catslug;
/**
* #ORM\OneToMany(targetEntity="Post", mappedBy="category")
*/
protected $posts;
/**
* #ORM\OneToOne(targetEntity="Acme\DemoBundle\Entity\User", inversedBy="cat")
* #ORM\JoinColumn(name="cat_id", referencedColumnName="id")
*/
protected $user;
User entity
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=255)
* #Assert\NotBlank(message="Field cannot be blank")
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank()
*/
private $email;
/**
* #ORM\Column(type="json_array")
*/
private $roles = array();
/**
* #var bool
*
* #ORM\Column(type="boolean")
*/
private $isActive = true;
/**
* #Assert\NotBlank
* #Assert\Regex(
* pattern="/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).*$/",
* message="Use 1 upper case letter, 1 lower case letter, and 1 number")
*/
private $plainPassword;
/**
* #ORM\OneToOne(targetEntity="Acme\DemoBundle\Entity\Category", mappedBy="user")
*/
private $cat;
You can try to create own Security Voter to check if user has a permission to this action. Sample code:
class CategoryVoter implements VoterInterface
{
const CREATE = 'create';
/**
* #param string $attribute
* #return bool
*/
public function supportsAttribute($attribute)
{
return in_array($attribute, [
self::CREATE
]);
}
/**
* #param string $class
* #return bool
*/
public function supportsClass($class)
{
$supportedClass = 'Acme\DemoBundle\Entity\Category';
return $supportedClass === $class || is_subclass_of($class, $supportedClass);
}
/**
* #param TokenInterface $token
* #param object $blog
* #param array $attributes
* #return int
*/
public function vote(TokenInterface $token, Category $category, array $attributes)
{
....
$attribute = $attributes[0];
$user = $token->getUser();
switch($attribute) {
case 'create':
if ($user->getId() === $category->getUser()->getId()) {
return VoterInterface::ACCESS_GRANTED;
}
break;
....
}
...
}
}
create action:
public function createAction(Request $request, $title)
{
$em = $this->getDoctrine()->getManager();
$categoryRepository = $em->getRepository('AcmeDemoBundle:Category');
$category = $categoryRepository->findOneBy([
'title' => '$title',
]);
...
if (false === $this->get('security.context')->isGranted('create', $category)) {
throw new AccessDeniedException('Unauthorised access!');
}
...
}

JavaFX 2.x : Logarithmic scale on Y axis

As from this very good post here
Logarithmic scale in Java FX 2
I have changed this class to get log scale on Y axis, and it works fine. The only problem I have is that there are very few horizontal grid lines and scale always start ranges from 0 or near zero.
Here is what I get
I would like to have tick values grid also in the min and max range of my data serie, in this case min = 19,35 max = 20,35; as of now all 10 horizontal grid lines are all plotted outside this range.
How to accomplish this?
Thanks all, here is my log code for Y axis
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.chart.ValueAxis;
//http://blog.dooapp.com/logarithmic-scale-strikes-back-in-javafx-20
public class LogarithmicAxis extends ValueAxis<Number> {
//Create our LogarithmicAxis class that extends ValueAxis<Number> and define two properties that will represent the log lower and upper bounds of our axis.
private final DoubleProperty logUpperBound = new SimpleDoubleProperty();
private final DoubleProperty logLowerBound = new SimpleDoubleProperty();
//
//we bind our properties with the default bounds of the value axis. But before, we should verify the given range according to the mathematic logarithmic interval definition.
public LogarithmicAxis() {
super(1, 100);
bindLogBoundsToDefaultBounds();
}
public LogarithmicAxis(double lowerBound, double upperBound) {
super(lowerBound, upperBound);
try {
validateBounds(lowerBound, upperBound);
bindLogBoundsToDefaultBounds();
} catch (IllegalLogarithmicRangeException e) {
}
}
/**
* Bind our logarithmic bounds with the super class bounds, consider the base 10 logarithmic scale.
*/
private void bindLogBoundsToDefaultBounds() {
logLowerBound.bind(new DoubleBinding() {
{
super.bind(lowerBoundProperty());
}
#Override
protected double computeValue() {
return Math.log10(lowerBoundProperty().get());
}
});
logUpperBound.bind(new DoubleBinding() {
{
super.bind(upperBoundProperty());
}
#Override
protected double computeValue() {
return Math.log10(upperBoundProperty().get());
}
});
}
/**
* Validate the bounds by throwing an exception if the values are not conform to the mathematics log interval:
* ]0,Double.MAX_VALUE]
*
* #param lowerBound
* #param upperBound
* #throws IllegalLogarithmicRangeException
*/
private void validateBounds(double lowerBound, double upperBound) throws IllegalLogarithmicRangeException {
if (lowerBound < 0 || upperBound < 0 || lowerBound > upperBound) {
throw new IllegalLogarithmicRangeException(
"The logarithmic range should be include to ]0,Double.MAX_VALUE] and the lowerBound should be less than the upperBound");
}
}
//Now we have to implement all abstract methods of the ValueAxis class.
//The first one, calculateMinorTickMarks is used to get the list of minor tick marks position that you want to display on the axis. You could find my definition below. It's based on the number of minor tick and the logarithmic formula.
#Override
protected List<Number> calculateMinorTickMarks() {
Number[] range = getRange();
List<Number> minorTickMarksPositions = new ArrayList<>();
if (range != null) {
Number lowerBound = range[0];
Number upperBound = range[1];
double logUpperBound = Math.log10(upperBound.doubleValue());
double logLowerBound = Math.log10(lowerBound.doubleValue());
int minorTickMarkCount = getMinorTickCount();
for (double i = logLowerBound; i <= logUpperBound; i += 1) {
for (double j = 0; j <= 10; j += (1. / minorTickMarkCount)) {
double value = j * Math.pow(10, i);
minorTickMarksPositions.add(value);
}
}
}
return minorTickMarksPositions;
}
//Then, the calculateTickValues method is used to calculate a list of all the data values for each tick mark in range, represented by the second parameter. The formula is the same than previously but here we want to display one tick each power of 10.
#Override
protected List<Number> calculateTickValues(double length, Object range) {
List<Number> tickPositions = new ArrayList<Number>();
if (range != null) {
Number lowerBound = ((Number[]) range)[0];
Number upperBound = ((Number[]) range)[1];
double logLowerBound = Math.log10(lowerBound.doubleValue());
double logUpperBound = Math.log10(upperBound.doubleValue());
System.out.println("lower bound is: " + lowerBound.doubleValue());
for (double i = logLowerBound; i <= logUpperBound; i += 1) {
for (double j = 1; j <= 10; j++) {
double value = (j * Math.pow(10, i));
tickPositions.add(value);
}
}
}
return tickPositions;
}
//The getRange provides the current range of the axis. A basic implementation is to return an array of the lowerBound and upperBound properties defined into the ValueAxis class.
#Override
protected Number[] getRange() {
return new Number[] { lowerBoundProperty().get(), upperBoundProperty().get() };
}
//The getTickMarkLabel is only used to convert the number value to a string that will be displayed under the tickMark. Here I choose to use a number formatter.
#Override
protected String getTickMarkLabel(Number value) {
NumberFormat formatter = NumberFormat.getInstance();
formatter.setMaximumIntegerDigits(6);
formatter.setMinimumIntegerDigits(1);
return formatter.format(value);
}
//The method setRange is used to update the range when data are added into the chart. There is two possibilities, the axis is animated or not. The simplest case is to set the lower and upper bound properties directly with the new values.
#Override
protected void setRange(Object range, boolean animate) {
if (range != null) {
Number lowerBound = ((Number[]) range)[0];
Number upperBound = ((Number[]) range)[1];
try {
validateBounds(lowerBound.doubleValue(), upperBound.doubleValue());
} catch (IllegalLogarithmicRangeException e) {
}
lowerBoundProperty().set(lowerBound.doubleValue());
upperBoundProperty().set(upperBound.doubleValue());
}
}
//We are almost done but we forgot to override 2 important methods that are used to perform the matching between data and the axis (and the reverse).
#Override
public Number getValueForDisplay(double displayPosition) {
double delta = logUpperBound.get() - logLowerBound.get();
if (getSide().isVertical()) {
return Math.pow(10, (((displayPosition - getHeight()) / -getHeight()) * delta) + logLowerBound.get());
} else {
return Math.pow(10, (((displayPosition / getWidth()) * delta) + logLowerBound.get()));
}
}
#Override
public double getDisplayPosition(Number value) {
double delta = logUpperBound.get() - logLowerBound.get();
double deltaV = Math.log10(value.doubleValue()) - logLowerBound.get();
if (getSide().isVertical()) {
return (1. - ((deltaV) / delta)) * getHeight();
} else {
return ((deltaV) / delta) * getWidth();
}
}
/**
* Exception to be thrown when a bound value isn't supported by the logarithmic axis<br>
*
*
* #author Kevin Senechal mailto: kevin.senechal#dooapp.com
*
*/
public class IllegalLogarithmicRangeException extends Exception {
/**
* #param string
*/
public IllegalLogarithmicRangeException(String message) {
super(message);
}
}
}
We too had these problems with the suggested implementation of logarithmicaxis, here is the complete code with fixes that worked for us..
import com.sun.javafx.charts.ChartLayoutAnimator;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.chart.ValueAxis;
import javafx.util.Duration;
//http://blog.dooapp.com/logarithmic-scale-strikes-back-in-javafx-20
//Edited by Vadim Levit & Benny Lutati for usage in AgentZero ( https://code.google.com/p/azapi-test/ )
public class LogarithmicNumberAxis extends ValueAxis<Number> {
private Object currentAnimationID;
private final ChartLayoutAnimator animator = new ChartLayoutAnimator(this);
//Create our LogarithmicAxis class that extends ValueAxis<Number> and define two properties that will represent the log lower and upper bounds of our axis.
private final DoubleProperty logUpperBound = new SimpleDoubleProperty();
private final DoubleProperty logLowerBound = new SimpleDoubleProperty();
//
//we bind our properties with the default bounds of the value axis. But before, we should verify the given range according to the mathematic logarithmic interval definition.
public LogarithmicNumberAxis() {
super(1, 10000000);
bindLogBoundsToDefaultBounds();
}
public LogarithmicNumberAxis(double lowerBound, double upperBound) {
super(lowerBound, upperBound);
validateBounds(lowerBound, upperBound);
bindLogBoundsToDefaultBounds();
}
public void setLogarithmizedUpperBound(double d) {
double nd = Math.pow(10, Math.ceil(Math.log10(d)));
setUpperBound(nd == d ? nd * 10 : nd);
}
/**
* Bind our logarithmic bounds with the super class bounds, consider the
* base 10 logarithmic scale.
*/
private void bindLogBoundsToDefaultBounds() {
logLowerBound.bind(new DoubleBinding() {
{
super.bind(lowerBoundProperty());
}
#Override
protected double computeValue() {
return Math.log10(lowerBoundProperty().get());
}
});
logUpperBound.bind(new DoubleBinding() {
{
super.bind(upperBoundProperty());
}
#Override
protected double computeValue() {
return Math.log10(upperBoundProperty().get());
}
});
}
/**
* Validate the bounds by throwing an exception if the values are not
* conform to the mathematics log interval: ]0,Double.MAX_VALUE]
*
* #param lowerBound
* #param upperBound
* #throws IllegalLogarithmicRangeException
*/
private void validateBounds(double lowerBound, double upperBound) throws IllegalLogarithmicRangeException {
if (lowerBound < 0 || upperBound < 0 || lowerBound > upperBound) {
throw new IllegalLogarithmicRangeException(
"The logarithmic range should be in [0,Double.MAX_VALUE] and the lowerBound should be less than the upperBound");
}
}
//Now we have to implement all abstract methods of the ValueAxis class.
//The first one, calculateMinorTickMarks is used to get the list of minor tick marks position that you want to display on the axis. You could find my definition below. It's based on the number of minor tick and the logarithmic formula.
#Override
protected List<Number> calculateMinorTickMarks() {
List<Number> minorTickMarksPositions = new ArrayList<>();
return minorTickMarksPositions;
}
//Then, the calculateTickValues method is used to calculate a list of all the data values for each tick mark in range, represented by the second parameter. The formula is the same than previously but here we want to display one tick each power of 10.
#Override
protected List<Number> calculateTickValues(double length, Object range) {
LinkedList<Number> tickPositions = new LinkedList<>();
if (range != null) {
double lowerBound = ((double[]) range)[0];
double upperBound = ((double[]) range)[1];
for (double i = Math.log10(lowerBound); i <= Math.log10(upperBound); i++) {
tickPositions.add(Math.pow(10, i));
}
if (!tickPositions.isEmpty()) {
if (tickPositions.getLast().doubleValue() != upperBound) {
tickPositions.add(upperBound);
}
}
}
return tickPositions;
}
/**
* The getRange provides the current range of the axis. A basic
* implementation is to return an array of the lowerBound and upperBound
* properties defined into the ValueAxis class.
*
* #return
*/
#Override
protected double[] getRange() {
return new double[]{
getLowerBound(),
getUpperBound()
};
}
/**
* The getTickMarkLabel is only used to convert the number value to a string
* that will be displayed under the tickMark. Here I choose to use a number
* formatter.
*
* #param value
* #return
*/
#Override
protected String getTickMarkLabel(Number value) {
NumberFormat formatter = NumberFormat.getInstance();
formatter.setMaximumIntegerDigits(10);
formatter.setMinimumIntegerDigits(1);
return formatter.format(value);
}
/**
* The method setRange is used to update the range when data are added into
* the chart. There is two possibilities, the axis is animated or not. The
* simplest case is to set the lower and upper bound properties directly
* with the new values.
*
* #param range
* #param animate
*/
#Override
protected void setRange(Object range, boolean animate) {
if (range != null) {
final double[] rangeProps = (double[]) range;
final double lowerBound = rangeProps[0];
final double upperBound = rangeProps[1];
final double oldLowerBound = getLowerBound();
setLowerBound(lowerBound);
setUpperBound(upperBound);
if (animate) {
animator.stop(currentAnimationID);
currentAnimationID = animator.animate(
new KeyFrame(Duration.ZERO,
new KeyValue(currentLowerBound, oldLowerBound)
),
new KeyFrame(Duration.millis(700),
new KeyValue(currentLowerBound, lowerBound)
)
);
} else {
currentLowerBound.set(lowerBound);
}
}
}
/**
* We are almost done but we forgot to override 2 important methods that are
* used to perform the matching between data and the axis (and the reverse).
*
* #param displayPosition
* #return
*/
#Override
public Number getValueForDisplay(double displayPosition) {
double delta = logUpperBound.get() - logLowerBound.get();
if (getSide().isVertical()) {
return Math.pow(10, (((displayPosition - getHeight()) / -getHeight()) * delta) + logLowerBound.get());
} else {
return Math.pow(10, (((displayPosition / getWidth()) * delta) + logLowerBound.get()));
}
}
#Override
public double getDisplayPosition(Number value) {
double delta = logUpperBound.get() - logLowerBound.get();
double deltaV = Math.log10(value.doubleValue()) - logLowerBound.get();
if (getSide().isVertical()) {
return (1. - ((deltaV) / delta)) * getHeight();
} else {
return ((deltaV) / delta) * getWidth();
}
}
/**
* Exception to be thrown when a bound value isn't supported by the
* logarithmic axis<br>
*
*
* #author Kevin Senechal mailto: kevin.senechal#dooapp.com
*
*/
public class IllegalLogarithmicRangeException extends RuntimeException {
/**
* #param string
*/
public IllegalLogarithmicRangeException(String message) {
super(message);
}
}
}
I think your problem is this:
super(1, 100);
From the documentation:
Create a non-auto-ranging ValueAxis with the given upper & lower bound
Try using a constructor without parameters, which will make the boundaries auto-ranging.
You should end up with a constructor looking like this:
public LogarithmicAxis() {
// was: super(1, 100);
super();
bindLogBoundsToDefaultBounds();
}

How to implement date picker in lwuit?

I'm developing a mobile app using j2me and lwuit.
There is a lcdui DateField (act as date picker) in j2me. Like that there is any component or item in lwuit.
How to implement the date picker (Similar to lcdui DateField) in lwuit.
The calendar (in lwuit) object is not user friendly. If phone screen size is small then it will not be correctly shown. In normal j2me (lcdui) the datefield has very good look. I want to create a component/item like that in lwuit (using lwuit in j2me).
You can use lcdui DateField in lwuit. I do it by this way:
import java.util.Calendar;
import java.util.Date;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.DateField;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import com.sun.lwuit.Button;
import com.sun.lwuit.Display;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.plaf.UIManager;
public class DatePicker extends Button implements ActionListener {
private static final String OK = "ok";
private static final String CANCEL = "cancel";
private Date date;
public DatePicker() {
setUIID("TextArea");
addActionListener(this);
}
public Date getDate() {
return date;
}
public void actionPerformed(ActionEvent evt) {
final Form dateForm = new Form();
final DateField dateField = new DateField(null, DateField.DATE);
if (date != null) {
dateField.setDate(date);
}
dateForm.append(dateField);
final javax.microedition.lcdui.Command acceptCommand = new javax.microedition.lcdui.Command(UIManager.getInstance().localize(OK, OK),
javax.microedition.lcdui.Command.OK, 0);
final javax.microedition.lcdui.Command cancelCommand = new javax.microedition.lcdui.Command(UIManager.getInstance().localize(CANCEL, CANCEL), javax.microedition.lcdui.Command.CANCEL, 0);
dateForm.addCommand(acceptCommand);
dateForm.addCommand(cancelCommand);
CommandListener commandListener = new CommandListener() {
public void commandAction(javax.microedition.lcdui.Command command, Displayable displayable) {
if (command == acceptCommand && dateField.getDate() != null) {
DatePicker.this.date = dateField.getDate();
DatePicker.this.setText(DatePicker.toString(DatePicker.this.date));
}
Display.init(Application.getInstance().midlet); // You have to save your midlet
Application.getInstance().mainForm.show(); // and the last lwuit Form
}
};
dateForm.setCommandListener(commandListener);
javax.microedition.lcdui.Display.getDisplay(Application.getInstance().midlet).setCurrent(dateForm); // Application.getInstance().midlet - your j2me application midlet
}
}
So now you can use it like lwuit Component, but on the actionPerformed it will open lcdui native Form with DateField on the top.
I have developed a calender extending component and it work fine in LWUIT and the code I used as follows
public class Calendar extends Container {
private ComboBox month;
private ComboBox year;
private MonthView mv;
private static final String[] MONTHS = new String[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
private static final String[] DAYS = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
private static final String[] LABELS = {"Su", "M", "Tu", "W", "Th", "F", "Sa"};
static final long MINUTE = 1000 * 60;
static final long HOUR = MINUTE * 60;
static final long DAY = HOUR * 24;
static final long WEEK = DAY * 7;
private EventDispatcher dispatcher = new EventDispatcher();
private EventDispatcher dataChangeListeners = new EventDispatcher();
private long[] dates = new long[42];
private boolean changesSelectedDateEnabled = true;
private TimeZone tmz;
private static ComboListCellRenderer comboListCellRenderer = new ComboListCellRenderer();;
private int[] bgColorArray = new int[]{0x2E9AFE, 0x39FEB6, 0x39FEB6};
/**
* Creates a new instance of Calendar set to the given date based on time
* since epoch (the java.util.Date convention)
*
* #param time time since epoch
*/
public Calendar(int[] bgColorArray, ListCellRenderer listCellRenderer, long time) {
this(bgColorArray, listCellRenderer, time, java.util.TimeZone.getDefault());
}
/**
* Constructs a calendar with the current date and time
*/
public Calendar(int[] bgColorArray, ListCellRenderer listCellRenderer) {
this(bgColorArray, listCellRenderer, System.currentTimeMillis());
}
/**
* Constructs a calendar with the current date and time
*/
public Calendar() {
this(null, comboListCellRenderer, System.currentTimeMillis());
}
/**
* Creates a new instance of Calendar set to the given date based on time
* since epoch (the java.util.Date convention)
*
* #param time time since epoch
* #param tmz a reference timezone
*/
public Calendar(int[] bgColorArray, ListCellRenderer listCellRenderer, long time, TimeZone tmz) {
super(new BorderLayout());
if(bgColorArray != null)
this.bgColorArray = bgColorArray;
this.tmz = tmz;
setUIID("Calendar");
Container upper = new Container(new FlowLayout(Component.CENTER));
month = new ComboBox();
year = new ComboBox();
mv = new MonthView(time);
Vector months = new Vector();
for (int i = 0; i < MONTHS.length; i++) {
months.addElement("" + getLocalizedMonth(i));
}
ListModel monthsModel = new DefaultListModel(months);
int selected = months.indexOf(getLocalizedMonth(mv.getMonth()));
month.setModel(monthsModel);
month.setSelectedIndex(selected);
month.addActionListener(mv);
if(listCellRenderer != null){
month.setListCellRenderer(listCellRenderer);
year.setListCellRenderer(listCellRenderer);
}
month.getSelectedStyle().setBgColor(bgColorArray[1]);
month.getUnselectedStyle().setBgColor(bgColorArray[0]);
month.getPressedStyle().setBgColor(bgColorArray[2]);
year.getSelectedStyle().setBgColor(bgColorArray[1]);
year.getUnselectedStyle().setBgColor(bgColorArray[0]);
year.getPressedStyle().setBgColor(bgColorArray[2]);
/* month.getSelectedStyle().setBgColor(0xff00000);
year.getSelectedStyle().setBgColor(0xff00000);
ComboListCellRenderer comboListCellRenderer = new ComboListCellRenderer();
*/
java.util.Calendar cal = java.util.Calendar.getInstance(tmz);
cal.setTime(new java.util.Date(time));
month.getStyle().setBgTransparency(0);
int y = cal.get(java.util.Calendar.YEAR);
Vector years = new Vector();
for (int i = 2100; i > 1900; i--) {
years.addElement("" + i);
}
ListModel yearModel = new DefaultListModel(years);
selected = years.indexOf("" + y);
year.setModel(yearModel);
year.setSelectedIndex(selected);
year.getStyle().setBgTransparency(0);
year.addActionListener(mv);
Container cnt = new Container(new BoxLayout(BoxLayout.X_AXIS));
cnt.setRTL(false);
Container dateCnt = new Container(new BoxLayout(BoxLayout.X_AXIS));
dateCnt.setUIID("CalendarDate");
dateCnt.addComponent(month);
dateCnt.addComponent(year);
cnt.addComponent(dateCnt);
upper.addComponent(cnt);
addComponent(BorderLayout.NORTH, upper);
addComponent(BorderLayout.CENTER, mv);
}
/**
* Returns the time for the current calendar.
*
* #return the time for the current calendar.
*/
public long getSelectedDay() {
return mv.getSelectedDay();
}
private String getLocalizedMonth(int i) {
Hashtable t = UIManager.getInstance().getResourceBundle();
String text = MONTHS[i];
if (t != null) {
Object o = t.get("Calendar." + text);
if (o != null) {
text = (String) o;
}
}
return text;
}
void componentChanged() {
java.util.Calendar cal = java.util.Calendar.getInstance(tmz);
cal.set(java.util.Calendar.YEAR, mv.getYear());
cal.set(java.util.Calendar.MONTH, mv.getMonth());
cal.set(java.util.Calendar.DAY_OF_MONTH, mv.getDayOfMonth());
month.getParent().revalidate();
}
/**
* Return the date object matching the current selection
*
* #return the date object matching the current selection
*/
public Date getDate() {
return new Date(mv.getSelectedDay());
}
/**
* Sets the current date in the view and the selected date to be the same.
*
* #param d new date
*/
public void setDate(Date d) {
mv.setSelectedDay(d.getTime());
mv.setCurrentDay(mv.currentDay, true);
componentChanged();
}
/**
* This method sets the Calendar selected day
* #param d the selected day
*/
public void setSelectedDate(Date d){
mv.setSelectedDay(d.getTime());
}
/**
* Sets the Calendar view on the given date, only the the month and year
* are being considered.
*
* #param d the date to set the calendar view on.
*/
public void setCurrentDate(Date d){
mv.setCurrentDay(d.getTime(), true);
componentChanged();
}
/**
* Sets the Calendar timezone, if not specified Calendar will use the
* default timezone
* #param tmz the timezone
*/
public void setTimeZone(TimeZone tmz){
this.tmz = tmz;
}
/**
* Gets the Calendar timezone
*
* #return Calendar TimeZone
*/
public TimeZone getTimeZone(){
return tmz;
}
/**
* Sets the selected style of the month view component within the calendar
*
* #param s style for the month view
*/
public void setMonthViewSelectedStyle(Style s) {
mv.setSelectedStyle(s);
}
/**
* Sets the un selected style of the month view component within the calendar
*
* #param s style for the month view
*/
public void setMonthViewUnSelectedStyle(Style s) {
mv.setUnselectedStyle(s);
}
/**
* Gets the selected style of the month view component within the calendar
*
* #return the style of the month view
*/
public Style getMonthViewSelectedStyle() {
return mv.getSelectedStyle();
}
/**
* Gets the un selected style of the month view component within the calendar
*
* #return the style of the month view
*/
public Style getMonthViewUnSelectedStyle() {
return mv.getUnselectedStyle();
}
/**
* Fires when a change is made to the month view of this component
*
* #param l listener to add
*/
public void addActionListener(ActionListener l) {
mv.addActionListener(l);
}
/**
* Fires when a change is made to the month view of this component
*
* #param l listener to remove
*/
public void removeActionListener(ActionListener l) {
mv.removeActionListener(l);
}
/**
* Allows tracking selection changes in the calendar in real time
*
* #param l listener to add
*/
public void addDataChangeListener(DataChangedListener l) {
mv.addDataChangeListener(l);
}
/**
* Allows tracking selection changes in the calendar in real time
*
* #param l listener to remove
*/
public void removeDataChangeListener(DataChangedListener l) {
mv.removeDataChangeListener(l);
}
/**
* This flag determines if selected date can be changed by selecting an
* alternative date
*
* #param changesSelectedDateEnabled if true pressing on a date will cause
* the selected date to be changed to the pressed one
*/
public void setChangesSelectedDateEnabled(boolean changesSelectedDateEnabled) {
this.changesSelectedDateEnabled = changesSelectedDateEnabled;
}
/**
* This flag determines if selected date can be changed by selecting an
* alternative date
*
* #return true if enabled
*/
public boolean isChangesSelectedDateEnabled() {
return changesSelectedDateEnabled;
}
/**
* This method creates the Day Button Component for the Month View
*
* #return a Button that corresponds to the Days Components
*/
protected Button createDay() {
Button day = new Button();
day.setAlignment(CENTER);
day.setUIID("CalendarDay");
day.setEndsWith3Points(false);
day.setTickerEnabled(false);
return day;
}
/**
* This method creates the Day title Component for the Month View
*
* #param day the relevant day values are 0-6 where 0 is sunday.
* #return a Label that corresponds to the relevant Day
*/
protected Label createDayTitle(int day) {
String value = UIManager.getInstance().localize("Calendar." + DAYS[day], LABELS[day]);
Label dayh = new Label(value, "CalendarTitle");
dayh.setEndsWith3Points(false);
dayh.setTickerEnabled(false);
return dayh;
}
/**
* This method updates the Button day.
*
* #param dayButton the button to be updated
* #param day the new button day
*/
protected void updateButtonDayDate(Button dayButton, int currentMonth, int day) {
dayButton.setText("" + day);
}
class MonthView extends Container implements ActionListener{
private long currentDay;
private Button[] buttons = new Button[42];
private Button selected;
private long selectedDay = -1;
public MonthView(long time) {
super(new GridLayout(7, 7));
setUIID("MonthView");
for (int iter = 0; iter < DAYS.length; iter++) {
addComponent(createDayTitle(iter));
}
for (int iter = 0; iter < buttons.length; iter++) {
buttons[iter] = createDay();
addComponent(buttons[iter]);
if (iter <= 7) {
buttons[iter].setNextFocusUp(year);
}
buttons[iter].addActionListener(this);
}
setCurrentDay(time);
}
public void setCurrentDay(long day){
setCurrentDay(day, false);
}
private void setCurrentDay(long day, boolean force) {
repaint();
java.util.Calendar cal = java.util.Calendar.getInstance(tmz);
cal.setTime(new Date(currentDay));
cal.set(java.util.Calendar.HOUR, 1);
cal.set(java.util.Calendar.HOUR_OF_DAY, 1);
cal.set(java.util.Calendar.MINUTE, 0);
cal.set(java.util.Calendar.SECOND, 0);
cal.set(java.util.Calendar.MILLISECOND, 0);
int yearOld = cal.get(java.util.Calendar.YEAR);
int monthOld = cal.get(java.util.Calendar.MONTH);
int dayOld = cal.get(java.util.Calendar.DAY_OF_MONTH);
cal.setTime(new Date(day));
cal.set(java.util.Calendar.HOUR, 1);
cal.set(java.util.Calendar.HOUR_OF_DAY, 1);
cal.set(java.util.Calendar.MINUTE, 0);
cal.set(java.util.Calendar.SECOND, 0);
cal.set(java.util.Calendar.MILLISECOND, 0);
int yearNew = cal.get(java.util.Calendar.YEAR);
int monthNew = cal.get(java.util.Calendar.MONTH);
int dayNew = cal.get(java.util.Calendar.DAY_OF_MONTH);
year.setSelectedItem("" + yearNew);
month.setSelectedIndex(monthNew);
if (yearNew != yearOld || monthNew != monthOld || dayNew != dayOld || force) {
currentDay = cal.getTime().getTime();
if(selectedDay == -1){
selectedDay = currentDay;
}
int month = cal.get(java.util.Calendar.MONTH);
cal.set(java.util.Calendar.DAY_OF_MONTH, 1);
long startDate = cal.getTime().getTime();
int dow = cal.get(java.util.Calendar.DAY_OF_WEEK);
cal.setTime(new Date(cal.getTime().getTime() - DAY));
cal.set(java.util.Calendar.HOUR, 1);
cal.set(java.util.Calendar.HOUR_OF_DAY, 1);
cal.set(java.util.Calendar.MINUTE, 0);
cal.set(java.util.Calendar.SECOND, 0);
cal.set(java.util.Calendar.MILLISECOND, 0);
int lastDay = cal.get(java.util.Calendar.DAY_OF_MONTH);
int i = 0;
if(dow > java.util.Calendar.SUNDAY){
//last day of previous month
while (dow > java.util.Calendar.SUNDAY) {
cal.setTime(new Date(cal.getTime().getTime() - DAY));
dow = cal.get(java.util.Calendar.DAY_OF_WEEK);
}
int previousMonthSunday = cal.get(java.util.Calendar.DAY_OF_MONTH);
for (; i <= lastDay - previousMonthSunday; i++) {
buttons[i].setUIID("CalendarDay");
buttons[i].setEnabled(false);
buttons[i].setText("" + (previousMonthSunday + i));
}
}
//last day of current month
cal.set(java.util.Calendar.MONTH, (month + 1) % 12);
cal.set(java.util.Calendar.DAY_OF_MONTH, 1);
cal.setTime(new Date(cal.getTime().getTime() - DAY));
lastDay = cal.get(java.util.Calendar.DAY_OF_MONTH);
int j = i;
for (; j < buttons.length && (j - i + 1) <= lastDay; j++) {
buttons[j].setEnabled(true);
dates[j] = startDate;
if(dates[j] == selectedDay){
buttons[j].setUIID("CalendarSelectedDay");
selected = buttons[j];
}else{
buttons[j].setUIID("CalendarDay");
}
buttons[j].getSelectedStyle().setBgColor(bgColorArray[1]);
buttons[j].getUnselectedStyle().setBgColor(bgColorArray[0]);
buttons[j].getPressedStyle().setBgColor(bgColorArray[2]);
buttons[j].getStyle().setFont(Font.createSystemFont(
Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL));
buttons[j].getSelectedStyle().setFont(Font.createSystemFont(
Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL));
buttons[j].getUnselectedStyle().setFont(Font.createSystemFont(
Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL));
buttons[j].getPressedStyle().setFont(Font.createSystemFont(
Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL));
updateButtonDayDate(buttons[j], month, j - i + 1);
startDate += DAY;
}
int d = 1;
for (; j < buttons.length; j++) {
buttons[j].setUIID("CalendarDay");
buttons[j].setEnabled(false);
buttons[j].setText("" + d++);
buttons[j].getStyle().setFont(Font.createSystemFont(
Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL));
buttons[j].getSelectedStyle().setFont(Font.createSystemFont(
Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL));
buttons[j].getUnselectedStyle().setFont(Font.createSystemFont(
Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL));
buttons[j].getPressedStyle().setFont(Font.createSystemFont(
Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL));
}
}
}
public int getDayOfMonth() {
java.util.Calendar cal = java.util.Calendar.getInstance(tmz);
cal.setTime(new Date(currentDay));
return cal.get(java.util.Calendar.DAY_OF_MONTH);
}
public int getMonth() {
java.util.Calendar cal = java.util.Calendar.getInstance(tmz);
cal.setTime(new Date(currentDay));
return cal.get(java.util.Calendar.MONTH);
}
public void incrementMonth() {
int month = getMonth();
month++;
int year = getYear();
if (month > java.util.Calendar.DECEMBER) {
month = java.util.Calendar.JANUARY;
year++;
}
setMonth(year, month);
}
private long getSelectedDay() {
return selectedDay;
}
public void setSelectedDay(long selectedDay){
java.util.Calendar cal = java.util.Calendar.getInstance(tmz);
cal.setTime(new Date(selectedDay));
cal.set(java.util.Calendar.HOUR, 1);
cal.set(java.util.Calendar.HOUR_OF_DAY, 1);
cal.set(java.util.Calendar.MINUTE, 0);
cal.set(java.util.Calendar.SECOND, 0);
cal.set(java.util.Calendar.MILLISECOND, 0);
this.selectedDay = cal.getTime().getTime();
}
private void setMonth(int year, int month) {
java.util.Calendar cal = java.util.Calendar.getInstance(tmz);
cal.setTimeZone(TimeZone.getDefault());
cal.set(java.util.Calendar.MONTH, month);
cal.set(java.util.Calendar.DAY_OF_MONTH, 1);
cal.set(java.util.Calendar.YEAR, year);
Date date = cal.getTime();
long d = date.getTime();
// if this is past the last day of the month (e.g. going from January 31st
// to Febuary) we need to decrement the day until the month is correct
while (cal.get(java.util.Calendar.MONTH) != month) {
d -= DAY;
cal.setTime(new Date(d));
}
setCurrentDay(d);
}
public void decrementMonth() {
int month = getMonth();
month--;
int year = getYear();
if (month < java.util.Calendar.JANUARY) {
month = java.util.Calendar.DECEMBER;
year--;
}
setMonth(year, month);
}
public int getYear() {
java.util.Calendar cal = java.util.Calendar.getInstance(tmz);
cal.setTime(new Date(currentDay));
return cal.get(java.util.Calendar.YEAR);
}
public void addActionListener(ActionListener l) {
dispatcher.addListener(l);
}
public void removeActionListener(ActionListener l) {
dispatcher.removeListener(l);
}
/**
* Allows tracking selection changes in the calendar in real time
*
* #param l listener to add
*/
public void addDataChangeListener(DataChangedListener l) {
dataChangeListeners.addListener(l);
}
/**
* Allows tracking selection changes in the calendar in real time
*
* #param l listener to remove
*/
public void removeDataChangeListener(DataChangedListener l) {
dataChangeListeners.removeListener(l);
}
protected void fireActionEvent() {
componentChanged();
super.fireActionEvent();
dispatcher.fireActionEvent(new ActionEvent(Calendar.this));
}
public void actionPerformed(ActionEvent evt) {
Object src = evt.getSource();
if(src instanceof ComboBox){
setMonth(Integer.parseInt((String)year.getSelectedItem()),
month.getSelectedIndex());
componentChanged();
return;
}
if(changesSelectedDateEnabled){
System.out.println("ttttttttttttttttttttttttttttt");
for (int iter = 0; iter < buttons.length; iter++) {
if (src == buttons[iter]) {
selected.setUIID("CalendarDay");
buttons[iter].setUIID("CalendarSelectedDay");
selectedDay = dates[iter];
selected.getSelectedStyle().setBgColor(bgColorArray[1]);
selected.getUnselectedStyle().setBgColor(bgColorArray[0]);
selected.getPressedStyle().setBgColor(bgColorArray[2]);
selected = buttons[iter];
selected.getSelectedStyle().setBgColor(bgColorArray[1]);
selected.getUnselectedStyle().setBgColor(bgColorArray[0]);
selected.getPressedStyle().setBgColor(bgColorArray[2]);
fireActionEvent();
if (!getComponentForm().isSingleFocusMode()) {
setHandlesInput(false);
}
return;
}
}
}
}
}
}

Resources