├── gradle.properties
├── .gitignore
├── lib
├── src
│ ├── test
│ │ └── java
│ │ │ └── ch
│ │ │ └── poole
│ │ │ └── openinghoursfragment
│ │ │ └── templates
│ │ │ ├── package-info.java
│ │ │ └── TemplatesDatabaseTest.java
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── styles.xml
│ │ │ ├── drawable-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable-xhdpi
│ │ │ │ ├── ic_add_white_36dp.png
│ │ │ │ ├── ic_more_vert_white_36dp.png
│ │ │ │ └── ic_action_edit_holo_light.png
│ │ │ ├── layout
│ │ │ │ ├── divider.xml
│ │ │ │ ├── menu.xml
│ │ │ │ ├── toast.xml
│ │ │ │ ├── comment.xml
│ │ │ │ ├── twentyfourseven.xml
│ │ │ │ ├── valuepicker.xml
│ │ │ │ ├── template_list.xml
│ │ │ │ ├── interval.xml
│ │ │ │ ├── template_list_item.xml
│ │ │ │ ├── time_range_row.xml
│ │ │ │ ├── rangepicker.xml
│ │ │ │ ├── time_row.xml
│ │ │ │ ├── datepicker.xml
│ │ │ │ ├── modifier.xml
│ │ │ │ ├── rule_header.xml
│ │ │ │ ├── occurrence_in_month_picker.xml
│ │ │ │ ├── time_extended_range_row.xml
│ │ │ │ ├── holiday_row.xml
│ │ │ │ ├── timerangepicker.xml
│ │ │ │ ├── time_end_event_row.xml
│ │ │ │ ├── year_range.xml
│ │ │ │ ├── week_range.xml
│ │ │ │ ├── time_event_row.xml
│ │ │ │ ├── time_start_event_row.xml
│ │ │ │ ├── daterange_row.xml
│ │ │ │ ├── template_item.xml
│ │ │ │ ├── daterangepicker.xml
│ │ │ │ └── openinghours.xml
│ │ │ ├── values-kn
│ │ │ │ └── strings.xml
│ │ │ ├── values-hr
│ │ │ │ └── strings.xml
│ │ │ ├── values-no
│ │ │ │ └── strings.xml
│ │ │ ├── values-ro
│ │ │ │ └── strings.xml
│ │ │ ├── values-sk
│ │ │ │ └── strings.xml
│ │ │ ├── values-eu
│ │ │ │ └── strings.xml
│ │ │ ├── values-el
│ │ │ │ └── strings.xml
│ │ │ ├── values-br
│ │ │ │ └── strings.xml
│ │ │ ├── values-da
│ │ │ │ └── strings.xml
│ │ │ ├── values-pt-rBR
│ │ │ │ └── strings.xml
│ │ │ ├── values-ko
│ │ │ │ └── strings.xml
│ │ │ └── values-tr
│ │ │ │ └── strings.xml
│ │ ├── java
│ │ │ └── ch
│ │ │ │ └── poole
│ │ │ │ └── openinghoursfragment
│ │ │ │ ├── pickers
│ │ │ │ ├── package-info.java
│ │ │ │ ├── SetRangeListener.java
│ │ │ │ ├── SetTimeRangeListener.java
│ │ │ │ ├── SetDateRangeListener.java
│ │ │ │ ├── ValuePicker.java
│ │ │ │ └── RangePicker.java
│ │ │ │ ├── package-info.java
│ │ │ │ ├── templates
│ │ │ │ ├── package-info.java
│ │ │ │ ├── UpdateTextListener.java
│ │ │ │ ├── UpdateCursorListener.java
│ │ │ │ └── TemplateDatabaseHelper.java
│ │ │ │ ├── Delete.java
│ │ │ │ ├── DefaultTextWatcher.java
│ │ │ │ ├── OnSaveListener.java
│ │ │ │ ├── DateMenuInterface.java
│ │ │ │ ├── CancelableDialogFragment.java
│ │ │ │ ├── ValueArrayAdapter.java
│ │ │ │ ├── ValueWithDescription.java
│ │ │ │ └── Util.java
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ ├── java
│ │ └── ch
│ │ │ └── poole
│ │ │ └── openinghoursfragment
│ │ │ ├── TestActivity.java
│ │ │ ├── MixedModeTest.java
│ │ │ ├── TextInputTest.java
│ │ │ └── templates
│ │ │ └── TemplatesTest.java
│ │ ├── AndroidManifest.xml
│ │ └── resources
│ │ └── templates.json
├── .gitignore
├── .tx
│ └── config
└── documentation
│ └── docs
│ └── help
│ ├── zh-rTW
│ └── Opening hours.md
│ ├── zh-Hans
│ └── Opening hours.md
│ └── iw
│ └── Opening hours.md
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── documentation
└── images
│ ├── Screenshot_basic.png
│ └── Screenshot_date_offset.png
├── testapp
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── drawable-xhdpi
│ │ │ └── ic_launcher.png
│ │ ├── values
│ │ │ └── dimens.xml
│ │ └── layout
│ │ │ └── activity_test.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── ch
│ │ └── poole
│ │ └── ohfragmenttest
│ │ ├── Test.java
│ │ └── TestFragment.java
└── build.gradle
├── .settings
└── org.eclipse.jdt.core.prefs
├── settings.gradle
├── .checkstyle
├── LICENCE.txt
├── .github
└── workflows
│ └── android.yml
├── gradlew.bat
├── README.md
├── CHANGELOG.txt
└── gradlew
/gradle.properties:
--------------------------------------------------------------------------------
1 | android.enableJetifier=true
2 | android.useAndroidX=true
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /gen/
3 | /libs/
4 | /.classpath
5 | /.gradle/
6 | /build/
7 | /.project
8 | /.settings/
9 |
--------------------------------------------------------------------------------
/lib/src/test/java/ch/poole/openinghoursfragment/templates/package-info.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.templates;
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/documentation/images/Screenshot_basic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/documentation/images/Screenshot_basic.png
--------------------------------------------------------------------------------
/testapp/.gitignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /.project
3 | /.classpath
4 | /.settings/
5 | /bin/
6 | /project.properties
7 | /libs/
8 | /.externalToolBuilders/
9 |
--------------------------------------------------------------------------------
/lib/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #E87850
4 |
--------------------------------------------------------------------------------
/documentation/images/Screenshot_date_offset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/documentation/images/Screenshot_date_offset.png
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/pickers/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Classes for pickers
3 | */
4 | package ch.poole.openinghoursfragment.pickers;
--------------------------------------------------------------------------------
/lib/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/lib/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/lib/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/lib/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Classes for the opening hours editor
3 | */
4 | package ch.poole.openinghoursfragment;
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/templates/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Template related classes
3 | */
4 | package ch.poole.openinghoursfragment.templates;
--------------------------------------------------------------------------------
/lib/src/main/res/drawable-xhdpi/ic_add_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/lib/src/main/res/drawable-xhdpi/ic_add_white_36dp.png
--------------------------------------------------------------------------------
/testapp/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/testapp/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/.gitignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /.project
3 | /.classpath
4 | /.settings/
5 | /bin/
6 | /project.properties
7 | /libs/
8 | /.externalToolBuilders/
9 | /jacoco.exec
10 |
--------------------------------------------------------------------------------
/lib/src/main/res/drawable-xhdpi/ic_more_vert_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/lib/src/main/res/drawable-xhdpi/ic_more_vert_white_36dp.png
--------------------------------------------------------------------------------
/lib/src/main/res/drawable-xhdpi/ic_action_edit_holo_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simonpoole/OpeningHoursFragment/HEAD/lib/src/main/res/drawable-xhdpi/ic_action_edit_holo_light.png
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
3 | org.eclipse.jdt.core.compiler.compliance=1.8
4 | org.eclipse.jdt.core.compiler.source=1.8
5 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/divider.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | include ':testapp', ':lib'
--------------------------------------------------------------------------------
/testapp/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
--------------------------------------------------------------------------------
/.checkstyle:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/Delete.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment;
2 |
3 | /**
4 | * Interface for call backs that delete a Rule
5 | *
6 | * @author simon
7 | *
8 | */
9 | public interface Delete {
10 | /**
11 | * Delete the object in question
12 | */
13 | void delete();
14 | }
15 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-kn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ಹೌದು
5 | ಇಲ್ಲ
6 | End
7 |
8 | ಎಲ್ಲಾ
9 |
10 | Delete
11 | ಮುಚ್ಚಿದ
12 |
13 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/templates/UpdateTextListener.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.templates;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | public interface UpdateTextListener {
6 |
7 | /**
8 | * Update the OH string with a new text
9 | *
10 | * @param newText the new text
11 | */
12 | public void updateText(@NonNull String newText);
13 | }
14 |
--------------------------------------------------------------------------------
/lib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/templates/UpdateCursorListener.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.templates;
2 |
3 | import android.database.sqlite.SQLiteDatabase;
4 | import androidx.annotation.NonNull;
5 |
6 | public interface UpdateCursorListener {
7 |
8 | /**
9 | * Replace the current cursor for the template database
10 | *
11 | * @param db the template database
12 | */
13 | public void newCursor(@NonNull final SQLiteDatabase db);
14 | }
15 |
--------------------------------------------------------------------------------
/lib/src/androidTest/java/ch/poole/openinghoursfragment/TestActivity.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | public class TestActivity extends AppCompatActivity implements OnSaveListener {
6 |
7 | String result;
8 |
9 | @Override
10 | public void save(String key, String openingHours) {
11 | result = openingHours;
12 | }
13 |
14 | public String getResult() {
15 | return result;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/DefaultTextWatcher.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment;
2 |
3 | import android.text.TextWatcher;
4 |
5 | abstract class DefaultTextWatcher implements TextWatcher {
6 | @Override
7 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
8 | // empty
9 | }
10 |
11 | @Override
12 | public void onTextChanged(CharSequence s, int start, int before, int count) {
13 | // empty
14 | }
15 | }
--------------------------------------------------------------------------------
/lib/src/main/res/values-hr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Spremi
5 | Da
6 | Ne
7 | End
8 |
9 | Svi
10 | Komentar
11 |
12 | zatvoreno
13 | nepoznato
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/OnSaveListener.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment;
2 |
3 | /**
4 | * Interface for listeners to return the constructed openinghous value
5 | *
6 | * @author simon
7 | *
8 | */
9 | public interface OnSaveListener {
10 | /**
11 | * Save the value
12 | *
13 | * @param key the OSM key (for example opening_hours or service_times
14 | * @param value the constructed value
15 | */
16 | void save(String key, String value);
17 | }
18 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-no/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Lagre
5 | Ja
6 | Nei
7 | End
8 |
9 | Alle
10 |
11 | Slett
12 | lukket
13 | ukjent
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-ro/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Da
5 | Nu
6 | End
7 |
8 | Tot
9 |
10 | Delete
11 | Dată
12 | închis
13 | necunoscut
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/pickers/SetRangeListener.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.pickers;
2 |
3 | /**
4 | * Interface for listeners that return date values from RangePicker
5 | *
6 | * @author simon
7 | *
8 | */
9 | public interface SetRangeListener {
10 | /**
11 | * Listener for values from RangePicker
12 | *
13 | * @param start selected start range value
14 | * @param end selected end range value
15 | */
16 | void setRange(int start, int end);
17 | }
18 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-sk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Áno
5 | Nie
6 | End
7 |
8 | Všetko
9 |
10 | Delete
11 | Dátum
12 | zatvorené
13 | neznáme
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-eu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Gorde
5 | Egina
6 | Bai
7 | Ez
8 | Eraman gora
9 | Eraman behera
10 |
11 |
12 | Arrunta
13 | ezezaguna
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/DateMenuInterface.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment;
2 |
3 | import ch.poole.openinghoursparser.DateRange;
4 |
5 | /**
6 | * This is used to reduce code duplication when adding menu items for the various date range variants
7 | *
8 | * @author simon
9 | *
10 | */
11 | interface DateMenuInterface {
12 | /**
13 | * Add the actual dates that you want included in the config for the menu item
14 | *
15 | * @param dateRange the DateRange to add the dates to
16 | */
17 | void addDates(DateRange dateRange);
18 | }
19 |
--------------------------------------------------------------------------------
/testapp/src/main/res/layout/activity_test.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/toast.xml:
--------------------------------------------------------------------------------
1 |
9 |
14 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/pickers/SetTimeRangeListener.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.pickers;
2 |
3 | /**
4 | * Interface for listeners that return time values from TimeRangePicker
5 | *
6 | * @author simon
7 | *
8 | */
9 | public interface SetTimeRangeListener {
10 | /**
11 | * Listener for values from DateRangePicker
12 | *
13 | * @param startHour selected start year
14 | * @param startMinute selected start day of the month
15 | * @param endHour selected end year
16 | * @param endMinute selected end day of the month
17 | */
18 | void setTimeRange(int startHour, int startMinute, int endHour, int endMinute);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/.tx/config:
--------------------------------------------------------------------------------
1 | [main]
2 | host = https://www.transifex.com
3 |
4 | [o:openstreetmap:p:openinghoursfragment:r:opening-hoursmd]
5 | file_filter = documentation/docs/help//Opening hours.md
6 | source_file = documentation/docs/help/en/Opening hours.md
7 | source_lang = en
8 | minimum_perc = 50
9 | lang_map = zh_TW: zh-rTW, pt_BR: pt-rBR, zh_CN: zh-rCN, sv_SE: sv-rSE, id: in, he: iw, cs: cs-rCZ
10 |
11 | [o:openstreetmap:p:openinghoursfragment:r:stringsxml]
12 | file_filter = src/main/res/values-/strings.xml
13 | source_file = src/main/res/values/strings.xml
14 | source_lang = en
15 | minimum_perc = 20
16 | lang_map = id: in, he: iw, cs: cs-rCZ, zh_TW: zh-rTW, pt_BR: pt-rBR, zh_CN: zh-rCN, sv_SE: sv-rSE
17 |
18 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-el/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Αποθήκευση
5 | Έγινε
6 | Ναι
7 | Όχι
8 | Όλα
9 | Ωρες λειτουργίας
10 |
11 | Διαγραφή
12 | Μετακίνηση επάνω
13 | Μετακίνηση κάτω
14 |
15 |
16 | Κανονικό
17 | Σχόλιο
18 |
19 | κλειστό
20 | άγνωστη
21 |
22 |
23 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/comment.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
14 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/testapp/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/twentyfourseven.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
17 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LICENCE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Simon Poole
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software
4 | and associated documentation files (the "Software"), to deal in the Software without restriction,
5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7 | subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies
10 | or substantial portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
13 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
14 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
16 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/lib/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
17 |
18 |
19 |
20 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/lib/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
11 |
12 |
18 |
21 |
26 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/CancelableDialogFragment.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment;
2 |
3 | import android.os.Bundle;
4 | import androidx.annotation.NonNull;
5 | import androidx.fragment.app.DialogFragment;
6 | import androidx.fragment.app.Fragment;
7 | import androidx.fragment.app.FragmentManager;
8 | import androidx.fragment.app.FragmentTransaction;
9 |
10 | public class CancelableDialogFragment extends DialogFragment {
11 |
12 | @Override
13 | public void onCreate(Bundle savedInstanceState) {
14 | super.onCreate(savedInstanceState);
15 | setCancelable(true);
16 | }
17 |
18 | /**
19 | * Dismiss any instance of this dialog
20 | *
21 | * @param parentFragment the Fragment calling this
22 | * @param tag the tag used by the Fragment
23 | */
24 | protected static void dismissDialog(@NonNull Fragment parentFragment, @NonNull String tag) {
25 | FragmentManager fm = parentFragment.getChildFragmentManager();
26 | FragmentTransaction ft = fm.beginTransaction();
27 | Fragment fragment = fm.findFragmentByTag(tag);
28 | if (fragment != null) {
29 | ft.remove(fragment);
30 | }
31 | ft.commit();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/valuepicker.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
28 |
29 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/template_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
15 |
29 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/pickers/SetDateRangeListener.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.pickers;
2 |
3 | import androidx.annotation.Nullable;
4 | import ch.poole.openinghoursparser.Month;
5 | import ch.poole.openinghoursparser.VarDate;
6 | import ch.poole.openinghoursparser.WeekDay;
7 |
8 | /**
9 | * Interface for listeners that return date values from DateRangePicker
10 | *
11 | * @author simon
12 | *
13 | */
14 | public interface SetDateRangeListener {
15 | /**
16 | * Listener for values from DateRangePicker
17 | *
18 | * @param startYear selected start year
19 | * @param startMonth selected start month or null
20 | * @param startWeekday selected start weekday or null
21 | * @param startDay selected start day of the month or occurrence if startWeekday isn't null
22 | * @param startVarDate selected start variable date ie easter or null
23 | * @param endYear selected end year
24 | * @param endMonth selected end month or null
25 | * @param endWeekday selected end weekday or null
26 | * @param endDay selected end day of the month or occurrence if endWeekday isn't null
27 | * @param endVarDate selected end variable date ie easter or null
28 | */
29 | void setDateRange(int startYear, @Nullable Month startMonth, @Nullable WeekDay startWeekday, int startDay, @Nullable VarDate startVarDate, int endYear,
30 | @Nullable Month endMonth, @Nullable WeekDay endWeekday, int endDay, @Nullable VarDate endVarDate);
31 | }
32 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/interval.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
13 |
21 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/ValueArrayAdapter.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment;
2 |
3 | import java.util.List;
4 |
5 | import android.content.Context;
6 | import androidx.annotation.NonNull;
7 | import android.util.Log;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ArrayAdapter;
11 | import android.widget.TextView;
12 |
13 | public class ValueArrayAdapter extends ArrayAdapter {
14 |
15 | final List values;
16 |
17 | /**
18 | * Construct a new instance
19 | *
20 | * @param context Android Context
21 | * @param resource the resource id
22 | * @param values a List of ValuesWithDescription
23 | */
24 | public ValueArrayAdapter(@NonNull Context context, int resource, @NonNull List values) {
25 | super(context, resource, values);
26 | this.values = values;
27 | }
28 |
29 | @Override
30 | public View getView(int position, View convertView, ViewGroup container) {
31 | View v = super.getView(position, convertView, container);
32 | TextView textView = (TextView) v.findViewById(android.R.id.text1);
33 | if (textView != null) {
34 | ValueWithDescription value = values.get(position);
35 | textView.setText(value.getDescription() != null ? value.getDescription() : value.getValue());
36 | } else {
37 | Log.e("ValidatorAdapterView", "position " + position + " view is null");
38 | }
39 | return v;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/src/androidTest/resources/templates.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "Weekdays with lunch break",
4 | "is_default": 1,
5 | "template": "Mo-Fr 09:00-12:00,13:30-18:30;Sa 09:00-17:00;PH closed",
6 | "key": null,
7 | "region": "CH",
8 | "object": null
9 | },
10 | {
11 | "name": "Weekdays with lunch break and late shopping",
12 | "is_default": 0,
13 | "template": "Mo,Tu,Th,Fr 09:00-12:00,13:30-18:30;We 09:00-12:00,13:30-20:00;Sa 09:00-17:00;PH closed",
14 | "key": null,
15 | "region": "AT",
16 | "object": null
17 | },
18 | {
19 | "name": "Weekdays",
20 | "is_default": 0,
21 | "template": "Mo-Fr 09:00-18:30;Sa 09:00-17:00;PH closed",
22 | "key": null,
23 | "region": "CH",
24 | "object": null
25 | },
26 | {
27 | "name": "Weekdays with late shopping",
28 | "is_default": 0,
29 | "template": "Mo,Tu,Th,Fr 09:00-18:30;We 09:00-20:00;Sa 09:00-17:00;PH closed",
30 | "key": "opening_hours",
31 | "region": "CH",
32 | "object": null
33 | },
34 | {
35 | "name": "24 hours, 7 days a week",
36 | "is_default": 0,
37 | "template": "24/7",
38 | "key": null,
39 | "region": "CH",
40 | "object": "amenity=restaurant"
41 | },
42 | {
43 | "name": "Once per weekday",
44 | "is_default": 1,
45 | "template": "Mo-Fr 09:00; Sa 07:00; PH closed",
46 | "key": "collection_times",
47 | "region": "CH",
48 | "object": null
49 | }
50 | ]
51 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/template_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
20 |
27 |
34 |
35 |
39 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/time_range_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/ValueWithDescription.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment;
2 |
3 | import java.io.Serializable;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 |
8 | public class ValueWithDescription implements Serializable {
9 | private static final long serialVersionUID = 1L;
10 | private final String value;
11 | private final String description;
12 |
13 | /**
14 | * Construct a new instance
15 | *
16 | * @param value the value
17 | * @param description the description if any
18 | */
19 | public ValueWithDescription(@NonNull final String value, @Nullable final String description) {
20 | this.value = value;
21 | this.description = description;
22 | }
23 |
24 | /**
25 | * @return the value
26 | */
27 | public String getValue() {
28 | return value;
29 | }
30 |
31 | /**
32 | * @return the description
33 | */
34 | public String getDescription() {
35 | return description;
36 | }
37 |
38 | @Override
39 | public String toString() {
40 | return getDescription() != null ? getDescription() : getValue();
41 | }
42 |
43 | @Override
44 | public int hashCode() {
45 | return value == null ? 0 : value.hashCode();
46 | }
47 |
48 | @Override
49 | public boolean equals(Object obj) {
50 | if (this == obj) {
51 | return true;
52 | }
53 | if (obj == null) {
54 | return false;
55 | }
56 | if (getClass() != obj.getClass()) {
57 | return false;
58 | }
59 | ValueWithDescription other = (ValueWithDescription) obj;
60 | if (value == null) {
61 | if (other.value != null) {
62 | return false;
63 | }
64 | } else if (!value.equals(other.value)) {
65 | return false;
66 | }
67 | return true;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/.github/workflows/android.yml:
--------------------------------------------------------------------------------
1 | name: Android CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | test:
13 | runs-on: ubuntu-latest
14 |
15 | env:
16 | # Needed to get some information about the pull request, if any
17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18 | # SonarCloud access token should be generated from https://sonarcloud.io/account/security/
19 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
20 |
21 | steps:
22 | - name: checkout
23 | uses: actions/checkout@v4
24 | - name: set up JDK 17
25 | uses: actions/setup-java@v1
26 | with:
27 | java-version: 17
28 | - name: Enable KVM
29 | run: |
30 | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
31 | sudo udevadm control --reload-rules
32 | sudo udevadm trigger --name-match=kvm
33 | - name: run tests
34 | uses: reactivecircus/android-emulator-runner@v2
35 | with:
36 | api-level: 28
37 | emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
38 | disable-animations: true
39 | script: ./gradlew connectedCheck
40 | - name: Upload Test Results
41 | if: ${{ always() }}
42 | uses: actions/upload-artifact@v4
43 | with:
44 | name: Test output
45 | path: /Users/runner/work/OpeningHoursFragment/OpeningHoursFragment/lib/build/reports/androidTests/connected
46 | - name: Generate coverage report
47 | run: ./gradlew jacocoTestReport
48 | - name: SonarCloud Scan
49 | # only do this step if we have a token for sonar
50 | if: ${{ env.SONAR_TOKEN }}
51 | # note as we don't wait for processing to complete this will always succeed
52 | run: ./gradlew sonarqube -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=simonpoole-github --info
53 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/rangepicker.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
29 |
44 |
45 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-br/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Nullañ
5 | Mat eo
6 | Enrollañ
7 | Ouzhpennañ ur reolenn
8 | Freskaat
9 | Ya
10 | Ket
11 | Anv:
12 | Dre ziouer:
13 | %1$s (dre ziouer)
14 | Eurioù digeriñ
15 | Evezhiet
16 | Reolenn %1$s
17 |
18 |
19 | Diverkañ
20 | Dre ziouer
21 |
22 | Bloavezhioù
23 | Kemennadenn
24 |
25 | Sav-heol
26 | Kuzh-heol
27 | Deroù-deiz
28 | Vakañsoù foran
29 | Lu
30 | Meu
31 | Mer
32 | Ya
33 | Gw
34 | Sa
35 | Su
36 |
37 | Gwe
38 | C\'hw
39 | Meu
40 | Ebr
41 | Mae
42 | Mez
43 | Goue
44 | Eost
45 | Gwen
46 | Here
47 | Du
48 | Ker
49 |
50 | Serret
51 | dianav
52 |
53 |
54 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/time_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
23 |
24 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/datepicker.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
26 |
40 |
54 |
55 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/testapp/src/main/java/ch/poole/ohfragmenttest/Test.java:
--------------------------------------------------------------------------------
1 | package ch.poole.ohfragmenttest;
2 |
3 | import java.util.ArrayList;
4 |
5 | import android.content.res.Configuration;
6 | import android.os.Bundle;
7 | import androidx.fragment.app.Fragment;
8 | import androidx.fragment.app.FragmentManager;
9 | import androidx.fragment.app.FragmentTransaction;
10 | import androidx.appcompat.app.AppCompatActivity;
11 | import android.util.Log;
12 | import ch.poole.openinghoursfragment.OnSaveListener;
13 | import ch.poole.openinghoursfragment.OpeningHoursFragment;
14 | import ch.poole.openinghoursfragment.ValueWithDescription;
15 |
16 | public class Test extends AppCompatActivity implements OnSaveListener {
17 | final String LONG_TEST = "Mo[2] -2 days 10:00-12:00;24/7;week 4-40 PH+2days dawn-09:00;dawn-25:00/25;2010-2100/4 12:01-13:02, 14:00 , 10:00-(sunset+02:00) , 13:00+, 11:01-45:00/46, dawn-dusk, sunrise+ ; 12-16 closed \"ein test\" ; Mo, We 12:01-13:02 ; Apr-Sep 10:01-13:03, Dec 13:03-21:01";
18 | final String SHORT_TEST = "dawn+";
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.activity_test);
24 |
25 | FragmentManager fm = getSupportFragmentManager();
26 | FragmentTransaction ft = fm.beginTransaction();
27 | Fragment prev = fm.findFragmentByTag("fragment_openinghours");
28 | if (prev != null) {
29 | ft.remove(prev);
30 | }
31 | ft.commit();
32 |
33 | ArrayList textValues = new ArrayList<>();
34 | ValueWithDescription yes = new ValueWithDescription("yes", "Yes");
35 | textValues.add(yes);
36 | ValueWithDescription no = new ValueWithDescription("no", "No");
37 | textValues.add(no);
38 |
39 | // ValueWithDescription key = new ValueWithDescription("opening_hours", "Opening hours");
40 | ValueWithDescription key = new ValueWithDescription("collection_times", "Collection times");
41 | OpeningHoursFragment openingHoursDialog = OpeningHoursFragment.newInstance(key, null, ch.poole.openinghoursfragment.R.style.Theme_DialogLight, 5, true,
42 | textValues);
43 | openingHoursDialog.show(fm, "fragment_openinghours");
44 | }
45 |
46 | @Override
47 | public void save(String key, String openingHours) {
48 | Log.d("Test", "save got " + openingHours + " for key " + key);
49 | TestFragment.showDialog(this, openingHours);
50 | }
51 |
52 | @Override
53 | public void onConfigurationChanged(Configuration newConfig) {
54 | super.onConfigurationChanged(newConfig);
55 | this.recreate();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/modifier.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
22 |
23 |
32 |
33 |
45 |
46 |
55 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/lib/src/androidTest/java/ch/poole/openinghoursfragment/MixedModeTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
3 | * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | */
5 |
6 | package ch.poole.openinghoursfragment;
7 |
8 | import java.util.ArrayList;
9 |
10 | import org.junit.Assert;
11 | import org.junit.Before;
12 | import org.junit.Rule;
13 | import org.junit.Test;
14 | import org.junit.runner.RunWith;
15 |
16 | import androidx.fragment.app.Fragment;
17 | import androidx.fragment.app.FragmentActivity;
18 | import androidx.fragment.app.FragmentManager;
19 | import androidx.fragment.app.FragmentTransaction;
20 | import androidx.test.ext.junit.runners.AndroidJUnit4;
21 | import androidx.test.filters.LargeTest;
22 | import androidx.test.platform.app.InstrumentationRegistry;
23 | import androidx.test.rule.ActivityTestRule;
24 | import androidx.test.uiautomator.UiDevice;
25 | import androidx.test.uiautomator.UiObject2;
26 |
27 | @RunWith(AndroidJUnit4.class)
28 | @LargeTest
29 | public class MixedModeTest {
30 |
31 | private FragmentActivity activity;
32 | private UiDevice device;
33 |
34 | @Rule
35 | public ActivityTestRule mActivityRule = new ActivityTestRule<>(TestActivity.class);
36 |
37 | @Before
38 | public void setup() {
39 | device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
40 | activity = mActivityRule.getActivity();
41 | FragmentManager fm = activity.getSupportFragmentManager();
42 | FragmentTransaction ft = fm.beginTransaction();
43 | Fragment prev = fm.findFragmentByTag("fragment_openinghours");
44 | if (prev != null) {
45 | ft.remove(prev);
46 | }
47 | ft.commit();
48 |
49 | ValueWithDescription key = new ValueWithDescription("fee", "Fee");
50 |
51 | ArrayList values = new ArrayList<>();
52 | values.add(new ValueWithDescription("yes", "Yes"));
53 | values.add(new ValueWithDescription("no", "No"));
54 |
55 | OpeningHoursFragment fragment = OpeningHoursFragment.newInstance(key, null, null, "no", R.style.Theme_DialogLight, 5, false, values, null);
56 | fragment.show(fm, "fragment_openinghours");
57 | }
58 |
59 | @Test
60 | public void switchMode() {
61 | Assert.assertNotNull(TestUtils.findText(device, false, "no"));
62 | UiObject2 buttonText = TestUtils.findText(device, false, activity.getString(R.string.text_values));
63 | Assert.assertTrue(buttonText.isChecked());
64 | UiObject2 buttonOH = TestUtils.findText(device, false, activity.getString(R.string.opening_hours_key));
65 | buttonOH.click();
66 | Assert.assertTrue(buttonOH.isChecked());
67 | Assert.assertNotNull(TestUtils.findText(device, false, "Encountered"));
68 | buttonText.click();
69 | Assert.assertTrue(buttonText.isChecked());
70 | Assert.assertNull(TestUtils.findText(device, false, "Encountered"));
71 | }
72 | }
--------------------------------------------------------------------------------
/testapp/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add
2 | // configuration options common to all sub-projects/modules.
3 |
4 | // Project level build file starts here
5 | apply plugin: 'eclipse'
6 | apply plugin: 'com.android.application'
7 |
8 |
9 | apply from: 'https://raw.githubusercontent.com/simonpoole/gradle-tasks/master/eclipse-android-3'
10 | // apply from: '../../gradle-tasks/eclipse-android-3-lib'
11 |
12 | allprojects {
13 | repositories {
14 | mavenCentral()
15 | maven { url "https://maven.google.com" }
16 | mavenLocal()
17 | }
18 | }
19 |
20 | configurations.all {
21 | // Check for updates every build
22 | resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
23 | }
24 |
25 | android {
26 | namespace "ch.poole.ohfragmenttest"
27 |
28 | compileSdkVersion 35
29 |
30 | defaultConfig {
31 | minSdkVersion 21
32 | targetSdkVersion 35
33 | versionCode 100
34 | versionName "1"
35 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
36 | }
37 |
38 | compileOptions {
39 | sourceCompatibility JavaVersion.VERSION_1_8
40 | targetCompatibility JavaVersion.VERSION_1_8
41 | }
42 |
43 | buildTypes {
44 | debug {
45 | testCoverageEnabled true
46 | }
47 | }
48 |
49 | lintOptions {
50 | // checkReleaseBuilds false
51 | // Or, if you prefer, you can continue to check for errors in release builds,
52 | // but continue the build even when errors are found:
53 | abortOnError false
54 | }
55 | }
56 |
57 | ext {
58 | androidxVersion = "1.0.0"
59 | }
60 |
61 | dependencies {
62 | // this shouldn't be necessary
63 | implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
64 | implementation project(path: ':lib')
65 |
66 | implementation "androidx.appcompat:appcompat:1.7.0"
67 | implementation "androidx.appcompat:appcompat-resources:1.7.0"
68 | implementation "androidx.recyclerview:recyclerview:1.1.0"
69 | implementation "androidx.preference:preference:1.2.1"
70 | implementation "com.google.android.material:material:1.8.0"
71 | implementation "androidx.annotation:annotation:1.1.0"
72 | implementation "androidx.core:core:1.16.0"
73 | implementation "ch.poole:OpeningHoursParser:0.26.0"
74 | implementation "ch.poole.android:rangebar:0.1.6"
75 | implementation 'ch.poole.android:numberpickerview:1.3.0'
76 | implementation "com.google.code.gson:gson:2.8.5"
77 |
78 | // Instrumentation tests
79 | androidTestImplementation 'androidx.annotation:annotation:1.1.0'
80 | androidTestImplementation 'androidx.test.ext:junit:1.2.1'
81 | androidTestImplementation 'androidx.test:rules:1.6.1'
82 | androidTestImplementation "org.hamcrest:hamcrest-library:2.2"
83 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
84 |
85 | // androidTestCompile "com.android.support.test.uiautomator:uiautomator-v18:2.1.2"
86 | }
87 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/rule_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
23 |
24 |
29 |
30 |
40 |
41 |
50 |
51 |
58 |
65 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/occurrence_in_month_picker.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
26 |
40 |
54 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/time_extended_range_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
21 |
22 |
45 |
46 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-da/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Annuller
5 | OK
6 | Gem
7 | Færdig
8 | Tilføj regel
9 | Tilføj regel for 24/7
10 | Tilføj regel for ferie
11 | Indlæs skabelon
12 | Gem til skabelon
13 | Håndtér skabeloner
14 | Indlæs skabeloner
15 | Håndtér skabeloner
16 | Gem skabelon
17 | Ja
18 | Nej
19 | Start
20 | End
21 |
22 | Rediger skabelon
23 | Standard:
24 | Alle
25 | Åbningstider
26 | Overvåget
27 | Gadebelysning
28 |
29 | Indlæst standard skabelon
30 |
31 |
32 | Delete
33 | Vis regel type
34 | Flyt op
35 | Flyt ned
36 |
37 |
38 | Normal
39 | Datointerval
40 | Dato
41 | Modifikator
42 | Kommentar
43 |
44 | til
45 |
46 | Påske
47 |
48 | Solopgang
49 | Solnedgang
50 | Daggry
51 | Skumring
52 |
53 | Ma
54 | Ti
55 | On
56 | To
57 | Fr
58 | Lø
59 | Sø
60 |
61 | Jan
62 | Feb
63 | Mar
64 | Apr
65 | Maj
66 | Jun
67 | Jul
68 | Aug
69 | Sep
70 | Okt
71 | Nov
72 | Dec
73 |
74 | åben
75 | lukket
76 | ukendt
77 |
78 | før
79 | efter
80 |
81 |
82 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/holiday_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
20 |
33 |
41 |
46 |
50 |
51 |
60 |
65 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/simonpoole/OpeningHoursFragment/actions) [](https://sonarcloud.io/dashboard?id=OpeningHoursFragment) [](https://sonarcloud.io/dashboard?id=OpeningHoursFragment) [](https://sonarcloud.io/component_measures?id=OpeningHoursFragment%3Alib&metric=bugs) [](https://sonarcloud.io/component_measures?id=OpeningHoursFragment%3Alib&metric=Maintainability) [](https://sonarcloud.io/component_measures?id=OpeningHoursFragment%3Alib&metric=Security) [](https://sonarcloud.io/component_measures?id=OpeningHoursFragment%3Alib&metric=Reliability)
2 |
3 | # OpeningHoursFragment
4 |
5 | This is a re-usable UI element for editing opening hour values that covers the complete specification, it is suitable for non-destructive editing (it will not overwrite or destroy valid opening hours values).
6 |
7 | 
8 |
9 | Please see the [end user documentation](lib/documentation/docs/help/en/Opening%20hours.md) for more information.
10 |
11 | ## Usage
12 |
13 | ### From a FragmentActivity
14 |
15 | ``` java
16 | FragmentManager fm = getSupportFragmentManager();
17 | ...
18 | OpeningHoursFragment openingHoursDialog = OpeningHoursFragment.newInstance(key,finalValue, R.style.Theme_AppCompat_Light_Dialog_Alert, -1, true);
19 | openingHoursDialog.show(fm, "fragment_opening_hours");
20 | ```
21 |
22 | The calling activity needs to implement ch.poole.openinghoursfragement.OnSaveListener which will be used when the user saves a OH value. Have a look at the test app for a working trivial example.
23 |
24 | ### From a Fragment
25 |
26 | ``` java
27 | FragmentManager fm = getChildFragmentManager();
28 | ...
29 | OpeningHoursFragment openingHoursDialog = OpeningHoursFragment.newInstanceForFragment(key,finalValue, R.style.Theme_AppCompat_Light_Dialog_Alert, -1, true);
30 | openingHoursDialog.show(fm, "fragment_opening_hours");
31 | ```
32 |
33 | The calling Fragment needs to implement ch.poole.openinghoursfragement.OnSaveListener which will be used when the user saves a OH value. Have a look at the test app for a working trivial example.
34 |
35 | For other variants please see the javadoc.
36 |
37 | If you are overriding onActivityResult in the Activity calling the Fragment, you need to check that you calling through to super, or else loading and saving templates will fail silently.
38 |
39 | ## Including in your project
40 |
41 | Add the following to your *build.gradle* file(s):
42 |
43 | ``` groovy
44 | repositories {
45 | maven {
46 | mavenCentral()
47 | }
48 | }
49 | ```
50 |
51 | ``` groovy
52 | dependencies {
53 | compile "ch.poole:OpeningHoursFragment:0.15.1"
54 | }
55 | ```
56 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/timerangepicker.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
30 |
44 |
45 |
63 |
79 |
80 |
--------------------------------------------------------------------------------
/lib/src/androidTest/java/ch/poole/openinghoursfragment/TextInputTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
3 | * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | */
5 |
6 | package ch.poole.openinghoursfragment;
7 |
8 | import static org.junit.Assert.assertNotNull;
9 | import static org.junit.Assert.fail;
10 |
11 | import org.junit.Before;
12 | import org.junit.Rule;
13 | import org.junit.Test;
14 | import org.junit.runner.RunWith;
15 |
16 | import android.app.Instrumentation;
17 | import android.view.KeyEvent;
18 | import androidx.fragment.app.Fragment;
19 | import androidx.fragment.app.FragmentManager;
20 | import androidx.fragment.app.FragmentTransaction;
21 | import androidx.test.ext.junit.runners.AndroidJUnit4;
22 | import androidx.test.filters.LargeTest;
23 | import androidx.test.platform.app.InstrumentationRegistry;
24 | import androidx.test.rule.ActivityTestRule;
25 | import androidx.test.uiautomator.UiDevice;
26 | import androidx.test.uiautomator.UiObject;
27 | import androidx.test.uiautomator.UiObjectNotFoundException;
28 | import androidx.test.uiautomator.UiSelector;
29 | import androidx.test.uiautomator.Until;
30 |
31 | @RunWith(AndroidJUnit4.class)
32 | @LargeTest
33 | public class TextInputTest {
34 |
35 | private OpeningHoursFragment fragment;
36 | private UiDevice device;
37 | private Instrumentation instrumentation;
38 |
39 | @Rule
40 | public ActivityTestRule mActivityRule = new ActivityTestRule<>(TestActivity.class);
41 |
42 | @Before
43 | public void setup() {
44 | instrumentation = InstrumentationRegistry.getInstrumentation();
45 | device = UiDevice.getInstance(instrumentation);
46 |
47 | FragmentManager fm = mActivityRule.getActivity().getSupportFragmentManager();
48 | FragmentTransaction ft = fm.beginTransaction();
49 | Fragment prev = fm.findFragmentByTag("fragment_openinghours");
50 | if (prev != null) {
51 | ft.remove(prev);
52 | }
53 | ft.commit();
54 |
55 | ValueWithDescription key = new ValueWithDescription("opening_hours", "Opening hours");
56 |
57 | fragment = OpeningHoursFragment.newInstance(key, null, null, null, R.style.Theme_DialogLight, 5, false, null, null);
58 | fragment.show(fm, "fragment_openinghours");
59 | UiSelector uiSelector = new UiSelector().resourceIdMatches(".*more.*");
60 | UiObject fab = device.findObject(uiSelector);
61 | try {
62 | fab.click();
63 | TestUtils.clickText(device, false, fragment.getString(R.string.clear), true);
64 | } catch (UiObjectNotFoundException e) {
65 | fail(e.getMessage());
66 | }
67 | }
68 |
69 | @Test
70 | public void twentyfourseven() {
71 | UiSelector uiSelector = new UiSelector().resourceIdMatches(".*openinghours_string_edit.*");
72 | UiObject text = device.findObject(uiSelector);
73 | try {
74 | text.click();
75 | device.pressKeyCode(KeyEvent.KEYCODE_2);
76 | device.pressKeyCode(KeyEvent.KEYCODE_4);
77 | device.pressKeyCode(KeyEvent.KEYCODE_SLASH);
78 | device.pressKeyCode(KeyEvent.KEYCODE_7);
79 | device.pressEnter();
80 | device.performActionAndWait(()->{}, Until.newWindow(), 1000);
81 | } catch (UiObjectNotFoundException e) {
82 | fail(e.getMessage());
83 | }
84 | assertNotNull(TestUtils.findText(device, false, fragment.getString(R.string.twentyfourseven)));
85 | }
86 | }
--------------------------------------------------------------------------------
/lib/src/main/res/layout/time_end_event_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
23 |
24 |
48 |
49 |
59 |
60 |
69 |
74 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/lib/documentation/docs/help/zh-rTW/Opening hours.md:
--------------------------------------------------------------------------------
1 | # 開放街圖營業時間編輯器
2 |
3 | OpenStreetMap 營業時間規範相當複雜,並不易於一個簡單直觀的使用者介面。
4 |
5 | 然而大部分的時候,你應該只會用到一小部分的定議。編輯器嘗試在選單中隱藏更加模糊的功能,來達成這一點,大部分的時候減少路上設定,儘可能用預先設定的模版,加以小量修改。
6 |
7 | _這份文件是初步的並且正在進展_
8 |
9 | ## 使用營業時間編輯器
10 |
11 | 在一般的工作流程中,你編輯的物件一般已經有開放時間的標籤 (opening_hour、service_times 和 colllection_times),或是你可以重新設定物件的預設組合,用空白的開放時間欄位。如果你需要手動輸入欄位,像是用 Vespucci,你可以在詳情頁面輸入鍵值,之後切換回欄位頁籤繼續編輯。如果你相信開放時間標籤必須扅於預設組合的話,請在你的編輯器開啟 issue。
12 |
13 | 如果你有定義預設模版(透過「管理模版」選項物件),編輯器啟動時空白值時將會自動載入。而用「載入模版」功能你可以載入任何儲存的模版,而用「儲存模版」選單則會儲存目前的值為模版。你可以定義分開的模版與為特定鍵設定為預設。例如說"opening_hours","collection_times" 與 "service_times" 或客製值。更進一步說你可以限制模版適用的區域與特定識別碼,特別是特定的 OSM 最高層級標籤 (例如 amenity=restaurant)。
14 |
15 | 當然,您可以從頭開始構建營業時間的值,但我們建議使用現有的模板之一作為起點。
16 |
17 | 如果已經有營業時間的數值則會載入,另外會自動修正以符合營業時間規範。如果無法修正,則會在大概的位置顯示錯誤訊息,原始的營業時間數值,等待人工修正。開放街圖資料庫中有大約1/4的營業時間數值有問題,但只有少於10%的狀況是無法修正。詳見 [OpeningHoursParser](https://github.com/simonpoole/OpeningHoursParser),並且看有那些允許的規範變體。
18 |
19 | ### 主選單按鈕
20 |
21 | * __增加規則__:增加一個新規則。
22 | * __增加假日規則__:國家改變時,為假日增加新的規則。
23 | * __為 24/7 增加規則__:為總是開放的物件增加規則,開放時間規範不支持任何其他子值為24/7,但我們允許增加更高階的選擇器 (例如年份範圍)。
24 | * __載入模板__:載入先有的模板。
25 | * __儲存至模板__:將現有的營業時間數值儲存為模板留待日後使用。
26 | * __管理模板__:編輯(如變更名稱)或刪除現有模板
27 | * __重新整理__:重新解析營業時間的數值。
28 | * __全部刪除__:刪除全部規則。
29 |
30 | ### 規則
31 |
32 | 預設規則會依 _normal_ rules 增加,意味將直接套用並且覆寫同一天原先規則的數值。這可能會為套用延伸時間規則帶來困擾,特別是你希望透過 _顯示規則類別_ 選單 _追加_ 轉換規則。
33 |
34 | #### 規則選單
35 |
36 | * __增加修飾符/註釋__:更改此規則的效果並增加可選擇的註釋。
37 | * __增加假日__:為公衆假期或學校假期增加選取器。
38 | * __增加時間跨度 ...__
39 | * __時間 - 時間__:同一天的開始時間到結束時間。
40 | * __時間 - 延長時間__:開始時間跨到隔天的結束時間 (例如 26:00 是隔天的 02:00 (am))。
41 | * __變化時間 - 時間__:從開始變化時間 (黎明,黃昏,日出和日落) 到同一天的結束時間。
42 | * __變化時間 - 延長時間__:從第二天起始變化時間到隔天的結束時間。
43 | * __時間 - 變化時間__:起啟時間到結束的變化時間
44 | * __變化時間 - 變化時間__:從起始變化時間到結束變化時間。
45 | * __時間__:特定的時間。
46 | * __時間-一直持續__:從起始時間一直持續。
47 | * __變化時間__:特定的變化時間
48 | * __變化時間 - 一直持續__:從變化時間到一直持續
49 | * __增加週間範圍__:增加以週間為依據的選擇器。
50 | * __增加日期範圍...__
51 | * __日期 - 日期__:從開始日期 (年、月、日) 到結束日期。
52 | * __變化日期 - 日期__:從起始變化日期 (目前規範僅定義_復活節_) 到結束日期。
53 | * __日期 - 變化日期__:從開始日期到變化日期。
54 | * __變化日期 - 變化日期__:從起始變化日期到結束變化日期。
55 | * __發生在月中-發生在月中__:一個月中從開始的週間是相同的。
56 | * __發生在月中 - 日期__:一個月中週間發生,到特定結束日期。
57 | * __日期 - 發生在月中__:從開始日舒到一個月中的週間結束。
58 | * __發生在月中 - 變動日期__:從一個月開始週間發生,到變動日期。
59 | * __變動日期 - 發生在月中__:從開始的變動日期,到一個月中的週間。
60 | * __日期 - 開放結束__:從開始日期起。
61 | * __日期變化 - 開端__:從起始變化日期開始。
62 | * __發生在月中 - 一直持續__:從一個月中開始週間發生。
63 | * __使用偏差量...__:與上述相同的內容,但是指定了偏差量 (這很少使用)。
64 | * __增加年範圍...__
65 | * __增加年範圍__:增加以年為依據的選擇器。
66 | * __增加啟始年__: 增加一整年範圍。
67 | * __增加週範圍__:增加以週為依據的選擇器。
68 | * __複製__:複製此規則,並且插入目前位置之後。
69 | * __顯示規則類型__:顯示並允許更改規則類型_正常_,_增加_和_倒退_(位於第一條規則中不可用)。
70 | * __向上移動__:將此規則向上移動一個位置(位於第一條規則時不可用)。
71 | * __向下移動__:將此規則向下移動一個位置。
72 | * __刪除__:刪除此一規則。
73 |
74 | ### 時間跨度
75 |
76 | 要讓編輯時間刻度變得更簡單可行,我們嘗試選擇最佳時間範圍,加載現有值時範圍欄的刻度。對新的時間刻度來說,欄從6:00(am)開始,然後每15分鐘增加。上述的設定可以在選單更改。
77 |
78 | 當你直接用時間軸太困難時,點 (不是在別針上) 在時間軸上,會打開比較大的時間檢取器。時間檢取器會延伸到下一天,所有簡單的方式延長時間區間,但不用刪除再加區間。
79 |
80 | #### 時間跨度選單
81 |
82 | * __顯示時間檢取器__:顯示更大的時間檢取器來開始和結束時間,在非常小的裝置上,則有更好的方式改變時間。
83 | * __切換到15分鐘刻度__:對範圍欄使用15分鐘刻度。
84 | * __切換到5分鐘刻度__:對範圍欄使用5分鐘的刻度。
85 | * __切換到1分鐘刻度__:對範圍欄使用1分鐘的刻度,很難在手機上使用。
86 | * __從午夜開始__:午夜開始範圍欄。
87 | * __顯示間隔__:顯示指定間隔(以分鐘為單位)的間隔字段。
88 | * __刪除__:刪除此一時間跨度。
89 |
90 | ### 管理模版
91 |
92 | 模版管理對話框允許你新增、編輯與刪除模版。
93 |
94 | 在 Android 4.4 以及之後的版本 下列的新增功能都能從選單按鈕進去。
95 |
96 | * __Show all__: 顯示資料庫中所有的模版。
97 | * __Save to file__: 寫入模版資料庫的內容到檔案。
98 | * __Load from file (replace)__: 從檔案載入模版並且取代目前資料庫的內容。
99 | * __Load from file__: 從檔案載入模版並且保留目前的內容。
100 |
101 | #### 儲存與編輯模版對話框
102 |
103 | 對話框允許設定
104 |
105 | * __Name__ 模版描述性的名稱。
106 | * __Default__ 如果選取的話則會設定為預設模版 (通常會被其他欄位限制)。
107 | * __Key__ 鍵這模版如果設定 _Custom key_,則會與這個模版相關,你可以在以下的欄位新增非標準的值。鍵的值支援 SQL wild cards,意味 _%_ 符合零或更多字元,*_* 則符合單一字元。所有 wild card 字元都能用 _\\_ 來逃離字面的符合。
108 | * __Region__ 模版適用的區域。
109 | * __Object__ 用於符合的應用程式特定的字元。
110 |
111 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/year_range.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
21 |
29 |
39 |
47 |
55 |
63 |
68 |
69 |
77 |
82 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/lib/src/test/java/ch/poole/openinghoursfragment/templates/TemplatesDatabaseTest.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.templates;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 | import static org.junit.Assert.fail;
6 |
7 | import org.junit.After;
8 | import org.junit.Before;
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 | import org.robolectric.RobolectricTestRunner;
12 |
13 | import android.database.Cursor;
14 | import androidx.test.core.app.ApplicationProvider;
15 | import androidx.test.filters.LargeTest;
16 |
17 | @RunWith(RobolectricTestRunner.class)
18 | @LargeTest
19 | public class TemplatesDatabaseTest {
20 | TemplateDatabaseHelper db;
21 |
22 | /**
23 | * Pre-test setup
24 | */
25 | @Before
26 | public void setup() {
27 | ApplicationProvider.getApplicationContext().deleteDatabase(TemplateDatabaseHelper.DATABASE_NAME);
28 | db = new TemplateDatabaseHelper(ApplicationProvider.getApplicationContext());
29 | }
30 |
31 | /**
32 | * Post-test teardown
33 | */
34 | @After
35 | public void teardown() {
36 | db.close();
37 | ApplicationProvider.getApplicationContext().deleteDatabase(TemplateDatabaseHelper.DATABASE_NAME);
38 | }
39 |
40 | /**
41 | * Query by key test
42 | */
43 | @Test
44 | public void queryByKeyTest() {
45 | try (Cursor cursor = TemplateDatabase.queryBy(db.getReadableDatabase(), "opening_hours", null, null)) {
46 | assertEquals(5, cursor.getCount());
47 | }
48 | TemplateDatabase.add(db.getWritableDatabase(), "opening_hours", "test entry", true, "Mo-Fr 09:00-12:00,13:30-18:30;Sa 09:00-17:00;PH closed", null,
49 | null);
50 | try (Cursor cursor = TemplateDatabase.queryBy(db.getReadableDatabase(), "opening_hours", null, null)) {
51 | assertEquals(6, cursor.getCount());
52 | }
53 | try (Cursor cursor = TemplateDatabase.queryBy(db.getReadableDatabase(), "opening1hours", null, null)) {
54 | assertEquals(6, cursor.getCount());
55 | }
56 | TemplateDatabase.add(db.getWritableDatabase(), "opening\\_hours", "test entry", true, "Mo-Fr 09:00-12:00,13:30-18:30;Sa 09:00-17:00;PH closed", null,
57 | null);
58 | try (Cursor cursor = TemplateDatabase.queryBy(db.getReadableDatabase(), "opening_hours", null, null)) {
59 | assertEquals(7, cursor.getCount());
60 | }
61 | try (Cursor cursor = TemplateDatabase.queryBy(db.getReadableDatabase(), "opening1hours", null, null)) {
62 | assertEquals(6, cursor.getCount());
63 | }
64 | }
65 |
66 | /**
67 | * Query by region test
68 | */
69 | @Test
70 | public void queryByRegionTest() {
71 | TemplateDatabase.add(db.getWritableDatabase(), null, "test entry", true, "Mo-Fr 09:00-12:00,13:30-18:30;Sa 09:00-17:00;PH closed", "CH", null);
72 | try (Cursor cursor = TemplateDatabase.queryBy(db.getReadableDatabase(), null, null, null)) {
73 | assertEquals(7, cursor.getCount());
74 | }
75 | TemplateDatabase.add(db.getWritableDatabase(), null, "test entry", true, "Mo-Fr 09:00-12:00,13:30-18:30;Sa 09:00-17:00;PH closed", "DE", null);
76 | try (Cursor cursor = TemplateDatabase.queryBy(db.getReadableDatabase(), null, null, null)) {
77 | assertEquals(8, cursor.getCount());
78 | }
79 | try (Cursor cursor = TemplateDatabase.queryBy(db.getReadableDatabase(), null, "CH", null)) {
80 | assertEquals(7, cursor.getCount());
81 | }
82 | }
83 |
84 | /**
85 | * Default test
86 | */
87 | @Test
88 | public void defaultTest() {
89 | assertEquals("Mo-Fr 09:00-12:00,13:30-18:30;Sa 09:00-17:00;PH closed",
90 | TemplateDatabase.getDefault(db.getReadableDatabase(), "opening_hours", null, null));
91 | TemplateDatabase.add(db.getWritableDatabase(), "opening_hours", "test entry", true, "test", null, null);
92 | assertEquals("test", TemplateDatabase.getDefault(db.getReadableDatabase(), "opening_hours", null, null));
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/templates/TemplateDatabaseHelper.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.templates;
2 |
3 | import android.content.Context;
4 | import android.database.SQLException;
5 | import android.database.sqlite.SQLiteDatabase;
6 | import android.database.sqlite.SQLiteOpenHelper;
7 | import android.util.Log;
8 | import ch.poole.openinghoursfragment.R;
9 |
10 | public class TemplateDatabaseHelper extends SQLiteOpenHelper {
11 | private static final String DEBUG_TAG = "TemplateDatabase";
12 | static final String DATABASE_NAME = "openinghours_templates";
13 | private static final int DATABASE_VERSION = 5;
14 |
15 | private final Context context;
16 |
17 | /**
18 | * Construct a new instance
19 | *
20 | * @param context Android Context
21 | */
22 | public TemplateDatabaseHelper(final Context context) {
23 | super(context, DATABASE_NAME, null, DATABASE_VERSION);
24 | this.context = context;
25 | }
26 |
27 | @Override
28 | public void onCreate(SQLiteDatabase db) {
29 | try {
30 | db.execSQL(
31 | "CREATE TABLE templates (key TEXT DEFAULT NULL, name TEXT, is_default INTEGER DEFAULT 0, template TEXT DEFAULT '', region TEXT DEFAULT NULL, object TEXT DEFAULT NULL)");
32 | TemplateDatabase.add(db, null, context.getString(R.string.weekdays_with_lunch), true, "Mo-Fr 09:00-12:00,13:30-18:30;Sa 09:00-17:00;PH closed",
33 | null, null);
34 | TemplateDatabase.add(db, null, context.getString(R.string.weekdays_with_lunch_late_shopping), false,
35 | "Mo,Tu,Th,Fr 09:00-12:00,13:30-18:30;We 09:00-12:00,13:30-20:00;Sa 09:00-17:00;PH closed", null, null);
36 | TemplateDatabase.add(db, null, context.getString(R.string.weekdays), false, "Mo-Fr 09:00-18:30;Sa 09:00-17:00;PH closed", null, null);
37 | TemplateDatabase.add(db, null, context.getString(R.string.weekdays_late_shopping), false,
38 | "Mo,Tu,Th,Fr 09:00-18:30;We 09:00-20:00;Sa 09:00-17:00;PH closed", null, null);
39 | TemplateDatabase.add(db, null, context.getString(R.string.twentyfourseven), false, "24/7", null, null);
40 | TemplateDatabase.add(db, "collection\\_times", context.getString(R.string.collection_times_weekdays), true, "Mo-Fr 09:00; Sa 07:00; PH closed",
41 | null, null);
42 | } catch (SQLException e) {
43 | Log.w(DEBUG_TAG, "Problem creating database", e);
44 | }
45 | }
46 |
47 | @Override
48 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
49 | Log.d(DEBUG_TAG, "Upgrading database from version " + oldVersion + " to " + newVersion);
50 | if (oldVersion <= 1 && newVersion >= 2) {
51 | db.execSQL("ALTER TABLE templates ADD COLUMN key TEXT DEFAULT NULL");
52 | TemplateDatabase.add(db, "collection_times", context.getString(R.string.collection_times_weekdays), true, "Mo-Fr 09:00; Sa 07:00; PH closed", null,
53 | null);
54 | }
55 | if (oldVersion <= 2 && newVersion >= 3) {
56 | TemplateDatabase.add(db, null, context.getString(R.string.weekdays_with_lunch_late_shopping), false,
57 | "Mo,Tu,Th,Fr 09:00-12:00,13:30-18:30;We 09:00-12:00,13:30-20:00;Sa 09:00-17:00;PH closed", null, null);
58 | TemplateDatabase.add(db, null, context.getString(R.string.weekdays_late_shopping), false,
59 | "Mo,Tu,Th,Fr 09:00-18:30;We 09:00-20:00;Sa 09:00-17:00;PH closed", null, null);
60 | TemplateDatabase.add(db, null, context.getString(R.string.twentyfourseven), false, "24/7", null, null);
61 | }
62 | if (oldVersion <= 3 && newVersion >= 4) {
63 | db.execSQL("ALTER TABLE templates ADD COLUMN region TEXT DEFAULT NULL");
64 | db.execSQL("ALTER TABLE templates ADD COLUMN object TEXT DEFAULT NULL");
65 | }
66 | if (oldVersion <= 4 && newVersion >= 5) {
67 | db.rawQuery("SELECT REPLACE('key','_','\\_')", null);
68 | db.rawQuery("SELECT REPLACE('key',':','\\:')", null);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/testapp/src/main/java/ch/poole/ohfragmenttest/TestFragment.java:
--------------------------------------------------------------------------------
1 | package ch.poole.ohfragmenttest;
2 |
3 | import java.util.ArrayList;
4 |
5 | import android.annotation.SuppressLint;
6 | import android.content.Context;
7 | import android.os.Bundle;
8 | import androidx.annotation.NonNull;
9 | import androidx.fragment.app.DialogFragment;
10 | import androidx.fragment.app.Fragment;
11 | import androidx.fragment.app.FragmentActivity;
12 | import androidx.fragment.app.FragmentManager;
13 | import androidx.fragment.app.FragmentTransaction;
14 | import androidx.appcompat.app.AlertDialog;
15 | import androidx.appcompat.app.AlertDialog.Builder;
16 | import androidx.appcompat.app.AppCompatDialog;
17 | import android.util.Log;
18 | import ch.poole.openinghoursfragment.OnSaveListener;
19 | import ch.poole.openinghoursfragment.OpeningHoursFragment;
20 | import ch.poole.openinghoursfragment.ValueWithDescription;
21 |
22 | public class TestFragment extends DialogFragment implements OnSaveListener {
23 |
24 | private static final String DEBUG_TAG = TestFragment.class.getSimpleName();
25 |
26 | private static final String TAG = "fragment_test";
27 |
28 | private static final String KEY_OH = "oh";
29 |
30 | /**
31 |
32 | */
33 | static public void showDialog(FragmentActivity activity, String oh) {
34 | dismissDialog(activity);
35 | try {
36 |
37 | FragmentManager fm = activity.getSupportFragmentManager();
38 | TestFragment testFragment = newInstance(oh);
39 | testFragment.show(fm, TAG);
40 | } catch (IllegalStateException isex) {
41 | Log.e(DEBUG_TAG, "showDialog", isex);
42 | }
43 | }
44 |
45 | private static void dismissDialog(FragmentActivity activity) {
46 | try {
47 | FragmentManager fm = activity.getSupportFragmentManager();
48 | FragmentTransaction ft = fm.beginTransaction();
49 | Fragment fragment = fm.findFragmentByTag(TAG);
50 | if (fragment != null) {
51 | ft.remove(fragment);
52 | }
53 | ft.commit();
54 | } catch (IllegalStateException isex) {
55 | Log.e(DEBUG_TAG, "dismissDialog", isex);
56 | }
57 | }
58 |
59 | /**
60 | */
61 | static private TestFragment newInstance(String oh) {
62 | TestFragment f = new TestFragment();
63 |
64 | Bundle args = new Bundle();
65 | args.putSerializable(KEY_OH, oh);
66 |
67 | f.setArguments(args);
68 | f.setShowsDialog(true);
69 |
70 | return f;
71 | }
72 |
73 | private String oh;
74 |
75 | @Override
76 | public void onAttach(Context context) {
77 | super.onAttach(context);
78 | Log.d(DEBUG_TAG, "onAttach");
79 | }
80 |
81 | @Override
82 | public void onCreate(Bundle savedInstanceState) {
83 | super.onCreate(savedInstanceState);
84 | setCancelable(true);
85 | }
86 |
87 | @NonNull
88 | @SuppressLint("InflateParams")
89 | @Override
90 | public AppCompatDialog onCreateDialog(Bundle savedInstanceState) {
91 |
92 | Builder builder = new AlertDialog.Builder(getActivity());
93 | builder.setTitle("test fragment mode");
94 | oh = getArguments().getString(KEY_OH);
95 |
96 | builder.setPositiveButton(android.R.string.ok, null);
97 |
98 | return builder.create();
99 | }
100 |
101 | @Override
102 | public void onStart() {
103 | super.onStart();
104 | ArrayList textValues = new ArrayList<>();
105 | ValueWithDescription textValue = new ValueWithDescription("test_value", "Test description");
106 | textValues.add(textValue);
107 | OpeningHoursFragment openingHoursDialog = OpeningHoursFragment.newInstanceForFragment(new ValueWithDescription("fee", null), oh,
108 | ch.poole.openinghoursfragment.R.style.Theme_DialogLight, 5, false, textValues);
109 | FragmentManager fm = getChildFragmentManager();
110 | openingHoursDialog.show(fm, "fragment_openinghours");
111 | }
112 |
113 | @Override
114 | public void save(String key, String openingHours) {
115 | Log.d("TestFragment", "save got " + openingHours + " for key " + key);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-pt-rBR/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Cancelar
5 | OK
6 | Salvar
7 | Feito
8 | Adicionar regra
9 | Adicionar regra para 24/7
10 | Adicionar regra para feriados
11 | Carregar modelo
12 | Salvar para modelo
13 | Gerenciar modelos
14 | Atualizar
15 | Excluir tudo
16 | Carregar modelos
17 | Gerenciar modelos
18 | Salvar modelo
19 | Sim
20 | Não
21 | Início
22 | End
23 |
24 |
25 | Editar modelo
26 | Nome:
27 | Padrão:
28 | Chave:
29 | %1$s (padrão)
30 | %1$s %2$s
31 | Tudo
32 | Horário
33 | Tempos de coleta
34 | Supervisionado
35 | Iluminado
36 |
37 | Grupo%1$s
38 | Regra%1$s
39 |
40 | Duplicado
41 |
42 |
43 | Normal
44 | Aditivo
45 | Intervalo (minutos)
46 | Intervalo (anos)
47 | Intervalo (semanas)
48 |
49 | Intervalo de datas
50 | Data
51 | Semanas
52 | Anos
53 | Modificador
54 | Comentário
55 |
56 | 24 horas, 7 dias por semana
57 |
58 | até
59 |
60 | Páscoa
61 |
62 | Nascer do sol
63 | Pôr do sol
64 | Alvorada
65 | Crepúsculo
66 |
67 | Feriados públicos
68 | Feriados escolares
69 |
70 | Seg
71 | Ter
72 | Qua
73 | Qui
74 | Sex
75 | Sáb
76 | Dom
77 |
78 | Jan
79 | Fev
80 | Mar
81 | Abr
82 | Mai
83 | Jun
84 | Jul
85 | Ago
86 | Set
87 | Out
88 | Nov
89 | Dez
90 |
91 | aberto
92 | fechado
93 | desconhecido
94 |
95 | antes
96 | depois
97 |
98 |
99 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/week_range.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
20 |
28 |
38 |
46 |
53 |
61 |
66 |
67 |
74 |
79 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/time_event_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
22 |
23 |
35 |
36 |
48 |
49 |
58 |
63 |
72 |
73 |
82 |
87 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/pickers/ValuePicker.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.pickers;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.DialogInterface;
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import androidx.annotation.NonNull;
9 | import androidx.appcompat.app.AlertDialog.Builder;
10 | import androidx.appcompat.app.AppCompatDialog;
11 | import androidx.fragment.app.Fragment;
12 | import androidx.fragment.app.FragmentManager;
13 | import ch.poole.openinghoursfragment.CancelableDialogFragment;
14 | import ch.poole.openinghoursfragment.R;
15 | import ch.poole.openinghoursfragment.Util;
16 | import ch.poole.android.numberpickerview.library.NumberPickerView;
17 |
18 | /**
19 | * Display a dialog allowing the user to set a single numeric value
20 | *
21 | */
22 | public class ValuePicker extends CancelableDialogFragment {
23 | public static final int NOTHING_SELECTED = Integer.MIN_VALUE;
24 |
25 | private static final String TITLE_KEY = "title";
26 | private static final String MIN_KEY = "min";
27 | private static final String MAX_KEY = "max";
28 | private static final String CURRENT_KEY = "current";
29 | private static final String STYLE_RES = "styleRes";
30 |
31 | private static final String TAG = "fragment_valuepicker";
32 |
33 | /**
34 | * Show the range picker dialog
35 | *
36 | * @param parentFragment Fragment that called this
37 | * @param title resource id for the title to display
38 | * @param min minimum range value
39 | * @param max maximum range value
40 | * @param current initial value
41 | * @param styleRes resource id for style/theme
42 | */
43 | public static void showDialog(Fragment parentFragment, int title, int min, int max, int current, int styleRes) {
44 | dismissDialog(parentFragment, TAG);
45 |
46 | FragmentManager fm = parentFragment.getChildFragmentManager();
47 | ValuePicker valuePickerFragment = newInstance(title, min, max, current, styleRes);
48 | valuePickerFragment.show(fm, TAG);
49 | }
50 |
51 | /**
52 | * Create a new instance of RangePicker
53 | *
54 | * @param title resource id for the title to display
55 | * @param min minimum range value
56 | * @param max maximum range value
57 | * @param current initial value
58 | * @param styleRes resource id for style/theme
59 | * @return an instance of ValuePicker
60 | */
61 | private static ValuePicker newInstance(int title, int min, int max, int current, int styleRes) {
62 | ValuePicker f = new ValuePicker();
63 | Bundle args = new Bundle();
64 | args.putInt(TITLE_KEY, title);
65 | args.putInt(MIN_KEY, min);
66 | args.putInt(MAX_KEY, max);
67 | args.putInt(CURRENT_KEY, current);
68 | args.putInt(STYLE_RES, styleRes);
69 |
70 | f.setArguments(args);
71 | f.setShowsDialog(true);
72 |
73 | return f;
74 | }
75 |
76 | @NonNull
77 | @SuppressLint("InflateParams")
78 | @Override
79 | public AppCompatDialog onCreateDialog(Bundle savedInstanceState) {
80 | int title = getArguments().getInt(TITLE_KEY);
81 | final int min = getArguments().getInt(MIN_KEY);
82 | final int max = getArguments().getInt(MAX_KEY);
83 | int current = getArguments().getInt(CURRENT_KEY);
84 | final SetRangeListener listener = (SetRangeListener) getParentFragment();
85 |
86 | Builder builder = Util.getAlertDialogBuilder(getContext(), getArguments().getInt(STYLE_RES));
87 | builder.setTitle(title);
88 |
89 | final LayoutInflater inflater = getActivity().getLayoutInflater();
90 |
91 | View layout = inflater.inflate(R.layout.valuepicker, null);
92 | builder.setView(layout);
93 |
94 | String[] startValues = new String[max - min + 1];
95 | for (int i = min; i <= max; i++) {
96 | startValues[i - min] = Integer.toString(i);
97 | }
98 | final NumberPickerView npvStart = (NumberPickerView) layout.findViewById(R.id.start);
99 | npvStart.setDisplayedValues(startValues);
100 | npvStart.setMinValue(min);
101 | npvStart.setMaxValue(max);
102 | npvStart.setValue(current);
103 |
104 | builder.setPositiveButton(R.string.spd_ohf_ok, (DialogInterface dialog, int which) -> listener.setRange(npvStart.getValue(), -1));
105 | builder.setNeutralButton(R.string.spd_ohf_cancel, null);
106 |
107 | return builder.create();
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/CHANGELOG.txt:
--------------------------------------------------------------------------------
1 | Please see the github repository for a complete list of changes: https://github.com/simonpoole/OpeningHoursFragment/commits/master
2 |
3 | 0.16.0:
4 |
5 | - Use the provided style for AlertDialog creation
6 | - Add method method for displaying the template management modal with a provided style/theme id.
7 |
8 | 0.15.0:
9 |
10 | - Bump the minimum API to 21 and target API 35.
11 | - Fix for default template loading.
12 |
13 | 0.14.3:
14 |
15 | - Properly constrain selection position when clicking on error message
16 |
17 | 0.14.2:
18 |
19 | - Always run rebuild
20 |
21 | 0.14.1:
22 |
23 | - Fix regression where changes in OH mode wouldn't update the value
24 |
25 | 0.14.0:
26 |
27 | - Improve messaging when updating template
28 | - Improve behaviour when entering/correcting OH text directly
29 | - Fix CI
30 | - Display a message if the user didn't select a file
31 | - Update translations
32 |
33 | 0.13.5:
34 | - Migrate to hard fork of NumberPickerView
35 |
36 | 0.13.4:
37 | - Check that token is actually present in exceptions
38 |
39 | 0.13.3:
40 | - Save the value of useFragmentCallback
41 |
42 | 0.13.2:
43 | - Fix fragment mode if onAttach is called before onCreateView
44 |
45 | 0.13.0:
46 | - Support running as a 1 level deep nested Fragment
47 | - Update translations
48 |
49 | 0.12.0:
50 | - Update parser dependency
51 |
52 | 0.11.0:
53 | - Support custom key values in templates with SQL wild cards
54 | - Update translations
55 |
56 | 0.10.1:
57 | - Always set the editor action listener
58 | - Set IME options to actionDone.
59 |
60 | 0.10.0:
61 | - Don't automatically up date form from string, wait for "Enter" or the like.
62 | - Add support for open ended year ranges.
63 | - Update parser dependency.
64 | - Improve CI.
65 | - Publish on maven central
66 |
67 | 0.9.3:
68 | - Update number picker view and rangebar dependencies
69 |
70 | 0.9.2:
71 | - Update translations
72 |
73 | 0.9.1:
74 | - Move to sonatype / maven central for publishing
75 |
76 | 0.9.0:
77 | - Multi-error support
78 |
79 | 0.8.2:
80 | - Update parser dependency
81 | - Update translations.
82 |
83 | 0.8.1:
84 | - Update parser dependency
85 | - Update translations.
86 |
87 | 0.8.0:
88 | - Migrate to androidx.
89 |
90 | 0.7.0:
91 | - Update parser dependency
92 | - Add locale parameter to factory methods
93 | - Add error message display
94 | - Use current year as default start year for new date ranges.
95 |
96 | 0.6.8:
97 | - Fix issue with using description instead of value in mixed mode.
98 |
99 | 0.6.5:
100 | - Call through to onDismiss in the TemplateManagementDialog, fixes crash in onResume in the parent activity.
101 |
102 | 0.6.4:
103 | - Update Rangebar to 1.5 the previous version had issues with handling clicks on real devices.
104 |
105 | 0.6.3:
106 | - Fix various small issues which turned up when integrating the new functionality in 0.6 with Vespucci.
107 |
108 | 0.5.5:
109 | - Translation improvements.
110 |
111 | 0.5.4:
112 | - Update translations.
113 |
114 | 0.5.3:
115 | - Fix issue with day offsets not being displayed for end dates
116 | - Update translations.
117 |
118 | 0.5.2:
119 | - Enable RTL support (but there are no such translations currently)
120 | - Show templates for specific key at top of list
121 | - Update translations.
122 |
123 | 0.5.1:
124 | - Properly enable save button
125 |
126 | 0.5.0:
127 | - Support showing the list of templates instead of applying the default for empty entries
128 | - Support for mixed type values
129 |
130 | 0.4.2:
131 | - Protect against NPW when enabling save button
132 |
133 | 0.4.1:
134 | - When displaying extended times use "normal" times when possible
135 |
136 | 0.3.5:
137 | - Make dialog fill all available space
138 | - Update support lib and build target
139 |
140 | 0.3.4:
141 | - Protect again NPE
142 |
143 | 0.3.2:
144 | - Fix clearing if string can't be parsed
145 |
146 | 0.3.0:
147 | - Add facilities to duplicate rules and clear existing ones completely
148 |
149 | 0.2.2:
150 | - Support wrap around weekday ranges
151 |
152 | 0.2.1:
153 | - Support "occurrence in month" notation for dates
154 | - Bug fixes
155 |
156 | 0.2.0:
157 | - Support callbacks to a Fragment
158 | - Support separate templates for the major OH like keys
159 |
160 | 0.1.12:
161 | - Show negative day offsets for dates correctly
162 |
163 | 0.1.11:
164 | - Don't overwrite invalid strings when adding a rule
165 | - Try to avoid serialsation issues
166 |
167 | 0.1.10:
168 | - Protect against NPE when adding new rule to invalid string
169 |
170 | 0.1.9:
171 | - User the display string for variable dates (Easter)
172 |
173 | 0.1.8:
174 | - Enforce OSM 255 char tag length restriction
175 |
176 | 0.1.6:
177 | - Add shortcut for adding holidays.
178 |
179 | 0.1.5:
180 | - Typo fixes
181 | - Add missing dependencies to pom file.
182 |
183 | 0.1.4:
184 | - Improved documentation
185 | - Added missing time span menu item.
186 |
187 | 0.1.3:
188 | - First semi-public release.
--------------------------------------------------------------------------------
/lib/src/main/res/values-ko/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 취소
5 | 확인
6 | 저장
7 | 완료
8 | 여는 시간 값의 길이가 최대 255자를 넘는 %1$d자입니다.\n\n저장하기 전에 문자열을 간단히 해주세요!
9 | 올바르지 않는 여는 시간 문자열로 규칙을 추가할 수 없습니다. 정정하거나 삭제해주세요!
10 |
11 | 규칙 추가
12 | 휴일에 대한 규칙 추가
13 | 템플릿 불러오기
14 | 템플릿으로 저장
15 | 템플릿 관리
16 | 새로 고침
17 | 템플릿 불러오기
18 | 템플릿 관리
19 | 템플릿 저장
20 | 예
21 | 아니오
22 | 시작
23 | 끝
24 |
25 | 템플릿 편집
26 | 이름:
27 | 기본값:
28 | 키:
29 | %1$s (기본값)
30 | 모두
31 | 여는 시간
32 | 서비스 시간
33 | 감독 장소
34 | 조명
35 |
36 | 그룹 %1$s
37 | 규칙 %1$s
38 |
39 |
40 | 기본 템플릿 불러옴
41 |
42 |
43 | 삭제
44 | 수정자/댓글 추가
45 | 주 범위 추가
46 | 휴일 추가
47 |
48 | 시간
49 | 자정에 시작
50 |
51 | 날짜 범위 추가 ...
52 | 오프셋과 함께...
53 |
54 | 년 범위 추가
55 | 규칙 유형 보이기
56 | 위로 이동
57 | 아래로 이동
58 | 시간 픽커 표시
59 | 오프셋 보이기
60 | 시작 오프셋 보이기
61 | 끝 오프셋 보이기
62 | 간격 보이기
63 | 사용 보이기
64 |
65 |
66 |
67 | 보통
68 | 폴백
69 |
70 | 간격 (분)
71 | 간격 (년)
72 | 간격 (주)
73 |
74 | 오프셋 (±분)
75 | 오프셋 (±일)
76 |
77 | 날짜 범위
78 | 날짜
79 | 주 범위
80 | 주
81 | 년 범위
82 | 년
83 | 수정자
84 | 댓글
85 |
86 | 까지
87 |
88 | 공휴일
89 | 학교 휴일
90 |
91 | 월
92 | 화
93 | 수
94 | 목
95 | 금
96 | 토
97 | 일
98 |
99 | 1월
100 | 2월
101 | 3월
102 | 4월
103 | 5월
104 | 6월
105 | 7월
106 | 8월
107 | 9월
108 | 10월
109 | 11월
110 | 12월
111 |
112 | 열림
113 | 닫음
114 | 끄기
115 | 알 수 없음
116 |
117 | 이전
118 | 이후
119 |
120 |
121 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/time_start_event_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
21 |
22 |
32 |
33 |
42 |
47 |
56 |
57 |
58 |
83 |
84 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/daterange_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
16 |
17 |
23 |
24 |
32 |
39 |
44 |
51 |
57 |
64 |
65 |
76 |
84 |
91 |
96 |
103 |
109 |
116 |
117 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/template_item.xml:
--------------------------------------------------------------------------------
1 |
2 | >
11 |
19 |
29 |
37 |
51 |
59 |
72 |
82 |
90 |
102 |
110 |
119 |
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/Util.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Rect;
7 | import android.util.Log;
8 | import android.view.ContextThemeWrapper;
9 | import android.view.Gravity;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.widget.ScrollView;
13 | import android.widget.Spinner;
14 | import android.widget.TextView;
15 | import android.widget.Toast;
16 | import androidx.annotation.NonNull;
17 | import androidx.annotation.Nullable;
18 | import androidx.appcompat.app.AlertDialog;
19 | import androidx.core.widget.NestedScrollView;
20 |
21 |
22 | public final class Util {
23 | protected static final String DEBUG_TAG = "Util";
24 |
25 | /**
26 | * Private default constructor
27 | */
28 | private Util() {
29 | // Empty
30 | }
31 |
32 | /**
33 | * Scroll to the supplied view
34 | *
35 | * This code is from vespucci and licensed under the Apache 2.0 licence
36 | *
37 | * @author simon
38 | *
39 | * @param sv the ScrollView or NestedScrollView to scroll
40 | * @param row the row to display, if null scroll to top or bottom of sv
41 | * @param up if true scroll to top if row is null, otherwise scroll to bottom
42 | * @param force if true always try to scroll even if row is already on screen
43 | */
44 | public static void scrollToRow(@NonNull final View sv, @Nullable final View row, final boolean up, boolean force) {
45 | Rect scrollBounds = new Rect();
46 | sv.getHitRect(scrollBounds);
47 | if (row != null && row.getLocalVisibleRect(scrollBounds) && !force) {
48 | return; // already on screen
49 | }
50 | if (row == null) {
51 | sv.post(() -> {
52 | if (sv instanceof ScrollView) {
53 | ((ScrollView) sv).fullScroll(up ? View.FOCUS_UP : View.FOCUS_DOWN);
54 | } else if (sv instanceof NestedScrollView) {
55 | ((NestedScrollView) sv).fullScroll(up ? View.FOCUS_UP : View.FOCUS_DOWN);
56 | } else {
57 | Log.e(DEBUG_TAG, "scrollToRow unexpected view " + sv);
58 | }
59 | });
60 | } else {
61 | sv.post(() -> {
62 | final int target = up ? row.getTop() : row.getBottom();
63 | if (sv instanceof ScrollView) {
64 | ((ScrollView) sv).smoothScrollTo(0, target);
65 | } else if (sv instanceof NestedScrollView) {
66 | ((NestedScrollView) sv).smoothScrollTo(0, target);
67 | } else {
68 | Log.e(DEBUG_TAG, "scrollToRow unexpected view " + sv);
69 | }
70 | });
71 | }
72 | }
73 |
74 | /**
75 | * Display a toast at the top of the screen
76 | *
77 | * @param context android context
78 | * @param msg the message to display
79 | */
80 | public static void toastTop(@NonNull Context context, String msg) {
81 | LayoutInflater inflater = LayoutInflater.from(context);
82 | View layout = inflater.inflate(R.layout.toast, null);
83 | TextView text = (TextView) layout.findViewById(R.id.text);
84 | text.setText(msg);
85 | Toast toast = new Toast(context);
86 | toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0);
87 | toast.setDuration(Toast.LENGTH_LONG);
88 | toast.setView(layout);
89 | toast.show();
90 | }
91 |
92 | /**
93 | * Display a toast at the top of the screen
94 | *
95 | * @param context android context
96 | * @param msg the message resource id to display
97 | */
98 | public static void toastTop(@NonNull Context context, int msg) {
99 | LayoutInflater inflater = LayoutInflater.from(context);
100 | View layout = inflater.inflate(R.layout.toast, null);
101 | TextView text = (TextView) layout.findViewById(R.id.text);
102 | text.setText(msg);
103 | Toast toast = new Toast(context);
104 | toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0);
105 | toast.setDuration(Toast.LENGTH_LONG);
106 | toast.setView(layout);
107 | toast.show();
108 | }
109 |
110 | /**
111 | * Set initially selected value on a spinner
112 | *
113 | * @param res the Resources
114 | * @param valuesId the value array resource id
115 | * @param spinner the Spinner
116 | * @param value the value to set
117 | */
118 | public static void setSpinnerInitialEntryValue(@NonNull Resources res, int valuesId, @NonNull Spinner spinner, @Nullable String value) {
119 | final TypedArray values = res.obtainTypedArray(valuesId);
120 | for (int i = 0; i < values.length(); i++) {
121 | if ((value == null && "".equals(values.getString(i))) || (value != null && value.equals(values.getString(i)))) {
122 | spinner.setSelection(i);
123 | break;
124 | }
125 | }
126 | values.recycle();
127 | }
128 |
129 | /**
130 | * Get a correctly themed AlerDialog.Builder
131 | *
132 | * @param context an Android Context
133 | * @param themeRes theme to use, if -1 fallback to default
134 | * @return a AlerDialog.Builder
135 | */
136 | public static AlertDialog.Builder getAlertDialogBuilder(@NonNull Context context, int themeRes) {
137 | return new AlertDialog.Builder(new ContextThemeWrapper(context, themeRes > 0 ? themeRes : R.style.Theme_AlertDialog));
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/lib/src/androidTest/java/ch/poole/openinghoursfragment/templates/TemplatesTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
3 | * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | */
5 |
6 | package ch.poole.openinghoursfragment.templates;
7 |
8 | import static org.junit.Assert.assertNotNull;
9 | import static org.junit.Assert.assertNull;
10 | import static org.junit.Assert.assertTrue;
11 | import static org.junit.Assert.fail;
12 |
13 | import java.io.File;
14 | import java.io.FileInputStream;
15 | import java.io.FileNotFoundException;
16 | import java.io.FileOutputStream;
17 | import java.io.InputStream;
18 |
19 | import org.junit.Before;
20 | import org.junit.Rule;
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 |
24 | import androidx.fragment.app.Fragment;
25 | import androidx.fragment.app.FragmentActivity;
26 | import androidx.fragment.app.FragmentManager;
27 | import androidx.fragment.app.FragmentTransaction;
28 | import androidx.test.ext.junit.runners.AndroidJUnit4;
29 | import androidx.test.filters.LargeTest;
30 | import androidx.test.platform.app.InstrumentationRegistry;
31 | import androidx.test.rule.ActivityTestRule;
32 | import androidx.test.uiautomator.UiDevice;
33 | import androidx.test.uiautomator.UiObject;
34 | import androidx.test.uiautomator.UiObjectNotFoundException;
35 | import androidx.test.uiautomator.UiSelector;
36 | import ch.poole.openinghoursfragment.OpeningHoursFragment;
37 | import ch.poole.openinghoursfragment.R;
38 | import ch.poole.openinghoursfragment.TestActivity;
39 | import ch.poole.openinghoursfragment.TestUtils;
40 | import ch.poole.openinghoursfragment.ValueWithDescription;
41 |
42 | @RunWith(AndroidJUnit4.class)
43 | @LargeTest
44 | public class TemplatesTest {
45 |
46 | private OpeningHoursFragment fragment;
47 | private UiDevice device;
48 | FragmentManager fm;
49 | TemplateDatabaseHelper db;
50 | FragmentActivity activity;
51 |
52 | @Rule
53 | public ActivityTestRule mActivityRule = new ActivityTestRule<>(TestActivity.class);
54 |
55 | @Before
56 | public void setup() {
57 | device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
58 | activity = mActivityRule.getActivity();
59 | fm = activity.getSupportFragmentManager();
60 | FragmentTransaction ft = fm.beginTransaction();
61 | Fragment prev = fm.findFragmentByTag("fragment_openinghours");
62 | if (prev != null) {
63 | ft.remove(prev);
64 | }
65 | ft.commit();
66 |
67 | // create the template database
68 | db = new TemplateDatabaseHelper(activity);
69 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
70 | InputStream is = loader.getResourceAsStream("templates.json");
71 | TemplateDatabase.loadJson(db.getWritableDatabase(), is, true);
72 | }
73 |
74 | @Test
75 | public void manageTemplates() {
76 | ValueWithDescription key = new ValueWithDescription("opening_hours", "Opening hours");
77 | fragment = OpeningHoursFragment.newInstance(key, "AT", null, null, R.style.Theme_DialogLight, 5, true, null, null);
78 | fragment.show(fm, "fragment_openinghours");
79 | assertNotNull(TestUtils.findTextContains(device, false, "Austria"));
80 | assertNull(TestUtils.findTextContains(device, false, "Switzerland"));
81 | assertTrue(TestUtils.clickText(device, false, "Weekdays", true));
82 | assertTrue(TestUtils.clickMenuButton("more button", false, true));
83 | assertTrue(TestUtils.clickText(device, false, "Manage templates", true));
84 | assertNotNull(TestUtils.findTextContains(device, false, "Austria"));
85 | assertNull(TestUtils.findTextContains(device, false, "Switzerland"));
86 | assertTrue(TestUtils.clickMenuButton("more button", false, true));
87 | assertTrue(TestUtils.clickText(device, false, "Show all", true));
88 | assertNotNull(TestUtils.findTextContains(device, false, "Austria"));
89 | assertNotNull(TestUtils.findTextContains(device, false, "Switzerland"));
90 | UiObject template = device.findObject(new UiSelector().textContains("Austria"));
91 | try {
92 | assertTrue(template.clickAndWaitForNewWindow());
93 | } catch (UiObjectNotFoundException e) {
94 | fail(e.getMessage());
95 | }
96 | assertTrue(TestUtils.clickText(device, false, "Delete", true));
97 | assertNull(TestUtils.findTextContains(device, false, "Austria"));
98 | }
99 |
100 | @Test
101 | public void useDefault() {
102 | ValueWithDescription key = new ValueWithDescription("opening_hours", "Opening hours");
103 | fragment = OpeningHoursFragment.newInstance(key, "CH", null, null, R.style.Theme_DialogLight, 5, false, null, null);
104 | fragment.show(fm, "fragment_openinghours");
105 | assertNotNull(TestUtils.findTextContains(device, false, "Mo-Fr 09:00-12:00,13:30-18:30; Sa 09:00-17:00; PH closed"));
106 | }
107 |
108 | @Test
109 | public void exportImportTemplates() {
110 | File dir = activity.getExternalCacheDir();
111 | final File file = new File(dir, "template_out.json");
112 | try {
113 | assertTrue(TemplateDatabase.writeJSON(db.getWritableDatabase(), new FileOutputStream(file)));
114 | TemplateDatabase.loadJson(db.getWritableDatabase(), new FileInputStream(file), true);
115 | } catch (FileNotFoundException e) {
116 | fail(e.getMessage());
117 | } finally {
118 | file.delete();
119 | }
120 | manageTemplates();
121 | }
122 | }
--------------------------------------------------------------------------------
/lib/src/main/java/ch/poole/openinghoursfragment/pickers/RangePicker.java:
--------------------------------------------------------------------------------
1 | package ch.poole.openinghoursfragment.pickers;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.DialogInterface;
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import androidx.annotation.NonNull;
9 | import androidx.appcompat.app.AlertDialog.Builder;
10 | import androidx.appcompat.app.AppCompatDialog;
11 | import androidx.fragment.app.Fragment;
12 | import androidx.fragment.app.FragmentManager;
13 | import ch.poole.openinghoursfragment.CancelableDialogFragment;
14 | import ch.poole.openinghoursfragment.R;
15 | import ch.poole.openinghoursfragment.Util;
16 | import ch.poole.android.numberpickerview.library.NumberPickerView;
17 |
18 | /**
19 | * Display a dialog allowing the user to set a numeric range
20 | *
21 | */
22 | public class RangePicker extends CancelableDialogFragment {
23 | public static final int NOTHING_SELECTED = Integer.MIN_VALUE;
24 |
25 | private static final String TITLE = "title";
26 | private static final String MIN = "min";
27 | private static final String MAX = "max";
28 | private static final String START_CURRENT = "startCurrent";
29 | private static final String END_CURRENT = "endCurrent";
30 | private static final String STYLE_RES = "styleRes";
31 |
32 | private static final String TAG = "fragment_rangepicker";
33 |
34 | /**
35 | * Show the range picker dialog
36 | *
37 | * @param parentFragment Fragment that called this
38 | * @param title resource id for the title to display
39 | * @param min minimum range value
40 | * @param max maximum range value
41 | * @param startCurrent initial start value
42 | * @param endCurrent initial end value
43 | * @param styleRes resource id for style/theme
44 | */
45 | public static void showDialog(Fragment parentFragment, int title, int min, int max, int startCurrent, int endCurrent, int styleRes) {
46 | dismissDialog(parentFragment, TAG);
47 |
48 | FragmentManager fm = parentFragment.getChildFragmentManager();
49 | RangePicker rangePickerFragment = newInstance(title, min, max, startCurrent, endCurrent, styleRes);
50 | rangePickerFragment.show(fm, TAG);
51 | }
52 |
53 | /**
54 | * Create a new instance of RangePicker
55 | *
56 | * @param title resource id for the title to display
57 | * @param min minimum range value
58 | * @param max maximum range value
59 | * @param startCurrent initial start value
60 | * @param endCurrent initial end value
61 | * @param styleRes resource id for style/theme
62 | * @return an instance of RangePicker
63 | */
64 | private static RangePicker newInstance(int title, int min, int max, int startCurrent, int endCurrent, int styleRes) {
65 | RangePicker f = new RangePicker();
66 | Bundle args = new Bundle();
67 | args.putInt(TITLE, title);
68 | args.putInt(MIN, min);
69 | args.putInt(MAX, max);
70 | args.putInt(START_CURRENT, startCurrent);
71 | args.putInt(END_CURRENT, endCurrent);
72 | args.putInt(STYLE_RES, styleRes);
73 |
74 | f.setArguments(args);
75 | f.setShowsDialog(true);
76 |
77 | return f;
78 | }
79 |
80 | @NonNull
81 | @SuppressLint("InflateParams")
82 | @Override
83 | public AppCompatDialog onCreateDialog(Bundle savedInstanceState) {
84 | int title = getArguments().getInt(TITLE);
85 | final int min = getArguments().getInt(MIN);
86 | final int max = getArguments().getInt(MAX);
87 | int startCurrent = getArguments().getInt(START_CURRENT);
88 | int endCurrent = getArguments().getInt(END_CURRENT);
89 | final SetRangeListener listener = (SetRangeListener) getParentFragment();
90 |
91 | Builder builder = Util.getAlertDialogBuilder(getContext(), getArguments().getInt(STYLE_RES));
92 | builder.setTitle(title);
93 |
94 | final LayoutInflater inflater = getActivity().getLayoutInflater();
95 |
96 | View layout = inflater.inflate(R.layout.rangepicker, null);
97 | builder.setView(layout);
98 |
99 | String[] startValues = new String[max - min + 1];
100 | for (int i = min; i <= max; i++) {
101 | startValues[i - min] = Integer.toString(i);
102 | }
103 | final NumberPickerView npvStart = (NumberPickerView) layout.findViewById(R.id.start);
104 | npvStart.setDisplayedValues(startValues);
105 | npvStart.setMinValue(min);
106 | npvStart.setMaxValue(max);
107 | npvStart.setValue(startCurrent);
108 |
109 | String[] endValues = new String[max - min + 2];
110 | endValues[0] = "-";
111 | for (int i = min; i <= max; i++) {
112 | endValues[i - min + 1] = Integer.toString(i);
113 | }
114 | final NumberPickerView npvEnd = (NumberPickerView) layout.findViewById(R.id.end);
115 | npvEnd.setDisplayedValues(endValues);
116 | npvEnd.setMinValue(min - 1);
117 | npvEnd.setMaxValue(max);
118 | if (endCurrent == NOTHING_SELECTED) {
119 | endCurrent = min - 1;
120 | }
121 | npvEnd.setValue(endCurrent);
122 |
123 | builder.setPositiveButton(R.string.spd_ohf_ok, (DialogInterface dialog, int which) -> {
124 | int endValue = npvEnd.getValue();
125 | if (endValue == min - 1) {
126 | endValue = NOTHING_SELECTED;
127 | }
128 | listener.setRange(npvStart.getValue(), endValue);
129 | });
130 | builder.setNeutralButton(R.string.spd_ohf_cancel, null);
131 |
132 | return builder.create();
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/lib/src/main/res/values-tr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | İptal
5 |
6 | Tamam
7 | Kaydet
8 | Tamam
9 | Kural ekle
10 | 7/24 için kural ekle
11 | Tatil için kural ekle
12 | Şablon yükle
13 | Şablonu kaydet
14 | Şablonları yönet
15 | Yenile
16 | Hepsini sil
17 | Şablonları yükle
18 | Şablonları yönet
19 | Şablonu kaydet
20 | Evet
21 | Hayır
22 | Başla
23 | End
24 | Açılış saatleri dizisi
25 |
26 | Metin değerleri
27 |
28 |
29 | Şablonu düzenle
30 | İsim:
31 | Varsayılan:
32 | Anahtar:
33 | %1$s %2$s
34 | Tüm
35 | Açılış saatleri
36 | Servis zamanları
37 | Denetimli
38 | Işıklandırma
39 |
40 | Hafta içi öğle yemeği molası
41 | Hafta içi
42 | Haftada bir kez
43 |
44 |
45 | Sil
46 | Hafta aralığı ekle
47 | Tatil ekle
48 |
49 | Zaman aralığı ekle ...
50 | Gece yarısında başla
51 |
52 | Hafta içi gün aralığı ekle
53 | Tarih aralığı ekle ...
54 | Tarih - açık uçlu
55 | Değişken tarih - açık uçlu
56 | Yıl aralığı ekle
57 | Kural türünü göster
58 | Tıpkısı
59 | Yukarı taşı
60 | Aşağı taşı
61 | Zaman seçiciyi görüntüle
62 | 15 dakikalık işarete geç
63 | 5 dakikalık işarete geç
64 | 1 dakikalık işarete geç
65 | Aralığı göster
66 | Kullanımı göster
67 |
68 |
69 |
70 | Normal
71 | Aralık (dakika)
72 | Aralık (yıl)
73 | Aralık (hafta)
74 |
75 | Tarih aralığı
76 | Tarih
77 | Tarih (ayın hafta içi)
78 | Hafta aralığı
79 | Haftalar
80 | Yıl aralığı
81 | Yıllar
82 | Yorum
83 |
84 | Haftaiçi gibi kullanın
85 |
86 | Haftada 7 gün 24 saat
87 |
88 | a (e)
89 |
90 | Paskalya
91 |
92 | Gündoğumu
93 | Gün batımı
94 | Şafak
95 | Alacakaranlık
96 |
97 | Resmi tatil
98 | Okul tatilleri
99 |
100 | Ay içinde meydana gelme
101 |
102 | Pzt
103 | Sa
104 | Ça
105 | Pe
106 | Cu
107 | Cmt
108 | Pa
109 |
110 | Oca
111 | Şub
112 | Mar
113 | Nis
114 | May
115 | Haz
116 | Tem
117 | Ağu
118 | Eyl
119 | Eki
120 | Kas
121 | Ara
122 |
123 | aç
124 | kapalı
125 | devre dışı
126 | bilinmeyen
127 |
128 | önce
129 | sonra
130 |
131 |
132 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/daterangepicker.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
27 |
41 |
55 |
70 |
85 |
99 |
113 |
128 |
129 |
--------------------------------------------------------------------------------
/lib/documentation/docs/help/zh-Hans/Opening hours.md:
--------------------------------------------------------------------------------
1 | # 开放街图营业时间编辑器
2 |
3 | OpenStreetMap 营业时间规范相当复杂,并不易于一个简单直观的使用者介面。
4 |
5 | 然而大部分的时候,你应该只会用到一小部分的定义。编辑器尝试在选单中隐藏更加难懂的功能,来达成这一点,大部分的时候减少“路上”设定,尽可能用预先设定的模版,加以小量修改。
6 |
7 | _本文档是早期文档,正在开发中_
8 |
9 | ## 使用开放街图编辑器
10 |
11 | 在一般的工作流程中,你编辑的物件一般已经有开放时间的标签 (opening_hour、service_times 和 colllection_times),或是你可以重新设定物件的预设组合,用空白的开放时间栏位。如果你需要手动输入栏位,像是用 Vespucci,你可以在详情页面输入关键值,之后切换回栏位页签继续编辑。如果你相信开放时间标签必须多于预设组合的话,请在你的编辑器开启 issue。
12 |
13 | If you have defined a default template (do this via the "Manage templates" menu item) it will be loaded automatically when the editor is started with an empty value. With the "Load template" function you can load any saved template and with the "Save template" menu you can save the current value as a template. You can define separate templates and defaults for specific key, for example "opening_hours", "collection_times" and "service_times" or custom values. Further you can limit applicability of a template to a region and a specific identifier, typically an OSM top-level tag (for example amenity=restaurant).
14 |
15 | 当然,您可以从头开始构建营业时间的值,但我们建议使用现有的模板之一作为开始。
16 |
17 | 如果已经有营业时间的数值则会载入,另外会自动修正以符合营业时间规范。如果无法修正,则会在大概的位置显示错误讯息,原始的营业时间数值,等待人工修正。开放街图资料库中有大约1/4的营业时间数值有问题,但只有少于10%的状况是无法修正。详见 [OpeningHoursParser](https://github.com/simonpoole/OpeningHoursParser),并且看有那些允许的规范变体。
18 |
19 | ### 主菜单按键
20 |
21 | * __添加规则__:添加新规则。
22 | * __为假期添加规则__:当国家/地区改变时为假期添加新规则
23 | * __为 24/7 增加规则__:为总是开放的物件增加规则,开放时间规范不支持任何其他子值为24/7,但我们允许增加更高阶的选择器 (例如年份范围)。
24 | * __Load template__:加载现有模板。
25 | * __保存到模板__:将当前的营业时间值另存为模板,以作为备份为将来使用。
26 | * __管理模板__:编辑(例如更改名称)并删除现有模板。
27 | * __刷新__:重新加载营业时间值。
28 | * __全部删除__:删除所有规则
29 |
30 | ### 规则
31 |
32 | 默认规则被添加为_normal_规则,这意味着它们将在同一天覆盖先前规则的值。在指定延长时间时中,可能会出现一个问题,通常您随后会希望通过_Show rule type_菜单项将规则切换为_additive_。
33 |
34 | #### 规则菜单
35 |
36 | * __添加修饰符/注释__:更改此规则的效果并添加可选注释。
37 | * __添加假期__:为公共或学校假期添加选择器。
38 | * __增加时间跨度...__
39 | * __时间-时间__:同一天的开始时间到结束时间。
40 | * __时间-延长时间__:第二天的开始时间到结束时间(例如26:00是第二天的凌晨02:00)。
41 | * __变化时间-时间__:从开始可变时间(黎明,黄昏,日出和日落)到同一天的结束时间。
42 | * __变化时间-延长时间__:从开始变化时间到第二天的结束时间。
43 | * __时间-变化时间__:开始时间到结束变化时间。
44 | * __变化时间-变化时间__:从开始变化时间到结束变化时间。
45 | * __时间__:一个时间点。
46 | * __开放时间__:从某个时间点开始。
47 | * __变化时间__:特定的变化时间
48 | * __变化时间 - 一直持续__:从变化时间到一直持续
49 | * __增加工作日范围__:添加基于工作日的选择器。
50 | * __增加日期范围...__
51 | * __日期-日期__:从开始日期(年,月,日)到结束日期。
52 | * __变化日期-日期__:从开变化变日期(当前规范仅定义_easter_)到结束日期。
53 | * __日期-变化日期__:从开始日期到变化日期
54 | * __变化日期-变化日期__:从开始变化日期到结束变化日期
55 | * __每月发生-每月发生__:一个月中从开始的周间是相同的。
56 | * __日期- 每月发生__:一个月中周间发生,到特定日期结束
57 | * __日期-发生在月份__:从开始日舒到一个月中的周间结束。
58 | * __Occurrence in month - variable date__: from a start weekday occurrence in a month to an end variable date.
59 | * __Variable date - occurrence in month__: from a start variable date to an end weekday occurrence in a month.
60 | * __Date - open end__: from a start date onwards.
61 | * __Variable date - open end__: from a start variable date onwards.
62 | * __Occurrence in month - open end__: from a start weekday occurrence in a month onwards.
63 | * __With offsets...__: the same entries as above however with offsets specified (this is rarely used).
64 | * __Add year range...__
65 | * __Add year range__: add a year based selector.
66 | * __Add starting year__: add an open ended year range.
67 | * __Add week range__: add a week number based selector.
68 | * __Duplicate__: create a copy of this rule and insert it after the current position.
69 | * __Show rule type__: display and allow changing of the rule type _normal_, _additive_ and _fallback_ (not available on the first rule).
70 | * __Move up__: move this rule up one position (not available on the first rule).
71 | * __Move down__: move this rule down one position.
72 | * __Delete__: delete this rule.
73 |
74 | ### Time spans
75 |
76 | To make editing time spans as easy as possible, we try to choose an optimal time range and granularity for the range bars when loading existing values. For new time spans the bars start at 6:00 (am) and have 15 minute increments, this can be changed via the menu.
77 |
78 | Clicking (not on the pins) the time bar will open the large time picker, when using the bars directly is too difficult. The time pickers extend in to the next day, so they are a simple way to extend a time range without having to delete and re-add the the range.
79 |
80 | #### Time span menu
81 |
82 | * __Display time picker__: show a large time picker for selecting start and end time, on very small displays this is the preferred way of changing times.
83 | * __Switch to 15 minute ticks__: use 15 minute granularity for the range bar.
84 | * __Switch to 5 minute ticks__: use 5 minute granularity for the range bar.
85 | * __Switch to 1 minute ticks__: use 1 minute granularity for the range bar, very difficult to use on a phone.
86 | * __Start at midnight__: start the range bar at midnight.
87 | * __Show interval__: show the interval field for specifying an interval in minutes.
88 | * __Delete__: delete this time span.
89 |
90 | ### Manage templates
91 |
92 | The template management dialog allows you to add, edit and delete templates.
93 |
94 | In Android 4.4 and later the following additional functionality is available from the menu button.
95 |
96 | * __Show all__: display all templates in the database.
97 | * __Save to file__: write the contents of the template database to a file.
98 | * __Load from file (replace)__: load templates from a file replacing the current contents of the database.
99 | * __Load from file__: load templates from a file retaining the current contents.
100 |
101 | #### Save and edit template dialogs
102 |
103 | The dialog allows you to set
104 |
105 | * __Name__ a descriptive name for the template.
106 | * __Default__ if checked this will be consider as a default template (typically further constrained by the other fields).
107 | * __Key__ the key this template is relevant for, if set to _Custom key_ you can add a non-standard value in the field below. The key values support SQL wild cards, that is _%_ matches zero or more characters, *_* matches a single character. Both wild card characters can be escaped with _\\_ for literal matches.
108 | * __Region__ the region the template is applicable to.
109 | * __Object__ an application specific string to use for matching.
110 |
111 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/openinghours.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
21 |
28 |
45 |
50 |
55 |
56 |
57 |
72 |
77 |
82 |
83 |
84 |
90 |
91 |
97 |
101 |
105 |
106 |
120 |
121 |
124 |
132 |
140 |
141 |
142 |
--------------------------------------------------------------------------------
/lib/documentation/docs/help/iw/Opening hours.md:
--------------------------------------------------------------------------------
1 | # עורך שעות הפתיחה של OpenStreetMap
2 |
3 | מפרט שעות הפתיחה של OpenStreetMap הוא די מורכב ולא מסביר פנים בהיבט של מנשק משתמש פשוט וברור.
4 |
5 | עם זאת, סביר להניח שברוב הזמן יידרש לך רק חלק מצומצם מתוך המנגנון. העורך לוקח זאת בחשבון תוך הסתרת תכונות שאינן שימושיות בתפריטים וברוב המקרים מצמצם את השימוש השוטף להתאמות קטנות של תבניות מותאמות אישית.
6 |
7 | _תיעוד זה הוא ראשוני בלבד וכרגע מתבצעות עליו עבודות עריכה נוספות_
8 |
9 | ## שימוש בעורך שעות הפתיחה
10 |
11 | במצב עבודה טיפוסי לפריט שבחרת לערוך כבר יש תגית שעות פתיחה (opening_hours, service_times ו־collection_times) או שניתן להחיל מחדש את הערכה עבור הפריט כדי לקבל שדה שעות פתיחה ריק. אם יש לך צורך בהוספת השדה ידנית וניסית לעשות זאת דרך וספוצ׳י ניתן להקליד את שם המפתח בעמוד הפרטים ואז לחזור ללשונית מבוססת הטפסים לטובת עריכה. אם לדעתך תגית שעות הפתיחה אמורה להיות חלק מהערכה הראשונית, נא לדווח על תקלה כנגד העורך שלך.
12 |
13 | אם הגדרת תבנית בררת מחדל (אפשר לעשות את זה דרך הפריט „ניהול תבניות” בתפריט) היא תיטען אוטומטית עם הפעלת העורך עם ערך ריק. בעזרת הפונקציה „טעינת תבנית” אפשר לטעון כל תבנית שמורה שהיא ועם התפריט „שמירת תבנית” אפשר לשמור את הערך הנוכחי כתבנית. אפשר להגדיר תבניות נפרדות ובררות מחדל למפתח מסוים, למשל „opening_hours”, „collection_times” ו־„service_times” או ערכים משלך. נוסף על כך, ניתן להגביל את היכולת להחיל תבנית על איזור ומזהה מסוים, בדרך כלל תגית ברמה עליונה של OSM (למשל amenity=restaurant).
14 |
15 | באופן טבעי ניתן להרכיב ערך שעות פתיחה מאפשר, אך אנו ממליצים להשתמש באחת מהתבניות הקיימות כנקודת התחלה.
16 |
17 | אם נטען ערך קיים של שעות פתיחה, מתבצע ניסיון לתקן אותו אוטומטית כדי להתאים למפרט שעות הפתיחה. אם פעולה כזו אינה אפשרית המיקום בקירוב בו התרחשה השגיאה יודגש בתצוגה של ערכי שעות הפתיחה הגולמיים ותהיה לך אפשרות לנסות ולתקן זאת ידנית. בערך ברבע מערכי שעות הפתיחה במסד הנתונים של OpenStreetMap יש תקלות אך פחות מ־10% אינן ניתנות לתיקון, יש לעיין בערך [OpeningHoursParser](https://github.com/simonpoole/OpeningHoursParser) (מנתח שעות פתיחה) לקבלת מידע נוסף על אילו סטיות מהמפרט נסבלות.
18 |
19 | ### כפתור תפריט ראשי
20 |
21 | * __הוספת כלל__: הוספת כלל חדש.
22 | * __הוספת כלל לחגים__: הוספת כלל חדש לחג יחד עם שינוי מצב.
23 | * __הוספת כלל ל־24/7__: הוספת כלל לפריט שתמיד פתוח, מפרט שעות הפתיחה לא תומך בערכים נגזרים עבור 24/7 עם זאת אנו מאפשרים הוספת בוררים ברמה גבוהה יותר (למשל: טווח שנים).
24 | * __טעינת תבנית__: טעינת תבנית קיימת.
25 | * __שמירה לתבנית__: שמירת ערך שעות הפתיחה הנוכחי כתבנית לשימוש עתידי.
26 | * __ניהול תבניות__: עריכה, למשל שינוי השם ומחיקה של תבניות קיימות.
27 | * __רענון__: פענוח ערך שעות הפתיחה מחדש.
28 | * __מחיקת הכול__: הסרת כל הכללים.
29 |
30 | ### כללים
31 |
32 | כללי בררת המחדל נוספו ככללים מסוג _רגיל_, הגדרה זו מרמזת על כך שהם יידרסו על ידי הערכים של הכללים הקודמים עבור אותם ימים. מצב זה עשוי להדאיג בהגדרת זמנים מורחבים, במיוחד עקב החלפת כללים דרך רשומת התפריט _הצגת סוג כלל_ לכלל _מתווסף_.
33 |
34 | #### תפריט כללים
35 |
36 | * __הוספת מצב/תגובה__: שינוי ההשפעה של הכלל הזה והוספת תגובה כרשות.
37 | * __הוספת חג__: הוספת בורר לחגים ציבוריים או חגי בית ספר.
38 | * __הוספת טווח זמן…__
39 | * __שעה - שעה__: שעת התחלה עד שעת סיום באותו היום.
40 | * __שעה - שעה מורחבת__: שעת התחלה עד שעת סיום ביום שלמחרת (למשל: 26:00 זה 02:00 לפנות בוקר ביום הבא).
41 | * __שעה משתנה - שעה__: משעת התחלה משתנה (שחר, דמדומים, זריחה ושקיעה) עד לשעת סיום באותו היום.
42 | * __שעה משתנה - שעה מורחבת__: משעת התחלה משתנה ועד לשעת סיום ביום שלמחרת.
43 | * __שעה - שעה משתנה__: שעת התחלה עד שעת סיום משתנה.
44 | * __שעה משתנה - שעה משתנה__: שעת התחלה משתנה עד שעת סיום משתנה.
45 | * __שעה__: נקודה בזמן.
46 | * __שעה - הודעה חדשה__: מנקודת התחלה בזמן ואילך.
47 | * __שעה משתנה__: בשעה משתנה
48 | * __שעה משתנה - הודעה חדשה__: משעת התחלה משתנה ואילך
49 | * __הוספת טווח ימים בשבוע__: הוספת בורר על סמך ימים בשבוע.
50 | * __הוספת טווח תאריכים…__
51 | * __תאריך - תאריך__: מתאריך התחלה (שנה, חודש, יום) עד לתאריך סיום.
52 | * __תאריך משתנה - תאריך__: מתאריך התחלה משתנה (כרגע המפרט מגדיר רק את _פסחא_) עד לתאריך סיום.
53 | * __תאריך - תאריך משתנה__: מתאריך התחלה ועד תאריך משתנה.
54 | * __תאריך משתנה - תאריך משתנה__: מתאריך התחלה משתנה עד תאריך סיום משתנה.
55 | * __פעם בחודש - פעם בחודש__: החל ממופע של יום בשבוע מתוך חודש עד לאחד נוסף כזה.
56 | * __פעם בחודש - תאריך__: החל ממופע של יום בשבוע מתוך חודש עד לתאריך סיום.
57 | * __תאריך - פעם בחודש__: מתאריך התחלה עד מופע של יום בשבוע מתוך חודש.
58 | * __פעם בחודש - תאריך משתנה__: החל ממופע של יום בשבוע מתוך חודש עד לתאריך סיום משתנה.
59 | * __תאריך משתנה - פעם בחודש__: מתאריך התחלה משתנה עד מופע של יום בשבוע מתוך חודש.
60 | * __שעה - הודעה חדשה__: משעה מסוימת ואילך.
61 | * __תאריך משתנה - הודעה חדשה__: מתאריך התחלה משתנה ואילך.
62 | * __פעם בחודש - הודעה חדשה__: החל ממופע של יום בשבוע מתוך חודש ואילך.
63 | * __עם איזונים…__: אותן הרשומות כלעיל רק עם איזונים (בקושי בשימוש).
64 | * __הוספת טווח שנים…__
65 | * __הוספת טווח שנים__: הוספת בורר לבחירת שנים.
66 | * __הוספת שנת התחלה__: הוספת טווח שנים עם סוף פתוח.
67 | * __הוספת טווח שבועות__: הוספת בורר לבחירת מספרי שבועות.
68 | * __שכפול__: יצירת עותק של הכלל הזה והוספתו לאחר המיקום הנוכחי.
69 | * __הצגת סוג כלל__: להציג ולאפשר לשנות את סוג הכלל _רגיל_, _מתווסף_ ו_עתודה_ (לא זמין בתור הכלל הראשון).
70 | * __העברה למעלה__: העלאת הכלל הזה בשורה אחת למעלה (לא זמין עבור הכלל הראשון).
71 | * __העברה למטה__: הורדת הכלל הזה בשורה אחת למטה.
72 | * __מחיקה__: מחיקת הכלל הזה.
73 |
74 | ### טווחי שעות
75 |
76 | כדי להקל על עריכת טווי שעות עד כמה שניתן, אנו מנסים לבחור טווח שעות מיטבי ויכולת בחירה מוגדרת עבור סרגלי הטווח בעת טעינת ערכים קיימים. לטווחי שעות חדשים, הסרגלים מתחילים ב־6:00 בבוקר וניתן להגדיל ב־15 דקות בכל צעד, ניתן לשנות זאת דרך התפריט.
77 |
78 | לחיצה (לא על הנעצים) על סרגל הזמן פותחת את בורר הזמן הגדול, כאשר השימוש הישיר בסרגלים הוא מסובך מדי. בוררי הזמן מתרחבים ליום הבא, לכן הם מעניקים דרך פשוטה להרחיב טווח זמן מבלי למחוק ולהוסיף את הטווח מחדש.
79 |
80 | #### תפריט טווחי שעות
81 |
82 | * __הצגת בורר זמן__: הצגת בורר זמן גדול לבחירת זמן התחלה וסיום, בתצוגות קטנות מאוד זו הדרך המועדפת לעריכת זמנים.
83 | * __מעבר לפעימות של 15 דקות__: להשתמש בדיוק של 15 דקות עבור סרגל הטווח.
84 | * __מעבר לפעימות של 5 דקות__: להשתמש בדיוק של 5 דקות עבור סרגל הטווח.
85 | * __מעבר לפעימות של דקה__: להשתמש בדיוק של דקה עבור סרגל הטווח, לא נוח לשימוש בטלפון.
86 | * __התחלה בחצות__: התחלת סרגל הטווח בחצות.
87 | * __הצגת הפרש__: הצגת שדה ההפרש לציון הפרש בדקות.
88 | * __מחיקה__: מחיקת טווח הזמן הזה.
89 |
90 | ### ניהול תבניות
91 |
92 | חלונית ניהול התבניות הזאת מאפשרת לך להוסיף, לערוך ולמחוק תבניות.
93 |
94 | ב־Android 4.4 ומעלה היכולת הנוספת הבאה זמינה מכפתור התפריט.
95 |
96 | * __הצגה של הכול__: הצגת כל התבניות במסד הנתונים.
97 | * __שמירה לקובץ__: כתיבת תכני מסד נתוני התבניות לקובץ.
98 | * __טעינה מקובץ (החלפה)__: טעינת תבניות מקובץ שמחליפה את התוכן הנוכחי של מסד הנתונים.
99 | * __טעינה מקובץ__: טעינת תבניות מקובץ תוך שימור התכנים הנוכחיים.
100 |
101 | #### לשמור ולערוך חלוניות תבניות
102 |
103 | החלונית מאפשרת לך להגדיר
104 |
105 | * __שם__ שם ייצוגי לתבנית.
106 | * __בררת מחדל__ אם מסומן, זאת תיחשב לתבנית בררת המחדל (בדרך כלל מקובע אף יותר על ידי השדות האחרים).
107 | * __מפתח__ המפתח שהתבנית הזו מתאימה לו, אם מוגדר לכדי _מפתח אישי_ אפשר להוסיף ערך מחוץ לתקן בשדה שלהלן. ערכי המפתח תומכים בתווים כוללניים של SQL, כאשר _%_ לוכד אפס תווים או יותר, *_* לוכד תו יחיד. את שני התווים הכוללניים אפשר להחריג באמצעות _\\_ ללכידה כפי שהם.
108 | * __אזור__ האזור עליו חלה התבנית.
109 | * __פריט__ מחרוזת ייעודית ליישום לשימוש עבור התאמה.
110 |
111 |
--------------------------------------------------------------------------------