Copy slideshow slides to new slideshow including master and box locations(Apache POI) - apache-poi

Is there any way to completely copy a slide from one slideshow to another slideshow including all of the box locations, colors, fonts, etc.?
Referencing the cookbook I have the below
private void copySlides(XMLSlideShow fromPptx, XMLSlideShow toPptx) {
for(XSLFSlide fromSlide : fromPptx.getSlides()){
toPptx.createSlide().importContent(fromSlide);
}
}
However the background doesn't match the 'from' pptx and the a number of the text boxes are shifted. I'm guessing the colors are due to me not modifying the master and the shift is because something related to the anchors. I have also tried what I thought would force the master of one slide onto the other, but it does the same thing as above.
private void copySlides(XMLSlideShow fromPptx, XMLSlideShow toPptx) {
for(XSLFSlide fromSlide : fromPptx.getSlides()){
XSLFSlide toSlide = toPptx.createSlide();
copySlide(fromSlide, toSlide);
toSlide.importContent(fromSlide);
}
}
private static void copySlide(
final XSLFSlide fromSlide, final XSLFSlide toSlide) {
XSLFSlideLayout fromLayout = fromSlide.getSlideLayout();
XSLFSlideMaster fromMaster = fromSlide.getSlideMaster();
XSLFSlideLayout toLayout = toSlide.getSlideLayout();
XSLFSlideMaster toMaster = toSlide.getSlideMaster();
toLayout.importContent(fromLayout);
toMaster.importContent(fromMaster);
}

If I set either toSlide.setFollowMasterGraphics(false); or toSlide.setFollowMasterObjects(false); I can set the background color.
For the boxes not being in the correct location it seems that the boxes were in the correct location, but the slides were different sizes. In my case I'm fine with using whatever is the 'final' slide size, and if multiple sizes show up someone will have to deal with it.
private void copySlides(XMLSlideShow fromPptx, XMLSlideShow toPptx) {
for(XSLFSlide fromSlide : fromPptx.getSlides()){
XSLFSlide toSlide = toPptx.createSlide();
copySlide(fromSlide, toSlide);
toSlide.importContent(fromSlide);
}
toPptx.setPageSize(fromPptx.getPageSize());
}
private static void copySlide(
final XSLFSlide fromSlide, final XSLFSlide toSlide) {
toSlide.setFollowMasterGraphics(false);
toSlide.setFollowMasterObjects(false);
XSLFSlideLayout fromLayout = fromSlide.getSlideLayout();
XSLFSlideMaster fromMaster = fromSlide.getSlideMaster();
XSLFBackground fromBackground = fromSlide.getBackground();
XSLFSlideLayout toLayout = toSlide.getSlideLayout();
XSLFSlideMaster toMaster = toSlide.getSlideMaster();
XSLFBackground toBackground = toSlide.getBackground();
toLayout.importContent(fromLayout);
toMaster.importContent(fromMaster);
toBackground.setFillColor(fromBackground.getFillColor());
}
This does not fully answer my question (which may be unobtainable based on some forum comments I read) but this solves the problem I was up against.
For anyone else that comes across this I also played with getting all of the shapes in the 'from' and 'to' slides and trying to copy things from one to the other, but was not necessary for me.

Related

LibGDX very strange bug - objects are disappeared

