I do my first project with Spring boot and I use Mustache. So, I have a problem with it. When I try to start my application my page with database looks like this:
[{"dietaId":1,"nazwa":"Antycellulitowa","opis":"Na początku chcielibyśmy omówić podstawowe zasady omawianego tutaj programu żywieniowego. Przede wszystkim, dobrze jest jeść mało, lecz często. Niezwykle istotne jest także regularne przyjmowanie posiłków i nie omijanie żadnego z nich (szczególnie śniadań, które powinny dostarczać nam niezbędnej energii na resztę dnia). Dieta antycellulitowa powinna być odpowiednio zbilansowana i bogata w nieprzetworzone, świeże produkty (zwłaszcza warzywa i owoce). Najlepiej unikać jest potraw smażonych i duszonych w tłustych lub śmietanowych sosach. Zamiast tego, dobrze jest przygotowywać posiłki poprzez gotowanie na parze lub pieczenie.\r\n\r\nNiezwykle istotnym zaleceniem diety antycellulitowej jest rezygnacja lub znaczne ograniczenie soli, gdyż zatrzymuje ona w naszym organizmie wodę i toksyny. Zamiast tej przyprawy, możemy spokojnie sięgać po świeże zioła, czosnek, cebulę, bazylię, estragon, oregano itp. Nasze menu powinno składać się z chudego mięsa, drobiu, ryb oraz nabiału. Możemy także jak najczęściej sięgać po cytrusy, które wspomagają odtwarzanie wpływających na poprawę wyglądu skóry włókien kolagenu. Polecamy zapoznanie się z artykułem dotyczącym diety grapefruitowej, która jest jednym z najbardziej skutecznych programów żywieniowych wspomagających walkę ze skórką pomarańczową. Podczas walki z cellulitem świetnie sprawdzają się także działające przeciwobrzękowo produkty bogate w potas, w tym sałata, pomidory i ziemniaki. Warto sięgać również po witaminę B, którą znajdziemy w jajach, drożdżach i kiełkach zbóż. Szczególnie ważne w walce ze skórką pomarańczową są produkty zawierające kwasy tłuszczowe omega (np. oleje roślinne, ryby, orzechy, oliwa) – usprawniają one metabolizm i spalanie tkanek tłuszczowych.\r\n\r\nChcąc pozbyć się cellulitu, nie możemy zapominać o piciu co najmniej 2 litrów mineralnej wody o niskiej zawartości sodu. Wspomaga ona wydalanie z organizmu wszelkich ubocznych produktów przemiany materii, które to przyczyniają się do nasilenia efektu skórki pomarańczowej. Oprócz wody, dobrze jest pić także czerwoną i zieloną herbatę (usprawnia metabolizm) oraz napary z ziół. Zalecane są również wszystkie produkty działające moczopędnie a wiec: arbuz, pietruszka, seler, czereśnie, truskawki.\r\n\r\nPodczas stosowania diety antycellulitowej, należy unikać potraw tłustych i mocno przyprawionych (w tym popularnych w dzisiejszych czasach dań typu fast food). Zawierają one dużo soli i wysoko przetworzonych produktów, które to są odradzane w każdym odpowiednio zbilansowanym programie żywieniowym. Dobrze jest także ograniczyć słodycze i alkohol. Od czasu do czasu można oczywiście sięgnąć po lampkę czerwonego wina lub drink na bazie świeżo wyciśniętego soku, lecz lepiej unikać wysokoprocentowych trunków. Jeżeli mamy ochotę na cos słodkiego, najlepiej jest wybrać gorzką czekoladę o wysokiej zawartości kakao. Unikajmy jednak cukru w czystej postaci, mlecznych deserów a także słodzonych serków. Dobrze jest także ograniczyć lub zupełnie wyeliminować z menu czerwone mięso, tłusty ser żółty, kawę oraz wędliny. Z naszego jadłospisu należy definitywnie wykreślić słodkie napoje gazowane.\r\n\r\nJak w jednym zdaniu można scharakteryzować dietę antycellulitową? Jest to przede wszystkim zdrowy i lekki program żywieniowy. Niezwykle istotny jest też fakt, że korzyści z jego stosowania mogą być różnorodne – nie tylko znacznie zredukujemy uporczywą skórkę pomarańczową, lecz dodatkowo możemy poprawić wygląd naszej sylwetki i stan skóry. Pamiętajmy jednak, że dieta będzie skuteczna tylko i wyłącznie wtedy, jeśli nie potraktujemy jej jako metody doraźnej, lecz jako sposób odżywiania, który warto stosować przez resztę naszego życia."},
My controller DietaController.class:
#RestController
public class DietaController {
#Autowired
private DietaRepository dietaRepository;
#GetMapping("/dieta")
public List<Dieta> getAllNotes() {
return dietaRepository.findAll();
}
}
Code of My html page Dieta.html:
<!DOCTYPE HTML>
<html lang="pl">
<head>
<title>Diety</title>
<style>
table {
border-collapse: collapse;
}
table, td, th {
border: 1px solid #999;
padding: 5px;
}
body {background-color: #ffffff;}
h1 {
font-size: 250%;
color:#d52440;
}
p {
font-size: 150%;
}
</style>
</head>
<body>
<h1>Diety</h1>
<table style="width:100%">
<tr>
<th>Numer</th>
<th>Nazwa</th>
<th>Opis</th>
</tr>
{{#diety}}
<tr>
<td>{{dietaId}}</td>
<td>{{nazwa}}</td>
<td>{{opis}}</td>
</tr>
{{/diety}}
</table>
</body>
</html>
My entity Dieta.class:
#Entity
#Table(name = "diety")
public class Dieta {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
#Column(name="DIETA_ID") private int dietaId;
#NotEmpty
#Column(unique=true, name ="DIETA_NAZWA")
private String nazwa;
#NotEmpty
#Column(name="OPIS") private String opis;
public Dieta(){ }
public Dieta (int dietaId,String nazwa, String opis )
{ this.dietaId = dietaId;
this.nazwa = nazwa;
this.opis = opis; }
public int getDietaId() {
return dietaId; }
public void setDietaId(int dietaId) {
this.dietaId = dietaId; }
public String getNazwa() {
return nazwa; }
public void setNazwa(String nazwa) {
this.nazwa = nazwa; }
public String getOpis() {
return opis; }
public void setOpis(String opis) {
this.opis = opis; }
}
What did I write wrong? Or do I have to add something?
import org.springframework.web.servlet.ModelAndView;
...
#Controller
public class DietaController {
#Autowired
private DietaRepository dietaRepository;
#GetMapping("/dieta")
public ModelAndView getAllNotes() {
List<Diet> diets = dietaRepository.findAll();
Map<String, Object> params = new HashMap<>();
params.put("diety", diets);
return new ModelAndView("Dieta", params); // html's name
}
}
You aren't actually using your mustache template, somewhere in controller you have to specified it.
The result you're getting is exactly what dietaRepository.findAll(); returns.
Also try to find some simple Spring/Mustache examples on public git repositories or blogs, because RestController isn't supposed to return rendered templates but rather json to be reused from other services/applications.
Related
I downloaded mediapipe for android and inside it are android module files mediapipe_repo\mediapipe\mediapipe\examples\android\solutions\hands.
In the 'hands' of mediapipe-solution-example.
enter image description here
This is a question about MainActivity.
Because I want to put the screen horizontally, I want to rotate the camera preview screen like rotating the image through the rotateBitmap function But I don't know how.
enter image description here
I really want to cry..
The following is the MainActivity with the video-related code removed from the original MainActivity.
package com.google.mediapipe.examples.hands;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import com.google.mediapipe.formats.proto.LandmarkProto.Landmark;
import com.google.mediapipe.formats.proto.LandmarkProto.NormalizedLandmark;
import com.google.mediapipe.solutioncore.CameraInput;
import com.google.mediapipe.solutioncore.SolutionGlSurfaceView;
import com.google.mediapipe.solutioncore.VideoInput;
import com.google.mediapipe.solutions.hands.HandLandmark;
import com.google.mediapipe.solutions.hands.Hands;
import com.google.mediapipe.solutions.hands.HandsOptions;
import com.google.mediapipe.solutions.hands.HandsResult;
import java.io.IOException;
import java.io.InputStream;
/** Main activity of MediaPipe Hands app. */
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Hands hands;
// Run the pipeline and the model inference on GPU or CPU.
private static final boolean RUN_ON_GPU = true;
private enum InputSource {
UNKNOWN,
IMAGE,
CAMERA,
}
private InputSource inputSource = InputSource.UNKNOWN;
// Image demo UI and image loader components.
private ActivityResultLauncher<Intent> imageGetter;
private HandsResultImageView imageView;
// Live camera demo UI and camera components.
private CameraInput cameraInput;
private SolutionGlSurfaceView<HandsResult> glSurfaceView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupStaticImageDemoUiComponents();
//Live camera
setupLiveDemoUiComponents();
}
#Override
protected void onResume() {
super.onResume();
if (inputSource == InputSource.CAMERA) {
// Restarts the camera and the opengl surface rendering.
cameraInput = new CameraInput(this);
cameraInput.setNewFrameListener(textureFrame -> hands.send(textureFrame));
glSurfaceView.post(this::startCamera);
glSurfaceView.setVisibility(View.VISIBLE);
}
}
#Override
protected void onPause() {
super.onPause();
if (inputSource == InputSource.CAMERA) {
glSurfaceView.setVisibility(View.GONE);
cameraInput.close();
}
}
private Bitmap downscaleBitmap(Bitmap originalBitmap) {
double aspectRatio = (double) originalBitmap.getWidth() / originalBitmap.getHeight();
int width = imageView.getWidth();
int height = imageView.getHeight();
if (((double) imageView.getWidth() / imageView.getHeight()) > aspectRatio) {
width = (int) (height * aspectRatio);
} else {
height = (int) (width / aspectRatio);
}
return Bitmap.createScaledBitmap(originalBitmap, width, height, false);
}
#RequiresApi(api = Build.VERSION_CODES.N)
private Bitmap rotateBitmap(Bitmap inputBitmap, InputStream imageData) throws IOException {
int orientation =
new ExifInterface(imageData)
.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
if (orientation == ExifInterface.ORIENTATION_NORMAL) {
return inputBitmap;
}
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.postRotate(270);
break;
default:
matrix.postRotate(0);
}
return Bitmap.createBitmap(
inputBitmap, 0, 0, inputBitmap.getWidth(), inputBitmap.getHeight(), matrix, true);
}
/** Sets up the UI components for the static image demo. */
private void setupStaticImageDemoUiComponents() {
// The Intent to access gallery and read images as bitmap.
imageGetter =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
Intent resultIntent = result.getData();
if (resultIntent != null) {
if (result.getResultCode() == RESULT_OK) {
Bitmap bitmap = null;
try {
bitmap =
downscaleBitmap(
MediaStore.Images.Media.getBitmap(
this.getContentResolver(), resultIntent.getData()));
} catch (IOException e) {
Log.e(TAG, "Bitmap reading error:" + e);
}
try {
InputStream imageData =
this.getContentResolver().openInputStream(resultIntent.getData());
bitmap = rotateBitmap(bitmap, imageData);
} catch (IOException e) {
Log.e(TAG, "Bitmap rotation error:" + e);
}
if (bitmap != null) {
hands.send(bitmap);
}
}
}
});
Button loadImageButton = findViewById(R.id.button_load_picture);
loadImageButton.setOnClickListener(
v -> {
if (inputSource != InputSource.IMAGE) {
stopCurrentPipeline();
setupStaticImageModePipeline();
}
// Reads images from gallery.
Intent pickImageIntent = new Intent(Intent.ACTION_PICK);
pickImageIntent.setDataAndType(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*");
imageGetter.launch(pickImageIntent);
});
imageView = new HandsResultImageView(this);
}
/** Sets up core workflow for static image mode. */
private void setupStaticImageModePipeline() {
this.inputSource = InputSource.IMAGE;
// Initializes a new MediaPipe Hands solution instance in the static image mode.
hands =
new Hands(
this,
HandsOptions.builder()
.setStaticImageMode(true)
.setMaxNumHands(2)
.setRunOnGpu(RUN_ON_GPU)
.build());
// Connects MediaPipe Hands solution to the user-defined HandsResultImageView.
hands.setResultListener(
handsResult -> {
logWristLandmark(handsResult, /*showPixelValues=*/ true);
imageView.setHandsResult(handsResult);
runOnUiThread(() -> imageView.update());
});
hands.setErrorListener((message, e) -> Log.e(TAG, "MediaPipe Hands error:" + message));
// Updates the preview layout.
FrameLayout frameLayout = findViewById(R.id.preview_display_layout);
frameLayout.removeAllViewsInLayout();
imageView.setImageDrawable(null);
frameLayout.addView(imageView);
imageView.setVisibility(View.VISIBLE);
}
/** Sets up the UI components for the live demo with camera input. */
private void setupLiveDemoUiComponents() {
Button startCameraButton = findViewById(R.id.button_start_camera);
startCameraButton.setOnClickListener(
v -> {
if (inputSource == InputSource.CAMERA) {
return;
}
stopCurrentPipeline();
setupStreamingModePipeline(InputSource.CAMERA);
});
}
/** Sets up core workflow for streaming mode. */
private void setupStreamingModePipeline(InputSource inputSource) {
this.inputSource = inputSource;
// Initializes a new MediaPipe Hands solution instance in the streaming mode.
hands =
new Hands(
this,
HandsOptions.builder()
.setStaticImageMode(false)
.setMaxNumHands(2)
.setRunOnGpu(RUN_ON_GPU)
.build());
hands.setErrorListener((message, e) -> Log.e(TAG, "MediaPipe Hands error:" + message));
if (inputSource == InputSource.CAMERA) {
cameraInput = new CameraInput(this);
cameraInput.setNewFrameListener(textureFrame -> hands.send(textureFrame));
}
// Initializes a new Gl surface view with a user-defined HandsResultGlRenderer.
glSurfaceView =
new SolutionGlSurfaceView<>(this, hands.getGlContext(), hands.getGlMajorVersion());
glSurfaceView.setSolutionResultRenderer(new HandsResultGlRenderer());
glSurfaceView.setRenderInputImage(true);
hands.setResultListener(
handsResult -> {
logWristLandmark(handsResult, /*showPixelValues=*/ false);
glSurfaceView.setRenderData(handsResult);
glSurfaceView.requestRender();
});
// The runnable to start camera after the gl surface view is attached.
// For video input source, videoInput.start() will be called when the video uri is available.
if (inputSource == InputSource.CAMERA) {
glSurfaceView.post(this::startCamera);
}
// Updates the preview layout.
FrameLayout frameLayout = findViewById(R.id.preview_display_layout);
imageView.setVisibility(View.GONE);
frameLayout.removeAllViewsInLayout();
frameLayout.addView(glSurfaceView);
glSurfaceView.setVisibility(View.VISIBLE);
frameLayout.requestLayout();
}
private void startCamera() {
cameraInput.start(
this,
hands.getGlContext(),
CameraInput.CameraFacing.FRONT,
glSurfaceView.getWidth(),
glSurfaceView.getHeight());
}
private void stopCurrentPipeline() {
if (cameraInput != null) {
cameraInput.setNewFrameListener(null);
cameraInput.close();
}
if (glSurfaceView != null) {
glSurfaceView.setVisibility(View.GONE);
}
if (hands != null) {
hands.close();
}
}
private void logWristLandmark(HandsResult result, boolean showPixelValues) {
if (result.multiHandLandmarks().isEmpty()) {
return;
}
NormalizedLandmark wristLandmark =
result.multiHandLandmarks().get(0).getLandmarkList().get(HandLandmark.WRIST);
// For Bitmaps, show the pixel values. For texture inputs, show the normalized coordinates.
if (showPixelValues) {
int width = result.inputBitmap().getWidth();
int height = result.inputBitmap().getHeight();
Log.i(
TAG,
String.format(
"MediaPipe Hand wrist coordinates (pixel values): x=%f, y=%f",
wristLandmark.getX() * width, wristLandmark.getY() * height));
} else {
Log.i(
TAG,
String.format(
"MediaPipe Hand wrist normalized coordinates (value range: [0, 1]): x=%f, y=%f",
wristLandmark.getX(), wristLandmark.getY()));
}
if (result.multiHandWorldLandmarks().isEmpty()) {
return;
}
Landmark wristWorldLandmark =
result.multiHandWorldLandmarks().get(0).getLandmarkList().get(HandLandmark.WRIST);
Log.i(
TAG,
String.format(
"MediaPipe Hand wrist world coordinates (in meters with the origin at the hand's"
+ " approximate geometric center): x=%f m, y=%f m, z=%f m",
wristWorldLandmark.getX(), wristWorldLandmark.getY(), wristWorldLandmark.getZ()));
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/buttonBarStyle" android:gravity="center"
android:orientation="horizontal">
<Button
android:id="#+id/button_load_picture"
android:layout_width="wrap_content"
style="?android:attr/buttonBarButtonStyle" android:layout_height="wrap_content"
android:text="#string/load_picture" />
<Button
android:id="#+id/button_start_camera"
android:layout_width="wrap_content"
style="?android:attr/buttonBarButtonStyle" android:layout_height="wrap_content"
android:text="#string/start_camera" />
</LinearLayout>
<FrameLayout
android:id="#+id/preview_display_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
I expect how to rotate camera input in 'hands' of 'mediapipe-solutions-examples'
I get this error just once in a while when libgdx ui renders:
09-25 17:50:26.779 31171-32670/se.company.app.android E/AndroidRuntime﹕ FATAL EXCEPTION: GLThread 1126
Process: se.company.app.android, PID: 31171
java.lang.IndexOutOfBoundsException: index can't be >= size: 36 >= 36
at com.badlogic.gdx.utils.FloatArray.get(FloatArray.java:104)
at com.badlogic.gdx.scenes.scene2d.ui.TextField.calculateOffsets(TextField.java:214)
at com.badlogic.gdx.scenes.scene2d.ui.TextArea.calculateOffsets(TextArea.java:266)
at com.badlogic.gdx.scenes.scene2d.ui.TextField.draw(TextField.java:294)
at com.badlogic.gdx.scenes.scene2d.Group.drawChildren(Group.java:123)
at com.badlogic.gdx.scenes.scene2d.Group.draw(Group.java:57)
at com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup.draw(WidgetGroup.java:154)
at com.badlogic.gdx.scenes.scene2d.ui.Table.draw(Table.java:117)
at com.badlogic.gdx.scenes.scene2d.Group.drawChildren(Group.java:110)
at com.badlogic.gdx.scenes.scene2d.Group.draw(Group.java:57)
at com.badlogic.gdx.scenes.scene2d.Stage.draw(Stage.java:128)
at se.company.app.screens.AbstractScreen.render(AbstractScreen.java:36)
at se.company.app.screens.InstructionsScreen.render(InstructionsScreen.java:80)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:422)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)
09-25 17:50:30.823 31171-31171/se.company.app.android E/AndroidGraphics﹕ waiting for pause synchronization took too long; assuming deadlock and killing
09-25 17:50:30.833 31171-31171/se.company.app.android I/Process﹕ Sending signal. PID: 31171 SIG: 9
I can't figure out what it is about. Threading issue? But what? When I set text I do it with Gdx.app.postRunnable().
I have classes:
public class InstructionsScreen extends AbstractScreen {
private InputProcessor inputProcessor = new InputAdapter() {
#Override
public boolean keyDown(int keycode) {
if ((keycode == Input.Keys.ESCAPE) || (keycode == Input.Keys.BACK) ) {
game.setScreen(new BeginGameOptionsScreen(game, resources));
}
return false;
}
};
private Table table;
private ScrollPane resultsTextAreaScrollPane;
private TextArea resultsTextArea;
private TextArea textArea;
private float maxX,maxY,maxZ;
private Sound sound;
private long timer=0;
public InstructionsScreen(GameClass game, Resources resources) {
super(game, resources);
}
#Override
public void resize(int width, int height) {
addInputProcessor(inputProcessor);
table = new Table();
table.setFillParent(true);
stage.addActor(table);
TextArea resultsTextAreaBool;
resultsTextAreaBool = new TextArea("", resources.getSkin());
resultsTextAreaBool.setDisabled(true);
resultsTextAreaBool.setText(String.valueOf(Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer)));
table.add(resultsTextAreaBool).width(GraphicUtils.widthOfScreen(90)).height(GraphicUtils.heightOfScreen(20)).pad(GraphicUtils.onePercentHeight, GraphicUtils.onePercentWidth, GraphicUtils.onePercentHeight, GraphicUtils.onePercentWidth);
table.row();
resultsTextArea = new TextArea("", resources.getSkin());
resultsTextArea.setDisabled(true);
resultsTextArea.setText("");
table.add(resultsTextArea).width(GraphicUtils.widthOfScreen(90)).height(GraphicUtils.heightOfScreen(40)).pad(GraphicUtils.onePercentHeight, GraphicUtils.onePercentWidth, GraphicUtils.onePercentHeight, GraphicUtils.onePercentWidth);
table.row();
sound=resources.getRobotBlip();
}
#Override
public void render(float delta) {
super.render(delta);
float accelX = Gdx.input.getAccelerometerX();
float accelY = Gdx.input.getAccelerometerY();
float accelZ = Gdx.input.getAccelerometerZ();
if(accelX>maxX)
maxX=accelX;
if(accelY>maxY)
maxY=accelY;
if(accelZ>maxZ)
maxZ=accelZ;
if(Math.abs(maxX)>19f) {
timer++;
}
if(timer==1) {
sound.play();
}
if(timer>20) {
timer=0;
maxX=0;
}
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
resultsTextArea.setText("x=" + String.valueOf(maxX) + "\ny=" + String.valueOf(maxY) + "\nz=" + String.valueOf(maxZ));
}
});
}
}
Problem seems to arise because of newlines "\n" in String above.
I use FreeTypeFontGenerator for font creation on the fly:
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("data/fonts/anonymous-pro/Anonymous_Pro.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter freeTypeFontParameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
freeTypeFontParameter.borderColor = Color.BLACK;
freeTypeFontParameter.borderWidth = 1;
freeTypeFontParameter.size = (int)(Gdx.graphics.getWidth()/25.0f);
anonymous_pro = generator.generateFont(freeTypeFontParameter);
generator.dispose();
Which I add with:
TextField.TextFieldStyle textFieldStyle=skin.get("default", TextField.TextFieldStyle.class);
textFieldStyle.font=anonymous_pro;
skin.add("default", textFieldStyle);
And retrieve with:
resultsTextArea = new TextArea("", resources.getSkin()); //Resources is my own class
I hope you'll excuse me for bumping this old issue, especially when there's already an answer. This page is one of very few references on Google to the subject matter and I found a different solution.
In short, I had to open up the .fnt file that I was using and remove the references to glyphs 0 and 10. I know you're using FreeTypeFontGenerator, but I suspect it's generating Glyph sizes for character codes 0 and 10, too. For the folks using Hiero or another generator, you can edit the .fnt file and change the following lines:
chars count=98
char id=0 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=9 page=0 chnl=0
char id=10 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=0 page=0 chnl=0
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=9 page=0 chnl=0
To
chars count=96
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=9 page=0 chnl=0
Note that id=0 and id=10 are gone and the count is updated.
This GitHub issue appears to address the root of the problem: https://github.com/libgdx/libgdx/issues/4570
I have a div holding some chat history. I would like for the div content to scroll when it becomes full. I have this working using jQuery in another project, but what would be the proper AngularDart way to achieve this?
Simplifying a bit, in my HTML I have
<div class="chatHistory">{{ctrl.text}}</div>
(using style white-space:pre) and in my controller I have the method
void addToChatHistory(String msg) {
text += msg;
var elt = querySelector(".chatHistory");
elt.scrollTop = elt.scrollHeight;
}
Issues:
This code scrolls the div content but not quite enough because it sets the scrollTop too quickly; i.e., even before the .chatHistory can be updated by Angular.
Besides this (partial) solution doesn't feel very Angular in style given the use of querySelector.
I tried setting up a watch on the text field but that also fires too early. Suggestions?
For the first issue you can use Timer.run to defer the scroll execution :
Timer.run(() => elt.scrollTop = elt.scrollHeight);
For the second issue you can inject the Element managed by your controller and use querySelector on it :
MyController(Element e) : elt = e.querySelector('.chatHistory');
EDIT
I published a package containing this directive: http://pub.dartlang.org/packages/bwu_angular
-------
I would create a Directive/Decorator like NgEventDirective but for the resize event and add it to your div. In the event handler you set your scrollTop property.
I found contradictory info about the resize event.
DART - Resize div element event says it is available everywhere
Onresize for div elements? is a workaround for browsers that don't support this event.
another page covering this topic: http://marcj.github.io/css-element-queries/
I tried to create an Angular implementation for the 'workaround' (2nd link) but run into this issue https://code.google.com/p/dart/issues/detail?id=18062 which contains info about a workaround but I didn't yet find time to implement it.
EDIT
I checked my attempt and it worked in Dartium with the version I downloaded today (Dart VM version: 1.4.0-dev.4.0 (Thu May 1 04:06:09 2014) on "linux_x64").
I haven't tried in other version since I created the issue.
(The code should be improved to make the directive more generic - the event method should be assignable by an attribute not hardcoded)
index.html
<!DOCTYPE html>
<html ng-app>
<head>
<script src="packages/web_components/platform.js"></script>
<style>
.resize-triggers {
visibility: hidden;
}
.resize-triggers, .resize-triggers > div, .contract-trigger:before {
content: " ";
display: block;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
.resize-triggers > div {
background: #eee;
overflow: auto;
}
.contract-trigger:before {
width: 200%;
height: 200%;
}
</style>
<style>
#my_element {
height: 200px;
overflow: scroll;
}
</style>
</head>
<body ng-cloak>
<div>
<div id="my_element" style="border: 1px solid blue;">
<div id='my_sizable' ng-observe-size></div>
</div>
</div>
<script type="application/dart" src="index.dart"></script>
<script type="text/javascript" src="packages/browser/dart.js"></script>
</body>
</html>
index.dart
library angular_observe_resize.main;
import 'dart:async' as async;
import 'dart:html' as dom;
import 'package:angular/angular.dart' as ng;
import 'package:angular/application_factory.dart' as ngaf;
// see https://stackoverflow.com/questions/19329530
// and this bug https://code.google.com/p/dart/issues/detail?id=18062
// source from http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/
#ng.Decorator(selector: '[ng-observe-size]')
class NgObserveSizeDirective implements ng.AttachAware, ng.DetachAware {
dom.Element _element;
bool _hasAttacheEvent;
NgObserveSizeDirective(this._element);
void onSizeChange(dom.Event e) {
_element.parent.scrollTop = _element.scrollHeight;
}
dom.HtmlElement _triggers;
void resetTriggers() {
var expand = _triggers.children[0];
var contract = _triggers.children[_triggers.children.length - 1];
var expandChild = expand.children[0];
contract.scrollLeft = contract.scrollWidth;
contract.scrollTop = contract.scrollHeight;
expandChild.style.width = '${expand.offsetWidth + 1}px';
expandChild.style.height = '${expand.offsetHeight + 1}px';
expand.scrollLeft = expand.scrollWidth;
expand.scrollTop = expand.scrollHeight;
}
int _resizeLastWidth;
int _resizeLastHeight;
bool checkTriggers() {
return _element.offsetWidth != _resizeLastWidth ||
_element.offsetHeight != _resizeLastHeight;
}
int _resizeRaf;
void scrollListener(dom.Event e) {
resetTriggers();
if(_resizeRaf != null) {
dom.window.cancelAnimationFrame(_resizeRaf);
}
_resizeRaf = dom.window.requestAnimationFrame((num highResTime){
if(checkTriggers()) {
_resizeLastWidth = _element.offsetWidth;
_resizeLastHeight = _element.offsetHeight;
onSizeChange(e);
}
});
}
#override
void attach() {
if(_element.getComputedStyle().position == 'static') {
_element.style.position = 'relative';
}
_triggers = new dom.DivElement()
..classes.add('resize-triggers')
..append(new dom.DivElement()..classes.add('expand-trigger')..append(new dom.DivElement()))
..append(new dom.DivElement()..classes.add('contract-trigger'));
_element.append(_triggers);
new async.Future.delayed(new Duration(seconds: 1), () {
//_triggers = _element.children[_element.children.length - 1];
resetTriggers();
dom.Element.scrollEvent.forTarget(_element, useCapture: true).listen(scrollListener);
});
}
#override
void detach() {
_triggers.remove();
}
}
class MyAppModule extends ng.Module {
MyAppModule() {
type(NgObserveSizeDirective);
}
}
main() {
print('main');
ngaf.applicationFactory().addModule(new MyAppModule()).run();
new async.Timer.periodic(new Duration(seconds: 1), (t) {
var elt = (dom.querySelector('#my_sizable') as dom.HtmlElement);
elt.append(new dom.Element.html('<div>${new DateTime.now()}</div>'));
});
}
If you're using an AngularDart component you can inject the shadowdom then select an element inside it to focus on. Didnt find a way of getting the container of the shadowdom.
new Future.delayed(new Duration(milliseconds: 300), () {
var rowElement = _shadowRoot.querySelector('.step-container');
if (rowElement != null ) {
rowElement.scrollIntoView(ScrollAlignment.TOP);
}
});
ShadowDom.host might work, though its currently marked as experimental.
My current app is using .NET MVC3 with EF 4.1 Code First and an Oracle back end. Everything works fine practically all the time except in one scenario, which is where we have a View that displays multiple images. Sometimes all images are loaded fine, other times some of them fail to load and I get one of 2 error messages - "The connection was not closed" or "Connection must be opened". The image are stored in the db as BLOBs and not on the server's file system.
I have a view model containing a collection of Documents (which are images) and use an EditorTemplate to render the collection in the View. The rendered code makes a call to a Controller action to retrieve each image in the collection. Here's the Razor code that renders the collection:
Parent View:
<div id="carousel1" class="data-carousel">
#Html.EditorFor(x => x.Documents)
</div>
Editor template:
<div>
<img style="border: solid; border-color: lightgrey; border-width: thin" src="#Url.Action("GetImage", "Product", new {docId = Model.DocumentID, width = 250, height = 250})" alt=""/>
</div>
so this code gets written to the browser
<img style="border: solid; border-color: lightgrey; border-width: thin" src="http://localhost:9613/Product/GetImage?docId=1&width=250&height=250" alt=""/>
<img style="border: solid; border-color: lightgrey; border-width: thin" src="http://localhost:9613/Product/GetImage?docId=2&width=250&height=250" alt=""/>
<img style="border: solid; border-color: lightgrey; border-width: thin" src="http://localhost:9613/Product/GetImage?docId=3&width=250&height=250" alt=""/>
<img style="border: solid; border-color: lightgrey; border-width: thin" src="http://localhost:9613/Product/GetImage?docId=4&width=250&height=250" alt=""/>
As you can see this creates a link that passes some params including the id to an action method which returns the image as a byte array:
public void GetImage(int docId, int width, int height)
{
// Load image from database
var doc = productRepository.Documents.SingleOrDefault(f => f.DocumentID == docId);
var image = doc.FileContent;
new WebImage(image)
.Resize(width, height, true, true)
.Crop(1, 1)
.Write();
}
I'm pretty sure what's happening is that the Controller action is being called for each image (potentially up to 10), and the db connection isn't closed before the next request comes in. I tried creating a method on the repository that creates a new instance of the Context in a "using" statement to see if this would improve things but it didn't.
So is there anything I can do? Should I be looking at the new async maybe, or is there some other pattern I can use to retrieve multiple images in a View?
TIA
EDIT:
The application is hosted in IIS7 with it's own application pool in Classic pipeline mode. I use StructureMap as an IoC container so this controls the creation and lifetime of the DbContext. The instantiation happens when the Controller gets instantiated:
SM setup:
public static class StructuremapMvc
{
public static void Start()
{
var container = (IContainer)IoC.Initialize();
DependencyResolver.SetResolver(new SmDependencyResolver(container));
}
}
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
x.For<IProductRepository>().Use<ProductRepository>();
x.For<IProductContext>().Use<ProductContext>();
});
return ObjectFactory.Container;
}
Controller:
public class ProductController : Controller
{
private readonly IProductRepository productRepository;
public ProductController(IProductRepository productRepository)
{
this.productRepository = productRepository;
}
public void GetImage(int docId, int width, int height)
{
// Load image from database
var doc = productRepository.Documents.SingleOrDefault(f => f.DocumentID == docId);
var image = doc.FileContent;
new WebImage(image)
.Resize(width, height, true, true)
.Crop(1, 1)
.Write();
}
// etc.
}
Repository:
public class ProductRepository : IProductRepository
{
private readonly IProductContext productContext;
public ProductRepository(IProductContext productContext)
{
productContext = productContext;
}
public IQueryable<Document> Documents
{
get { return productContext.Documents; }
}
// etc.
}
Context:
public class ProductContext : DbContext, IProductContext
{
// DbSets
public IDbSet<Document> Documents { get; set; }
public void SetModified(object entity)
{
Entry(entity).State = EntityState.Modified;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// etc.
}
// etc.
}
I have a sprite animation in my app and it's working fine for standard phone sized screens but whenever I put it on a tablet the animation gets glitchy and doesn't look right at all. I think it has something to do with the height and widths of the image. I've tried setting them as dp and sp but they still won't render right on the tablet.
Here's my animation xml
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingLeft="100dp" >
<view
android:id="#+id/animation"
android:layout_width="180dp"
android:layout_height="220dp"
class="com.scale.AndroidAnimation" />
</LinearLayout>
Here's my animation code
public class AndroidAnimation extends View{
private Bitmap mAnimation;
private Rect mSRectangle;
private int mNoOfFrames;
private int mCurrentFrame;
private int mSpriteHeight;
private int mSpriteWidth;
public AndroidAnimation(Context context, AttributeSet aSet) {
super(context, aSet);
mSRectangle = new Rect(0,0,0,0);
mCurrentFrame = 0;
}
public void init(Bitmap theBitmap, int Height, int Width, int theFrameCount) {
mAnimation = theBitmap;
mSpriteHeight = Height;
mSpriteWidth = Width;
mSRectangle.top = 0;
mSRectangle.bottom = mSpriteHeight;
mSRectangle.left = 0;
mSRectangle.right = mSpriteWidth;
mNoOfFrames = theFrameCount;
mCurrentFrame = 0;
}
public void update() {
mCurrentFrame++;
mCurrentFrame %= mNoOfFrames;
mSRectangle.left = mCurrentFrame * mSpriteWidth;
mSRectangle.right = mSRectangle.left + mSpriteWidth;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect dest = new Rect(0, 0, mSpriteWidth, mSpriteHeight);
canvas.drawBitmap(mAnimation, mSRectangle, dest, null);
}
}
Where I initialize it
anim = (AndroidAnimation) findViewById(R.id.animation);
anim.init(BitmapFactory.decodeResource(getResources(), R.drawable.connecting_sprite), 300, 170, 3);
mHandler.removeCallbacks(myTimerTask);
mHandler.postDelayed(myTimerTask, 300);
My handler that progresses it
public void run() {
mHandler.removeCallbacks(myTimerTask);
if (mCurrScreen == WAITING_SCREEN) {
mHandler.postDelayed(myTimerTask, 300);
}
anim.update();
anim.invalidate();
}
Thanks in advance!
It is good way to design seperate layout for tablet.Create layout-xlarge folder in res and put your new layout animation.xml file which is optimized for tablet screen.