0
0
mirror of https://github.com/ankidroid/Anki-Android.git synced 2024-09-20 12:02:16 +02:00

Merged Rick's font and display-related changes

This commit is contained in:
Nicolas Raoul 2010-05-09 23:51:44 +09:00
commit 6dd738ca26
6 changed files with 191 additions and 154 deletions

View File

@ -75,17 +75,19 @@
android:summary="@string/use_ruby_support_summ"
android:key="useRubySupport" />
<ListPreference
android:title="@string/qa_font_size"
android:summary="@string/qa_font_size_summ"
android:key="qaFontSize"
android:title="@string/display_font_size"
android:summary="@string/display_font_size_summ"
android:key="displayFontSize"
android:defaultValue="0"
android:entries="@array/qaFontSizeLabels"
android:entryValues="@array/qaFontSizeVals" />
<CheckBoxPreference
android:title="@string/show_question_answer"
android:defaultValue="false"
android:summary="@string/show_question_answer_summ"
android:key="showQuestionAnswer" />
android:entries="@array/displayFontSizeLabels"
android:entryValues="@array/displayFontSizeVals" />
<ListPreference
android:title="@string/hide_question_in_answer"
android:summary="@string/hide_question_in_answer_summ"
android:key="hideQuestionInAnswer"
android:defaultValue="0"
android:entries="@array/hideQuestionInAnswerLabels"
android:entryValues="@array/hideQuestionInAnswerVals" />
</PreferenceCategory>
<!-- TODO implement this preference. Right now: always use notifications

View File

@ -68,36 +68,49 @@
<item>4</item>
</string-array>
<!-- The values below match MIN_QA_FONT_SIZE and MAX_QA_FONT_SIZE in AnkiDroid.java.
This is a convenience, not at requirement -->
<string-array name="qaFontSizeLabels">
<item>Relative</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
<item>10</item>
<item>11</item>
<item>12</item>
<item>13</item>
<item>14</item>
<string-array name="displayFontSizeLabels">
<item>10 %</item>
<item>20 %</item>
<item>30 %</item>
<item>40 %</item>
<item>50 %</item>
<item>60 %</item>
<item>70 %</item>
<item>80 %</item>
<item>90 %</item>
<item>100 %</item>
<item>110 %</item>
<item>120 %</item>
<item>130 %</item>
<item>140 %</item>
<item>150 %</item>
</string-array>
<string-array name="qaFontSizeVals">
<item>0</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
<string-array name="displayFontSizeVals">
<item>10</item>
<item>11</item>
<item>12</item>
<item>13</item>
<item>14</item>
<item>20</item>
<item>30</item>
<item>40</item>
<item>50</item>
<item>60</item>
<item>70</item>
<item>80</item>
<item>90</item>
<item>100</item>
<item>110</item>
<item>120</item>
<item>130</item>
<item>140</item>
<item>150</item>
</string-array>
<string-array name="hideQuestionInAnswerLabels">
<item>Hide the question in answer</item>
<item>Show the question in answer</item>
<item>As defined in CardModel</item>
</string-array>
<string-array name="hideQuestionInAnswerVals">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>

View File

@ -78,7 +78,7 @@
<string name="overlay_on">Whiteboard On</string>
<string name="overlay_off">Whiteboard Off</string>
<string name="show_answer">Show Answer</string>
<string name="show_question">Show Question</string>
<string name="show_question">Re-display Question</string>
<string name="card_hint">Flashcard</string>
<string name="again">Again</string>
<string name="hard">Hard</string>
@ -105,10 +105,10 @@
<string name="write_answers_summ">Lets you write the answer and compare it with the correct one</string>
<string name="use_ruby_support">Provide ruby annotation support</string>
<string name="use_ruby_support_summ">If the characters '[' and ']' are found, then the enclosed text is handled as a ruby annotation</string>
<string name="qa_font_size">Font size</string>
<string name="qa_font_size_summ">Default font size. Using 'Relative' changes the font dynamically based on space</string>
<string name="show_question_answer">Show question in answer</string>
<string name="show_question_answer_summ">Shows the question also when displaying the answer unless user entered answer.</string>
<string name="display_font_size">Relative display font size</string>
<string name="display_font_size_summ">The font size to use in the display relative to the definitions in the deck</string>
<string name="hide_question_in_answer">Hide question in answer?</string>
<string name="hide_question_in_answer_summ">Determines whether the question should be hidden when the answer is shown.</string>
<string name="deck_path">Deck path</string>
<string name="deck_path_summ">Path to where the your decks are stored</string>