When I was creating my first tiled map creator in libGDX, I noticed a very strange bug. I creating grid of objects like this:
private static final int GRID_WIDTH=2400;
private static final int GRID_HEIGHT=2400;
private static final int CELL_SIZE=60;
so you can see there are 2400/60x2400/60 objects or cells. I am creating my map like this:
private void createMap(){
cells = new Cell[GRID_WIDTH/CELL_SIZE][GRID_HEIGHT/CELL_SIZE];
for(int i=0;i<GRID_WIDTH/CELL_SIZE;++i){
for(int j=0;j<GRID_HEIGHT/CELL_SIZE;++j){
cells[i][j]=new Cell(textures[0],i*CELL_SIZE,j*CELL_SIZE);
}
}
}
I also have coordinates for my debug in the screen so I know where they started to disappear. Y coordinate is ok there are from 0 to 2400, but on the X they started to disappear at 1500. When I start to draw there some texture every column will be visible to that texture for example (when I start to write texture at x=2100 every disappeared column will be visible to 2100) and when I will delete that texture every column will disappear again to 1500. So the objects are there but they are not visible. It is so annoying does anyone know about this bug?
As you can see coordinates are at the bottom left this is at the beginning:
and this is when I will add there some texture
[Edited] Code with camera:
private float x=GRID_WIDTH/2,y=GRID_HEIGHT/2;
#Override
public void render(float delta) {
batch = new SpriteBatch();
camera=new OrthographicCamera(CAM_WIDTH,CAM_HEIGHT);
viewPos = new Vector3();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
viewPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(viewPos);
batch.begin();
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT) || Gdx.input.isKeyPressed(Input.Keys.D))
x+=SPEED*Gdx.graphics.getDeltaTime();
if(Gdx.input.isKeyPressed(Input.Keys.LEFT) || Gdx.input.isKeyPressed(Input.Keys.A))
x-=SPEED*Gdx.graphics.getDeltaTime();
if(Gdx.input.isKeyPressed(Input.Keys.UP) || Gdx.input.isKeyPressed(Input.Keys.W))
y+=SPEED*Gdx.graphics.getDeltaTime();
if(Gdx.input.isKeyPressed(Input.Keys.DOWN) || Gdx.input.isKeyPressed(Input.Keys.S))
y-=SPEED*Gdx.graphics.getDeltaTime();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
camera.position.set(x,y,0);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.end();
}
The camera is correct. The problem is the batch.begin() and batch.end(). As you might know you cannot do batch.begin() and then shaperenderer.begin() directly after each others without closing one of them. Reason for this I am not 100% about. stage works similar. This means we have to close the batch before drawing the stage
batch.end();
stage.draw();
batch.begin();
// draw your batch stuff here
Also it's terrible to do this
batch = new SpriteBatch();
camera=new OrthographicCamera(CAM_WIDTH,CAM_HEIGHT);
inside the render method. Instead, put it into the create() method or some of your own initialize method. The important thing is to not create a new SpriteBatch every frame as the batch isn't collected by the GC. So you have to manually dispose it using batch.dispose() or it will leak so much memory your RAM will be gone in no time.
I hope this helped you out, good luck.

Wait() & Sleep() Not Working As Thought

Using JavaFX 8.0 and JRE 1.8.0 u45 in IntelliJ, I created a basic pixel editor app. I have two windows(stages). One is a 32x128 matrix of Circle Objects placed in a Grid Pane and the other, a Tools widow; I have one Controller.java. Using the mouse, the Tools window provides tools to draw lines, rectangles, etc. and a menu for Setup, Files and Playlists. The Files menu presents the user with Open, SaveAs and Delete. To view a saved pixel art file, the user clicks Open and via the JFileChooser, the selected file is opened and each Circle’s assigned color is displayed using the following method:
public static void openFile( String pathName) throws IOException {
path = Paths.get(pathName);
pixelByteArray = Files.readAllBytes(path);
int cnt = 0;
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
String hexRGB = String.format("#%02X%02X%02X",
pixelByteArray[cnt++], //red
pixelByteArray[cnt++], //green
pixelByteArray[cnt++]); //blue
Color color = Color.valueOf(hexRGB);
pixelArray[r][c].setFill(color);
}
}
String fileName = path.getFileName().toString();
window.setTitle(MessageFormat.format("Pixel Array {0} x {1} File: {2}", Integer.toString(row), Integer.toString(col), fileName));
} // openFile
The Circle’s color is updated with for loops using setFill(color).
Next I created a class to test a basic slide show. I would use JFileChooser to select multiple files, put them in an ArrayList<file> and use the openFile(pathname) in a for loop to display each, pausing 5 secs between each openFile(pathname) as shown below:
public class PlayPlaylist {
public static void playPlaylist() throws IOException, InterruptedException {
FileChooser fileChooser = new FileChooser();
fileChooser.setInitialDirectory(new File("C:\\ProgramData\\L1 Art Files\\"));
fileChooser.setTitle("Play One or More Pixel Art Files");
java.util.List<File> selectedFiles = fileChooser.showOpenMultipleDialog(null);
for (File selectedFile : selectedFiles) {
openFile(selectedFile.getPath());
sleep(5000);
}
} //Method playPlaylist()
I first used wait(5000) but couldn’t compile because I have a static method, which I need. The wait() method won’t run in a static method. I then tried sleep(5000) which compiles but to my confusion only the last file in the ArrayList<file> will be displayed. All the pixel art files will display the setTitle() correctly and pause for about 5 secs but the Circle’s will not change to the assigned color except for the last file, after the 5 secs have passed. The for loop, setFill(color) process in openFile() seems to be paused even though the setTitle() is executed correctly, which is after the setFill(color) process?
I’m new to Java and JavaFX and have never created any threads directly in this program or any other but researching possible problems implies the problem may be related to threads.
Is there a classic fix to this problem? Thanks for any help
After studying the references and suggested solutions below, I am unable to fix the problem. I tried two code changes. The first was to the for loop code above:
for (File selectedFile : selectedFiles) {
Platform.runLater(() -> {
try {
openFile(selectedFile.getPath());
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
});
The second change was to the openFile(pathname) above:
final int finalR = r;
final int finalC = c;
Platform.runLater(() -> pixelArray[finalR][finalC].setFill(color));
I get the same results as described above with only the last file being displayed. If I simply select one file in the Arraylist<File> it will display, i.e.:
if (selectedFiles != null) {
File playFile = selectedFiles.get(0);
openFile(playFile.getPath());
System.out.println("\n File 1 = " + playFile.getPath());
}
Now if I add Sleep(5000):
if (selectedFiles != null) {
File playFile = selectedFiles.get(0);
openFile(playFile.getPath());
System.out.println("\n File 1 = " + playFile.getPath());
sleep(5000);
}
It will display the pixel art file after 5 secs. What I don't understand is why it appears to "skip" over the pixelArray[r][c].setFill(color)); which sets all the Circle's to the saved colors but does execute the following and last statement in the openFile(pathname) which is setTitle(...)? It's like sleep(5000) blocks the pixelArray[r][c].setFill(color));but nothing else?
Why can I openFile(pathname) for just one file with proper results but not two or more in sequence?
I also have the two UI windows posted on the web at: Virtual Art. I think the pixel art shown in the Pixel Array window clarifies the goal of creating a user-defined slide show.
***This question was answered elegantly by jewelsea at:
How to avoid Thread.sleep() in a for loop from interrupting the UI Thread?***
You have two problems here, your understanding of wait(), and a GUI multithreading issue.
About the GUI multithreading... You will find more informations here about Platform.runLater(...):
Platform.runLater and Task in JavaFX
Now about Wait... It will pause your Thread until a Notify event is received through its monitor. To be able to call notify() you need to synchronize on the same object (the monitor).
synchronized (someObject) {
someObject.wait();
}
/* different thread / object */
synchronized (someObject) {
someObject.notify();
}
If you want to use Wait, you will need another Thread (a Timer?), to wakeup/notify you. Sleep should work fine in your case, as long as you use Platform.runlater(...)

Displaying javafx 2 linechart values on hover

I have been using this example for my project, and it works really nice.
My question: Is it possible to offset the hovered node such that it does not overlay the underlying data point. The example centers the hovered node right over the "normal" node. It kind of gets in the way on a chart with a lot of data points.
A simple solution is to set a custom translation to the displayed Label. The following code is extracted from the example.
private Label createDataThresholdLabel(int priorValue, int value)
{
final Label label = new Label(value + "");
label.setTranslateY(-25); //Move label 25 pixels up
label.getStyleClass().addAll("default-color0", "chart-line-symbol", "chart-series-line");
label.setStyle("-fx-font-size: 20; -fx-font-weight: bold;");
if (priorValue == 0)
{
label.setTextFill(Color.DARKGRAY);
}
else if (value > priorValue)
{
label.setTextFill(Color.FORESTGREEN);
}
else
{
label.setTextFill(Color.FIREBRICK);
}
label.setMinSize(Label.USE_PREF_SIZE, Label.USE_PREF_SIZE);
return label;
}

Dynamically selecting JavaFX LIneChart symbol colors

I have a JavaFX app which contains a line chart. I want users to be able to select the color of each series in the chart. Since the selection is dynamic I can't use static CSS to set the colors. I also have other controls that I need to set to the same color as the associated series. It's possible to set the line color of a series dynamically using code like this:
series.getNode().setStyle("-fx-stroke: " + color + ";");
That works well and I can use the user-specified color on the associated controls.
My problem is that I also need to set the color of the symbols for each series to the same color. I can't find any way to do that dynamically. All of the tutorials, documentation, and posts that I've read on the topic point to the static CSS approach.
Most charting widgets make this sort of thing very easy to do, but I've found no clues here or on the Oracle forums. Any guidance would be greatly appreciated.
-- Update --
I've found no way to do this other than to enumerate every data point in every series, grab the associated symbol node and set the style individually. Not what I was hoping for. In the process I realized that the default Node allocated for a symbol is a StackPane. I didn't need that flexibility so I replaced it with a Rectangle. This made rendering faster.
I'm late to the game, but maybe someone can use my solution. What worked for me, was iterating through every item in the data series and setting the CSS style for each one.
for (int index = 0; index < series.getData().size(); index++) {
XYChart.Data dataPoint = series.getData().get(index);
Node lineSymbol = dataPoint.getNode().lookup(".chart-line-symbol");
lineSymbol.setStyle("-fx-background-color: #00ff00, #000000; -fx-background-insets: 0, 2;\n" +
" -fx-background-radius: 3px;\n" +
" -fx-padding: 3px;");
}
I was stuck with a similar problem. I don't know upfront which data is going to be added to the graph, so I can't make use of a fixed stylesheet.
I came up with this solution. This code listens for new series added to graph. For every added series, it will create a new listener for data added to the series.
This listener will look up which series this is, the 0th, 1st, etc and then find the two nodes for the coloring of the line and of the legend/symbol.
As soon as it has set both, it can unsubscribe.
Problem can be that the legend/symbol node is not available yet when you receive the callback on the first added datapoint.
I'm aware it's very convoluted and I'm open to hear improvements.
At least it will give you the option to dynamically set the color to anything you want.
final LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(), new NumberAxis());
final ObservableList<Series<Number, Number>> series = chart.getData();
series.addListener(new ListChangeListener<Series<Number, Number>>() {
#Override
public void onChanged(Change<? extends Series<Number, Number>> change) {
ObservableList<? extends Series<Number, Number>> list = change.getList();
for (final Series<Number, Number> serie : list) {
serie.getData().addListener(new ListChangeListener<Data<Number, Number>>() {
#Override
public void onChanged(Change<? extends Data<Number, Number>> ignore) {
int index = series.indexOf(serie);
Set<Node> nodes = chart.lookupAll(".series" + index);
boolean isStyleSet = false;
for (Node n : nodes) {
if (StringUtils.isEmpty(n.getStyle())) {
String css = "-fx-stroke: %s; -fx-background-color: %s, white; ";
String color = //assign dynamically here, for instance based on the name of the series
n.setStyle(String.format(css, color, color));
isStyleSet = true;
}
}
if (!isStyleSet & nodes.size() > 1) {
serie.getData().removeListener(this);
}
}
});
}
}
});
I had a problem which might be slightly different (possibly more complex); I needed to style some nodes of a series one color, others within the same series another color (I also needed to be able to change the allocation of color dynamically). I am working in JavaFx 2.2; I have css-styling, but of course that does not help here. I could not find my issue addressed anywhere; this was the closest I've found.
I just want to say that I could not get "series.getNode().setStyle("-fx-stroke: " + color + ";")" to work. However, using "-fx-background" instead does work. I hope this helps someone.

How to assign a string id to UI elements.

I'm developing an app on android and I am generating UI elements in a loop. But I need these elements to have an id with letters and numbers, for example "rl1" or "rl2". I was trying to use the method RelativeLayout.setId() but, that method only accepts int. Is there a way I can set an ID as I want without being limited to numbers?
Thanks.
Here is the code I am trying to make work.
for (int i=1; i < 10; i++)
{
//gets the frameview where the elements will be created.
String LinearLayoutId = "frameview1";
int resID = getResources().getIdentifier(LinearLayoutId, "id", "com.myapp.ERS");
LinearLayout linearLayout = (LinearLayout)findViewById(resID);
//creates the RelativeLayout that will hold the ImageIcon and the TextView
RelativeLayout rl = new RelativeLayout(this);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,40 );
rl.setLayoutParams(lp);
rl.setId("rl"); /// >>>> I would like here to set and ID of "rl1" for example.
rl.setBackgroundDrawable(getResources().getDrawable(R.drawable.bk36));
//creates the image icon within the layout at the left side
ImageView image = new ImageView(this);
lp = new RelativeLayout.LayoutParams(
40,RelativeLayout.LayoutParams.MATCH_PARENT );
image.setLayoutParams(lp);
String imageicon = "icon_"+i;
resID = getResources().getIdentifier(imageicon, "drawable", "com.myapp.ERS");
image.setImageDrawable(getResources().getDrawable(resID)); //sets the icon
rl.addView(image); //adds the ImageView to the relative layout
//creates the TextView within the layout with a 40 margin to the left
TextView tv = new TextView(this);
lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT );
lp.setMargins(40, 0, 0, 0);
tv.setLayoutParams(lp);
String textViewID = "tv"+i;
resID = getResources().getIdentifier(textViewID, "string", "com.myapp.ERS");
tv.setText(getResources().getString(resID));
tv.setTextColor(Color.BLACK);
tv.setTextSize(25);
rl.addView(tv);//adds the TextView to the relative layout
rl.setOnClickListener(mAddListener);
linearLayout.addView(rl);//adds the RelativeLayout to the LinearLayout
}
and then I have the OnCLickListener like this...
private OnClickListener mAddListener = new OnClickListener()
{
public void onClick(View v){
Intent intent;
Bundle bundle;
String id = getResources().getResourceEntryName(v.getId());
id = id.replaceAll("\\D+","");
int value = Integer.parseInt(id);
intent = new Intent(ERS.this, ShowInfo.class);
bundle = new Bundle();
bundle.putInt("key", value);
System.out.println(v.getId());
intent.putExtras(bundle);
startActivity(intent);
}
};
I have tried to set up numeric IDs, but then when I Look for them with:
String id = getResources().getResourceEntryName(v.getId());
It can't find them.
I had all of this in an xml file to begin with, but it was really long because there are about forty items in the list, and it was complicated for me to go and change a letter for example in all of them. I came up with this idea to generate them at runtime in a for loop. I am testing in the meantime with ten, but I can't get it to work.
If I am doing something incorrect, then pardon me, but I am new to this.
You may still find it easier to go back to XML layouts and use the R class to generate meaningful IDs. Although as you haven't included the original xml file you refer to at the end of the question, so I can only guess at the problem you had with it. It does seem to fit the bill though, and would allow you to create something along the lines of:
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="#+id/hellotextview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Hi there"/>
The android:id="#+id/hellotextview" generates an id that can be used elsewhere in your project. In your java code you could access that specific TextView with something similar to:
TextView helloText = (TextView) findViewById(R.id.hellotextview);
The R.id.hellotextview is a int automatically generated when the project is built (in gen/R.java), but as you get to pick the name you can assign them something relevant to you and your project. So instead of trying to use strings values such as "rl1" and "rl2" that you mentioned, you could use R.id.rl1 and R.id.rl2.
As well as individual UI elements, you can also use the same technique for strings (in res/values/strings.xml), and other resources stored under the project's res/ folder, such as icons, media files, etc. In the case of strings you would access them getString(R.string.some_name_given_by_you);
See Accessing Resources at the Android Developers site for more info.
Why dont you try using SharedPreferences as an alternative in case you want to access the elements which you give some ID elsewhere in some other activity.

Resources