View File

@ -79,14 +79,14 @@ public class AnkiDroid extends Activity
*/
private static final String TAG = "AnkiDroid";
/** Max size of the font of the questions and answers for relative calculation */
protected static final int MAX_QA_FONT_SIZE = 14;
/** Max size of the font for dynamic calculation of font size */
protected static final int MAX_DYNAMIC_FONT_SIZE = 14;
/** Min size of the font of the questions and answers for relative calculation */
protected static final int MIN_QA_FONT_SIZE = 3;
/** Min size of the font for dynamic calculation of font size */
protected static final int MIN_DYNAMIC_FONT_SIZE = 3;
/** The font size specified in shared preferences. If 0 then font is calculated with MAX/MIN_FONT_SIZE */
private int qaFontSize = 0;
/** The percentage of the absolute font size specified in the deck. */
private int displayFontSize = 100;
/**
* Menus
@ -167,8 +167,14 @@ public class AnkiDroid extends Activity
/** Preference: parse for ruby annotations */
private boolean useRubySupport;
/** Preference: show the question when showing the answer */
private boolean showQuestionAnswer;
/** Preference: hide the question when showing the answer */
private int hideQuestionInAnswer;
private static final int HQIA_DO_HIDE = 0;
private static final int HQIA_DO_SHOW = 1;
private static final int HQIA_CARD_MODEL = 2;
private boolean updateNotifications; // TODO use Veecheck only if this is true
@ -680,15 +686,14 @@ public class AnkiDroid extends Activity
showOrHideControls();
showOrHideAnswerField();
}
} else if (requestCode == EDIT_CURRENT_CARD)
{
DeckTask.launchDeckTask(
DeckTask.TASK_TYPE_UPDATE_FACT,
mUpdateCardHandler,
new DeckTask.TaskData(0, AnkiDroidApp.getDeck(), currentCard));
//TODO: code to save the changes made to the current card.
} else if (requestCode == EDIT_CURRENT_CARD) {
if (CardEditor.SAVE_CARD == resultCode) {
DeckTask.launchDeckTask(DeckTask.TASK_TYPE_UPDATE_FACT,
mUpdateCardHandler, new DeckTask.TaskData(0, AnkiDroidApp
.getDeck(), currentCard));
mFlipCard.setChecked(true);
displayCardQuestion();
}
} else if(requestCode == GET_SHARED_DECK)
{
//Clean the previous card before showing the first of the new loaded deck (so the transition is not so abrupt)
@ -847,9 +852,15 @@ public class AnkiDroid extends Activity
mAnswerField.setVisibility(View.VISIBLE);
}
mFlipCard.setVisibility(View.VISIBLE);
mFlipCard.requestFocus();
updateCard(enrichWithQASpan(currentCard.question, false));
String displayString = enrichWithQASpan(currentCard.question, false);
//Depending on preferences do or do not show the question
if (calculateShowQuestion()) {
displayString = displayString + "<hr/>";
}
updateCard(displayString);
}
}
@ -871,6 +882,8 @@ public class AnkiDroid extends Activity
mAnswerField.setVisibility(View.GONE);
mEase2.requestFocus();
String displayString = "";
// If the user wrote an answer
if(writeAnswers)
@ -885,27 +898,40 @@ public class AnkiDroid extends Activity
// Obtain the diff and send it to updateCard
DiffEngine diff = new DiffEngine();
updateCard(enrichWithQASpan(diff.diff_prettyHtml(
displayString = enrichWithQASpan(diff.diff_prettyHtml(
diff.diff_main(userAnswer, correctAnswer)) +
"<br/>" + currentCard.answer, true));
"<br/>" + currentCard.answer, true);
}
else
{
updateCard("");
displayString = "";
}
}
else
{
if (true == showQuestionAnswer) {
displayString = enrichWithQASpan(currentCard.answer, true);
}
//Depending on preferences do or do not show the question
if (calculateShowQuestion()) {
StringBuffer sb = new StringBuffer();
sb.append(enrichWithQASpan(currentCard.question, false));
sb.append("<hr/>");
sb.append(enrichWithQASpan(currentCard.answer, true));
updateCard(sb.toString());
} else {
updateCard(enrichWithQASpan(currentCard.answer, true));
sb.append(displayString);
displayString = sb.toString();
mFlipCard.setVisibility(View.GONE);
}
updateCard(displayString);
}
private final boolean calculateShowQuestion() {
if (HQIA_DO_SHOW == hideQuestionInAnswer) {
return true;
}
if (HQIA_CARD_MODEL == hideQuestionInAnswer && 0 == Model.getModel(currentCard.cardModelId, false).getCardModel(currentCard.cardModelId).questionInAnswer) {
return true;
}
return false;
}
/**
@ -920,13 +946,6 @@ public class AnkiDroid extends Activity
content = Sound.extractSounds(deckFilename, content);
content = Image.loadImages(deckFilename, content);
// Calculate the size of the font if relative font size is chosen in preferences
int fontSize = qaFontSize;
if (0 == qaFontSize) {
fontSize = calculateDynamicFontSize(content);
}
mCard.getSettings().setDefaultFontSize(fontSize);
// In order to display the bold style correctly, we have to change font-weight to 700
content = content.replaceAll("font-weight:600;", "font-weight:700;");
@ -936,10 +955,11 @@ public class AnkiDroid extends Activity
}
// Add CSS for font colour and font size
if(currentCard != null)
{
if (null != currentCard) {
Model myModel = Model.getModel(currentCard.cardModelId, false);
content = myModel.getCSSForFontColorSize(currentCard.cardModelId) + content;
content = myModel.getCSSForFontColorSize(currentCard.cardModelId, displayFontSize) + content;
} else {
mCard.getSettings().setDefaultFontSize(calculateDynamicFontSize(content));
}
Log.i(TAG, "content card = \n" + content);
@ -948,26 +968,10 @@ public class AnkiDroid extends Activity
Sound.playSounds();
}
/**
* Calculates a dynamic font size depending on the length of the contents
* taking into account that the input string contains html-tags, which will not
* be displayed and therefore should not be taken into account.
* @param htmlContents
* @return font size respecting MIN_QA_FONT_SIZE and MAX_QA_FONT_SIZE
*/
protected final static int calculateDynamicFontSize(String htmlContent) {
// Replace each <br> with 15 spaces, each <hr> with 30 spaces, then remove all html tags and spaces
String realContent = htmlContent.replaceAll("\\<br.*?\\>", " ");
realContent = realContent.replaceAll("\\<hr.*?\\>", " ");
realContent = realContent.replaceAll("\\<.*?\\>", "");
realContent = realContent.replaceAll("&nbsp;", " ");
return Math.max(MIN_QA_FONT_SIZE, MAX_QA_FONT_SIZE - (int)(realContent.length()/5));
}
/** Constant for class attribute signalling answer */
/** Constant for class attribute signaling answer */
protected final static String ANSWER_CLASS = "answer";
/** Constant for class attribute signalling question */
/** Constant for class attribute signaling question */
protected final static String QUESTION_CLASS = "question";
/**
@ -990,6 +994,23 @@ public class AnkiDroid extends Activity
return sb.toString();
}
/**
* Calculates a dynamic font size depending on the length of the contents
* taking into account that the input string contains html-tags, which will not
* be displayed and therefore should not be taken into account.
* @param htmlContents
* @return font size respecting MIN_DYNAMIC_FONT_SIZE and MAX_DYNAMIC_FONT_SIZE
*/
protected final static int calculateDynamicFontSize(String htmlContent) {
// Replace each <br> with 15 spaces, each <hr> with 30 spaces, then remove all html tags and spaces
String realContent = htmlContent.replaceAll("\\<br.*?\\>", " ");
realContent = realContent.replaceAll("\\<hr.*?\\>", " ");
realContent = realContent.replaceAll("\\<.*?\\>", "");
realContent = realContent.replaceAll("&nbsp;", " ");
return Math.max(MIN_DYNAMIC_FONT_SIZE, MAX_DYNAMIC_FONT_SIZE - (int)(realContent.length()/5));
}
/**
* Utility method to write to a file.
*/
@ -1019,19 +1040,25 @@ public class AnkiDroid extends Activity
return true;
}
private SharedPreferences restorePreferences()
{
private SharedPreferences restorePreferences() {
SharedPreferences preferences = PrefSettings.getSharedPrefs(getBaseContext());
corporalPunishments = preferences.getBoolean("corporalPunishments", false);
timerAndWhiteboard = preferences.getBoolean("timerAndWhiteboard", true);
Log.i(TAG, "restorePreferences - timerAndWhiteboard: " + timerAndWhiteboard);
writeAnswers = preferences.getBoolean("writeAnswers", false);
useRubySupport = preferences.getBoolean("useRubySupport", false);
//A little hack to get int values from ListPreference. there should be an easier way ...
String qaFontSizeString = preferences.getString("qaFontSize", "0");
qaFontSize = Integer.parseInt(qaFontSizeString);
showQuestionAnswer = preferences.getBoolean("showQuestionAnswer", false);
displayFontSize = Integer.parseInt(preferences.getString("displayFontSize", "100"));
hideQuestionInAnswer = Integer.parseInt(preferences.getString("hideQuestionInAnswer", Integer.toString(HQIA_DO_SHOW)));
updateNotifications = preferences.getBoolean("enabled", true);
//redraw screen with new preferences
if (null != mFlipCard) {
if (mFlipCard.isChecked()) {
displayCardAnswer();
} else {
displayCardQuestion();
}
}
return preferences;
}

View File

@ -99,9 +99,10 @@ public class CardModel implements Comparator<CardModel> {
/** SELECT string with only those fields, which are used in AnkiDroid */
private final static String SELECT_STRING = "SELECT id, ordinal, modelId, name, description, active, qformat, aformat" //lformat left out
//qedformat, aedformat, questionInAnswer left out
+ ", questionFontSize, questionFontColour" //questionFontFamily, questionAlign left out
+ ", answerFontSize, answerFontColour" //same as for question
//qedformat, aedformat left out
+ ", questionInAnswer"
+ ", questionFontFamily, questionFontSize, questionFontColour" //questionAlign left out
+ ", answerFontFamily, answerFontSize, answerFontColour" //same as for question
+ ", lastFontColour" //lastFontFamily, lastFontSize left out
//rest left out
+ " FROM cardModels";
@ -134,11 +135,14 @@ public class CardModel implements Comparator<CardModel> {
myCardModel.active = cursor.getInt(5);
myCardModel.qformat = cursor.getString(6);
myCardModel.aformat = cursor.getString(7);
myCardModel.questionFontSize = cursor.getInt(8);
myCardModel.questionFontColour = cursor.getString(9);
myCardModel.answerFontSize = cursor.getInt(10);
myCardModel.answerFontColour = cursor.getString(11);
myCardModel.lastFontColour = cursor.getString(12);
myCardModel.questionInAnswer = cursor.getInt(8);
myCardModel.questionFontFamily = cursor.getString(9);
myCardModel.questionFontSize = cursor.getInt(10);
myCardModel.questionFontColour = cursor.getString(11);
myCardModel.answerFontFamily = cursor.getString(12);
myCardModel.answerFontSize = cursor.getInt(13);
myCardModel.answerFontColour = cursor.getString(14);
myCardModel.lastFontColour = cursor.getString(15);
models.put(myCardModel.id, myCardModel);
} while (cursor.moveToNext());
}

View File

@ -66,9 +66,6 @@ public class Model {
*/
private static HashMap<Long,Model> cardModelToModelMap = new HashMap<Long, Model>();
// TODO: Javadoc.
// TODO: Methods for reading/writing from/to DB.
// BEGIN SQL table entries
long id; // Primary key
long deckId; // Foreign key
@ -83,7 +80,6 @@ public class Model {
int source = 0;
// BEGIN SQL table entries
/** Map for convenience and speed which contains CardModels from current model */
private TreeMap<Long, CardModel> cardModelsMap = new TreeMap<Long, CardModel>();
@ -92,6 +88,12 @@ public class Model {
/** Map for convenience and speed which contains the CSS code related to a CardModel */
private HashMap<Long, String> cssCardModelMap = new HashMap<Long, String>();
/**
* The percentage chosen in preferences for font sizing at the time when the css for the CardModels
* related to this Model was calcualted in prepareCSSForCardModels.
*/
private transient int displayPercentage = 0;
private Model(String name) {
this.name = name;
@ -163,9 +165,6 @@ public class Model {
//load related field models
FieldModel.fromDb(modelId, currentModel.fieldModelsMap);
//prepare CSS for each card model in stead of doing it again and again
currentModel.prepareCSSForCardModels();
//make relations to maps
models.put(currentModel.id, currentModel);
CardModel myCardModel = null;
@ -221,7 +220,7 @@ public class Model {
String cssString = null;
for (Map.Entry<Long, CardModel> entry : cardModelsMap.entrySet()) {
myCardModel = entry.getValue();
cssString = createCSSForFontColorSize(myCardModel.id);
cssString = createCSSForFontColorSize(myCardModel.id, displayPercentage);
this.cssCardModelMap.put(myCardModel.id, cssString);
}
}
@ -229,45 +228,40 @@ public class Model {
/**
* Returns a cached CSS for the font color and font size of a given CardModel taking into account the included fields
* @param myCardModelId
* @param percentage the preference factor to use for calculating the display font size from the cardmodel and fontmodel font size
* @return the html contents surrounded by a css style which contains class styles for answer/question and fields
*/
protected final String getCSSForFontColorSize(long myCardModelId) {
protected final String getCSSForFontColorSize(long myCardModelId, int percentage) {
//tjek whether the percentage is this the same as last time
if (this.displayPercentage != percentage) {
this.displayPercentage = percentage;
prepareCSSForCardModels();
}
return this.cssCardModelMap.get(myCardModelId);
}
/**
* @param myCardModelId
* @param percentage the factor to apply to the font size in card model to the display size (in %)
* @return the html contents surrounded by a css style which contains class styles for answer/question and fields
*/
private final String createCSSForFontColorSize(long myCardModelId) {
private final String createCSSForFontColorSize(long myCardModelId, int percentage) {
StringBuffer sb = new StringBuffer();
sb.append("<!-- ").append(percentage).append(" % display font size-->");
sb.append("<style type=\"text/css\">\n");
CardModel myCardModel = cardModelsMap.get(myCardModelId);
int referenceFontSize = 20; //this is the default in Anki. Only used if the question font for some reason is not set
if (0 < myCardModel.questionFontSize) {
referenceFontSize = myCardModel.questionFontSize;
}
//body background
if (null != myCardModel.lastFontColour && 0 < myCardModel.lastFontColour.trim().length()) {
sb.append("body {background-color:").append(myCardModel.lastFontColour).append(";}\n");
}
//question font size and color
//question
sb.append(".").append(AnkiDroid.QUESTION_CLASS).append(" {\n");
if (null != myCardModel.questionFontColour && 0 < myCardModel.questionFontColour.trim().length()) {
sb.append("color:").append(myCardModel.questionFontColour).append(";\n");
}
sb.append("font-size:100%;\n");
sb.append(calculateDisplay(percentage, myCardModel.questionFontFamily, myCardModel.questionFontSize, myCardModel.questionFontColour));
sb.append("}\n");
//answer font size and color
//answer
sb.append(".").append(AnkiDroid.ANSWER_CLASS).append(" {\n");
if (null != myCardModel.answerFontColour && 0 < myCardModel.answerFontColour.trim().length()) {
sb.append("color:").append(myCardModel.answerFontColour).append(";\n");
}
if (0 < myCardModel.answerFontSize) {
sb.append(calculateRelativeFontSize(referenceFontSize, myCardModel.answerFontSize));
}
sb.append(calculateDisplay(percentage, myCardModel.answerFontFamily, myCardModel.answerFontSize, myCardModel.answerFontColour));
sb.append("}\n");
//css for fields. Gets css for all fields no matter whether they actually are used in a given card model
FieldModel myFieldModel = null;
@ -276,12 +270,7 @@ public class Model {
myFieldModel = entry.getValue();
hexId = "fm" + Long.toHexString(myFieldModel.id);
sb.append(".").append(hexId).append(" {\n");
if (null != myFieldModel.quizFontColour && 0 < myFieldModel.quizFontColour.trim().length()) {
sb.append("color: ").append(myFieldModel.quizFontColour).append(";\n");
}
if (0 < myFieldModel.quizFontSize) {
sb.append(calculateRelativeFontSize(referenceFontSize, myFieldModel.quizFontSize));
}
sb.append(calculateDisplay(percentage, myFieldModel.quizFontFamily, myFieldModel.quizFontSize, myFieldModel.quizFontColour));
sb.append("}\n");
}
@ -289,18 +278,20 @@ public class Model {
sb.append("</style>");
return sb.toString();
}
/**
*
* @param reference
* @param current
* @return a css entry for relative font size as a percentage of the current in relation to the reference
*/
private final static String calculateRelativeFontSize(int reference, int current) {
private final static String calculateDisplay(int percentage, String fontFamily, int fontSize, String fontColour) {
StringBuffer sb = new StringBuffer();
sb.append("font-size:");
sb.append((100 * current)/reference);
sb.append("%;\n");
if (null != fontFamily && 0 < fontFamily.trim().length()) {
sb.append("font-family:\"").append(fontFamily).append("\";\n");
}
if (null != fontColour && 0 < fontColour.trim().length()) {
sb.append("color:").append(fontColour).append(";\n");
}
if (0 < fontSize) {
sb.append("font-size:");
sb.append((percentage * fontSize)/100);
sb.append("px;\n");
}
return sb.toString();
}