forked from organicmaps/organicmaps
[ios] Updated opening hours editor.
This commit is contained in:
parent
c79043734c
commit
226de1eb7b
8 changed files with 230 additions and 46 deletions
|
@ -1,4 +1,5 @@
|
|||
#import "MWMOpeningHoursAddScheduleTableViewCell.h"
|
||||
#import "MWMOpeningHoursCommon.h"
|
||||
#import "MWMOpeningHoursEditorViewController.h"
|
||||
|
||||
@interface MWMOpeningHoursAddScheduleTableViewCell ()
|
||||
|
@ -14,6 +15,13 @@
|
|||
return 84.0;
|
||||
}
|
||||
|
||||
- (void)refresh
|
||||
{
|
||||
NSString * title = [NSString stringWithFormat:@"%@ %@", L(@"add_schedule_for"),
|
||||
stringFromOpeningDays([self.model unhandledDays])];
|
||||
[self.addScheduleButton setTitle:title forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)addScheduleTap
|
||||
|
@ -26,9 +34,7 @@
|
|||
- (void)setModel:(MWMOpeningHoursModel *)model
|
||||
{
|
||||
_model = model;
|
||||
NSString * unhandledDays = [model.unhandledDays componentsJoinedByString:@", "];
|
||||
NSString * title = [NSString stringWithFormat:@"%@ %@", L(@"add_schedule_for"), unhandledDays];
|
||||
[self.addScheduleButton setTitle:title forState:UIControlStateNormal];
|
||||
[self refresh];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -27,7 +27,7 @@ using namespace osmoh;
|
|||
[super awakeFromNib];
|
||||
NSCalendar * cal = [NSCalendar currentCalendar];
|
||||
cal.locale = [NSLocale currentLocale];
|
||||
self.firstWeekday = [cal firstWeekday];
|
||||
self.firstWeekday = cal.firstWeekday;
|
||||
NSArray<NSString *> * weekdaySymbols = cal.shortStandaloneWeekdaySymbols;
|
||||
for (UILabel * label in self.labels)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#include "3party/opening_hours/opening_hours.hpp"
|
||||
#include "editor/opening_hours_ui.hpp"
|
||||
#include "base/assert.hpp"
|
||||
|
||||
NSDateComponents * dateComponentsFromTime(osmoh::Time const & time);
|
||||
NSDate * dateFromTime(osmoh::Time const & time);
|
||||
NSString * stringFromTime(osmoh::Time const & time);
|
||||
|
||||
NSString * stringFromOpeningDays(editor::ui::TOpeningDays const & openingDays);
|
|
@ -0,0 +1,69 @@
|
|||
#import "MWMOpeningHoursCommon.h"
|
||||
|
||||
NSDateComponents * dateComponentsFromTime(osmoh::Time const & time)
|
||||
{
|
||||
NSDateComponents * dc = [[NSDateComponents alloc] init];
|
||||
dc.hour = time.GetHoursCount();
|
||||
dc.minute = time.GetMinutesCount();
|
||||
return dc;
|
||||
}
|
||||
|
||||
NSDate * dateFromTime(osmoh::Time const & time)
|
||||
{
|
||||
NSCalendar * cal = [NSCalendar currentCalendar];
|
||||
cal.locale = [NSLocale currentLocale];
|
||||
return [cal dateFromComponents:dateComponentsFromTime(time)];
|
||||
}
|
||||
|
||||
NSString * stringFromTime(osmoh::Time const & time)
|
||||
{
|
||||
NSDateFormatter * fmt = [[NSDateFormatter alloc] init];
|
||||
fmt.locale = [NSLocale currentLocale];
|
||||
fmt.timeStyle = NSDateFormatterShortStyle;
|
||||
fmt.dateStyle = NSDateFormatterNoStyle;
|
||||
return [fmt stringFromDate:dateFromTime(time)];
|
||||
}
|
||||
|
||||
NSString * stringFromOpeningDays(editor::ui::TOpeningDays const & openingDays)
|
||||
{
|
||||
NSCalendar * cal = [NSCalendar currentCalendar];
|
||||
cal.locale = [NSLocale currentLocale];
|
||||
NSUInteger const firstWeekday = cal.firstWeekday - 1;
|
||||
|
||||
NSArray<NSString *> * weekdaySymbols = cal.shortStandaloneWeekdaySymbols;
|
||||
NSMutableArray<NSString *> * spanNames = [NSMutableArray arrayWithCapacity:2];
|
||||
NSMutableArray<NSString *> * spans = [NSMutableArray array];
|
||||
|
||||
auto weekdayFromDay = ^(NSUInteger day)
|
||||
{
|
||||
NSUInteger idx = day + 1;
|
||||
if (idx > static_cast<NSUInteger>(osmoh::Weekday::Saturday))
|
||||
idx -= static_cast<NSUInteger>(osmoh::Weekday::Saturday);
|
||||
return static_cast<osmoh::Weekday>(idx);
|
||||
};
|
||||
|
||||
auto joinSpanNames = ^
|
||||
{
|
||||
NSUInteger const spanNamesCount = spanNames.count;
|
||||
if (spanNamesCount == 0)
|
||||
return;
|
||||
else if (spanNamesCount == 1)
|
||||
[spans addObject:spanNames[0]];
|
||||
else if (spanNamesCount == 2)
|
||||
[spans addObject:[spanNames componentsJoinedByString:@"-"]];
|
||||
else
|
||||
ASSERT(false, ("Invalid span names count."));
|
||||
[spanNames removeAllObjects];
|
||||
};
|
||||
NSUInteger const weekDaysCount = 7;
|
||||
for (NSUInteger i = 0, day = firstWeekday; i < weekDaysCount; ++i, ++day)
|
||||
{
|
||||
osmoh::Weekday const wd = weekdayFromDay(day);
|
||||
if (openingDays.find(wd) == openingDays.end())
|
||||
joinSpanNames();
|
||||
else
|
||||
spanNames[(spanNames.count == 0 ? 0 : 1)] = weekdaySymbols[static_cast<NSInteger>(wd) - 1];
|
||||
}
|
||||
joinSpanNames();
|
||||
return [spans componentsJoinedByString:@", "];
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
#import "MWMOpeningHoursEditorViewController.h"
|
||||
#import "MWMOpeningHoursModel.h"
|
||||
#import "MWMOpeningHoursSection.h"
|
||||
#import "MWMTextView.h"
|
||||
|
||||
extern NSDictionary * const kMWMOpeningHoursEditorTableCells = @{
|
||||
@(MWMOpeningHoursEditorDaysSelectorCell) : @"MWMOpeningHoursDaysSelectorTableViewCell",
|
||||
|
@ -16,9 +17,20 @@ extern NSDictionary * const kMWMOpeningHoursEditorTableCells = @{
|
|||
};
|
||||
|
||||
@interface MWMOpeningHoursEditorViewController ()<UITableViewDelegate, UITableViewDataSource,
|
||||
MWMOpeningHoursModelProtocol>
|
||||
UITextViewDelegate, MWMOpeningHoursModelProtocol>
|
||||
|
||||
@property (weak, nonatomic, readwrite) IBOutlet UITableView * tableView;
|
||||
@property (weak, nonatomic, readwrite) IBOutlet UIView * advancedEditor;
|
||||
@property (weak, nonatomic, readwrite) IBOutlet MWMTextView * editorView;
|
||||
@property (weak, nonatomic) IBOutlet UIView * helpView;
|
||||
@property (weak, nonatomic) IBOutlet UITextView * help;
|
||||
@property (weak, nonatomic, readwrite) IBOutlet NSLayoutConstraint * ohTextViewHeight;
|
||||
@property (weak, nonatomic) IBOutlet UIView * exampleValuesSeparator;
|
||||
@property (weak, nonatomic) IBOutlet UIImageView * exampleValuesExpandView;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * exampesButtonBottomOffset;
|
||||
@property (weak, nonatomic, readwrite) IBOutlet UIButton * toggleModeButton;
|
||||
|
||||
@property (nonatomic) BOOL exampleExpanded;
|
||||
|
||||
@property (nonatomic) MWMOpeningHoursModel * model;
|
||||
|
||||
|
@ -31,6 +43,7 @@ extern NSDictionary * const kMWMOpeningHoursEditorTableCells = @{
|
|||
[super viewDidLoad];
|
||||
[self configNavBar];
|
||||
[self configTable];
|
||||
[self configAdvancedEditor];
|
||||
[self configData];
|
||||
}
|
||||
|
||||
|
@ -56,6 +69,12 @@ extern NSDictionary * const kMWMOpeningHoursEditorTableCells = @{
|
|||
}];
|
||||
}
|
||||
|
||||
- (void)configAdvancedEditor
|
||||
{
|
||||
[self.editorView setTextContainerInset:{12, 10, 12, 10}];
|
||||
[self setExampleExpanded:NO];
|
||||
}
|
||||
|
||||
- (void)configData
|
||||
{
|
||||
self.model = [[MWMOpeningHoursModel alloc] initWithDelegate:self];
|
||||
|
@ -65,6 +84,9 @@ extern NSDictionary * const kMWMOpeningHoursEditorTableCells = @{
|
|||
|
||||
- (void)onDone
|
||||
{
|
||||
[self.model updateOpeningHours];
|
||||
std::string str = self.openingHours.UTF8String;
|
||||
// TODO (AlexZ): Store edited opening time
|
||||
}
|
||||
|
||||
#pragma mark - Table
|
||||
|
@ -112,6 +134,8 @@ extern NSDictionary * const kMWMOpeningHoursEditorTableCells = @{
|
|||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView * _Nonnull)tableView
|
||||
{
|
||||
if (!self.model.isSimpleMode)
|
||||
return 0;
|
||||
return self.model.count + (self.model.canAddSection ? 1 : 0);
|
||||
}
|
||||
|
||||
|
@ -137,4 +161,38 @@ extern NSDictionary * const kMWMOpeningHoursEditorTableCells = @{
|
|||
[self fillCell:cell atIndexPath:indexPath];
|
||||
}
|
||||
|
||||
#pragma mark - Advanced mode
|
||||
|
||||
- (void)setExampleExpanded:(BOOL)exampleExpanded
|
||||
{
|
||||
_exampleExpanded = exampleExpanded;
|
||||
self.help.hidden = !exampleExpanded;
|
||||
self.exampesButtonBottomOffset.priority = exampleExpanded ? UILayoutPriorityDefaultLow : UILayoutPriorityDefaultHigh;
|
||||
self.exampleValuesSeparator.hidden = !exampleExpanded;
|
||||
self.exampleValuesExpandView.image = [UIImage imageNamed:exampleExpanded ? @"ic_arrow_gray_up" : @"ic_arrow_gray_down"];
|
||||
if (exampleExpanded)
|
||||
[self.editorView resignFirstResponder];
|
||||
else
|
||||
[self.editorView becomeFirstResponder];
|
||||
}
|
||||
|
||||
- (IBAction)toggleExample
|
||||
{
|
||||
self.exampleExpanded = !self.exampleExpanded;
|
||||
}
|
||||
|
||||
- (IBAction)toggleMode
|
||||
{
|
||||
self.model.isSimpleMode = !self.model.isSimpleMode;
|
||||
}
|
||||
|
||||
#pragma mark - UITextViewDelegate
|
||||
|
||||
- (void)textViewDidChange:(UITextView *)textView
|
||||
{
|
||||
self.openingHours = textView.text;
|
||||
self.navigationItem.rightBarButtonItem.enabled = self.model.isValid;
|
||||
self.toggleModeButton.enabled = self.model.isSimpleModeCapable;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
#import "MWMOpeningHoursEditorCells.h"
|
||||
#import "MWMOpeningHoursTableViewCell.h"
|
||||
#import "MWMTextView.h"
|
||||
|
||||
@protocol MWMOpeningHoursModelProtocol <NSObject>
|
||||
|
||||
@property (nonnull, copy, nonatomic) NSString * openingHours;
|
||||
@property (weak, nonatomic, readonly) UITableView * tableView;
|
||||
@property (weak, nonatomic, readonly) UIView * advancedEditor;
|
||||
@property (weak, nonatomic, readonly) MWMTextView * editorView;
|
||||
@property (weak, nonatomic, readonly) UIButton * toggleModeButton;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -11,7 +16,10 @@
|
|||
|
||||
@property (nonatomic, readonly) NSUInteger count;
|
||||
@property (nonatomic, readonly) BOOL canAddSection;
|
||||
@property (nonnull, nonatomic, readonly) NSArray<NSString *> * unhandledDays;
|
||||
|
||||
@property (nonatomic, readonly) BOOL isValid;
|
||||
@property (nonatomic) BOOL isSimpleMode;
|
||||
@property (nonatomic, readonly) BOOL isSimpleModeCapable;
|
||||
|
||||
- (instancetype _Nullable)initWithDelegate:(id<MWMOpeningHoursModelProtocol> _Nonnull)delegate;
|
||||
|
||||
|
@ -23,5 +31,8 @@
|
|||
- (CGFloat)heightForIndexPath:(NSIndexPath * _Nonnull)indexPath withWidth:(CGFloat)width;
|
||||
- (void)fillCell:(MWMOpeningHoursTableViewCell * _Nonnull)cell atIndexPath:(NSIndexPath * _Nonnull)indexPath;
|
||||
- (NSUInteger)numberOfRowsInSection:(NSUInteger)section;
|
||||
- (editor::ui::TOpeningDays)unhandledDays;
|
||||
|
||||
- (void)updateOpeningHours;
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,24 +1,26 @@
|
|||
#import "MWMOpeningHoursCommon.h"
|
||||
#import "MWMOpeningHoursModel.h"
|
||||
#import "MWMOpeningHoursSection.h"
|
||||
|
||||
#include "editor/opening_hours_ui.hpp"
|
||||
#include "editor/ui2oh.hpp"
|
||||
|
||||
extern UITableViewRowAnimation const kMWMOpeningHoursEditorRowAnimation = UITableViewRowAnimationFade;
|
||||
|
||||
@interface MWMOpeningHoursModel () <MWMOpeningHoursSectionProtocol>
|
||||
|
||||
@property (weak, nonatomic, readwrite) UITableView * tableView;
|
||||
@property (weak, nonatomic) id<MWMOpeningHoursModelProtocol> delegate;
|
||||
|
||||
@property (nonatomic) NSMutableArray<MWMOpeningHoursSection *> * sections;
|
||||
|
||||
@end
|
||||
|
||||
using namespace editor::ui;
|
||||
using namespace editor;
|
||||
using namespace osmoh;
|
||||
|
||||
@implementation MWMOpeningHoursModel
|
||||
{
|
||||
TimeTableSet timeTableSet;
|
||||
ui::TimeTableSet timeTableSet;
|
||||
}
|
||||
|
||||
- (instancetype _Nullable)initWithDelegate:(id<MWMOpeningHoursModelProtocol> _Nonnull)delegate
|
||||
|
@ -26,10 +28,8 @@ using namespace osmoh;
|
|||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
_tableView = delegate.tableView;
|
||||
_sections = [NSMutableArray arrayWithCapacity:timeTableSet.Size()];
|
||||
while (self.sections.count < timeTableSet.Size())
|
||||
[self addSection];
|
||||
self.delegate = delegate;
|
||||
self.isSimpleMode = self.isSimpleModeCapable;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -38,8 +38,6 @@ using namespace osmoh;
|
|||
{
|
||||
[self.sections addObject:[[MWMOpeningHoursSection alloc] initWithDelegate:self]];
|
||||
[self refreshSectionsIndexes];
|
||||
NSIndexSet * set = [[NSIndexSet alloc] initWithIndex:self.count - 1];
|
||||
[self.tableView reloadSections:set withRowAnimation:kMWMOpeningHoursEditorRowAnimation];
|
||||
}
|
||||
|
||||
- (void)refreshSectionsIndexes
|
||||
|
@ -56,6 +54,8 @@ using namespace osmoh;
|
|||
NSAssert(self.canAddSection, @"Can not add schedule");
|
||||
timeTableSet.Append(timeTableSet.GetComplementTimeTable());
|
||||
[self addSection];
|
||||
[self.tableView reloadSections:[[NSIndexSet alloc] initWithIndex:self.sections.count - 1]
|
||||
withRowAnimation:kMWMOpeningHoursEditorRowAnimation];
|
||||
NSAssert(timeTableSet.Size() == self.sections.count, @"Inconsistent state");
|
||||
[self.sections[self.sections.count - 1] scrollIntoView];
|
||||
}
|
||||
|
@ -69,13 +69,16 @@ using namespace osmoh;
|
|||
[self refreshSectionsIndexes];
|
||||
if (needRealDelete)
|
||||
{
|
||||
NSIndexSet * set = [[NSIndexSet alloc] initWithIndex:index];
|
||||
[self.tableView deleteSections:set withRowAnimation:kMWMOpeningHoursEditorRowAnimation];
|
||||
[self.tableView deleteSections:[[NSIndexSet alloc] initWithIndex:index]
|
||||
withRowAnimation:kMWMOpeningHoursEditorRowAnimation];
|
||||
[self.tableView reloadSections:[[NSIndexSet alloc] initWithIndex:self.count]
|
||||
withRowAnimation:kMWMOpeningHoursEditorRowAnimation];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSIndexSet * set = [[NSIndexSet alloc] initWithIndexesInRange:{index, self.count - index + 1}];
|
||||
[self.tableView reloadSections:set withRowAnimation:kMWMOpeningHoursEditorRowAnimation];
|
||||
NSRange reloadRange = {index, self.count - index + 1};
|
||||
[self.tableView reloadSections:[[NSIndexSet alloc] initWithIndexesInRange:reloadRange]
|
||||
withRowAnimation:kMWMOpeningHoursEditorRowAnimation];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +91,7 @@ using namespace osmoh;
|
|||
}
|
||||
}
|
||||
|
||||
- (TTimeTableProxy)getTimeTableProxy:(NSUInteger)index
|
||||
- (ui::TTimeTableProxy)getTimeTableProxy:(NSUInteger)index
|
||||
{
|
||||
NSAssert(index < self.count, @"Invalid section index");
|
||||
return timeTableSet.Get(index);
|
||||
|
@ -122,6 +125,18 @@ using namespace osmoh;
|
|||
return self.sections[section].numberOfRows;
|
||||
}
|
||||
|
||||
- (ui::TOpeningDays)unhandledDays
|
||||
{
|
||||
return timeTableSet.GetUnhandledDays();
|
||||
}
|
||||
|
||||
- (void)updateOpeningHours
|
||||
{
|
||||
stringstream sstr;
|
||||
sstr << MakeOpeningHours(timeTableSet).GetRule();
|
||||
self.delegate.openingHours = @(sstr.str().c_str());
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (NSUInteger)count
|
||||
|
@ -135,30 +150,50 @@ using namespace osmoh;
|
|||
return !timeTableSet.GetUnhandledDays().empty();
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)unhandledDays
|
||||
- (UITableView *)tableView
|
||||
{
|
||||
auto const unhandledDays = timeTableSet.GetUnhandledDays();
|
||||
NSCalendar * cal = [NSCalendar currentCalendar];
|
||||
cal.locale = [NSLocale currentLocale];
|
||||
NSUInteger const firstWeekday = [cal firstWeekday] - 1;
|
||||
Weekday (^day2Weekday)(NSUInteger) = ^Weekday(NSUInteger day)
|
||||
{
|
||||
NSUInteger idx = day + 1;
|
||||
if (idx > static_cast<NSUInteger>(Weekday::Saturday))
|
||||
idx -= static_cast<NSUInteger>(Weekday::Saturday);
|
||||
return static_cast<Weekday>(idx);
|
||||
};
|
||||
return self.delegate.tableView;
|
||||
}
|
||||
|
||||
NSArray<NSString *> * weekdaySymbols = cal.shortStandaloneWeekdaySymbols;
|
||||
NSMutableArray<NSString *> * dayNames = [NSMutableArray arrayWithCapacity:unhandledDays.size()];
|
||||
NSUInteger const weekDaysCount = 7;
|
||||
for (NSUInteger i = 0, day = firstWeekday; i < weekDaysCount; ++i, ++day)
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return osmoh::OpeningHours(self.delegate.openingHours.UTF8String).IsValid();
|
||||
}
|
||||
|
||||
- (void)setIsSimpleMode:(BOOL)isSimpleMode
|
||||
{
|
||||
if (_isSimpleMode == isSimpleMode)
|
||||
return;
|
||||
_isSimpleMode = isSimpleMode;
|
||||
id<MWMOpeningHoursModelProtocol> delegate = self.delegate;
|
||||
if (isSimpleMode && MakeTimeTableSet(osmoh::OpeningHours(delegate.openingHours.UTF8String), timeTableSet))
|
||||
{
|
||||
Weekday const wd = day2Weekday(day);
|
||||
if (unhandledDays.find(wd) != unhandledDays.end())
|
||||
[dayNames addObject:weekdaySymbols[static_cast<NSInteger>(wd) - 1]];
|
||||
_isSimpleMode = YES;
|
||||
delegate.tableView.hidden = NO;
|
||||
delegate.advancedEditor.hidden = YES;
|
||||
[delegate.toggleModeButton setTitle:L(@"advanced_mode") forState:UIControlStateNormal];
|
||||
_sections = [NSMutableArray arrayWithCapacity:timeTableSet.Size()];
|
||||
while (self.sections.count < timeTableSet.Size())
|
||||
[self addSection];
|
||||
[delegate.tableView reloadData];
|
||||
}
|
||||
return dayNames;
|
||||
else
|
||||
{
|
||||
_isSimpleMode = NO;
|
||||
[self updateOpeningHours];
|
||||
delegate.tableView.hidden = YES;
|
||||
delegate.advancedEditor.hidden = NO;
|
||||
[delegate.toggleModeButton setTitle:L(@"simple_mode") forState:UIControlStateNormal];
|
||||
MWMTextView * ev = delegate.editorView;
|
||||
ev.text = delegate.openingHours;
|
||||
[ev becomeFirstResponder];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isSimpleModeCapable
|
||||
{
|
||||
ui::TimeTableSet tts;
|
||||
return MakeTimeTableSet(osmoh::OpeningHours(self.delegate.openingHours.UTF8String), tts);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#import "MWMOpeningHoursCommon.h"
|
||||
#import "MWMOpeningHoursSection.h"
|
||||
#import "MWMOpeningHoursTableViewCell.h"
|
||||
|
||||
|
@ -116,12 +117,7 @@ using namespace osmoh;
|
|||
TTimeTableProxy tt = [self getTimeTableProxy];
|
||||
NSUInteger const index = isClosed ? [self closedTimeIndex:row] : 0;
|
||||
Timespan span = isClosed ? tt.GetExcludeTime()[index] : tt.GetOpeningTime();
|
||||
Time const & t = isStart ? span.GetStart() : span.GetEnd();
|
||||
|
||||
NSDateComponents * time = [[NSDateComponents alloc] init];
|
||||
time.hour = t.GetHoursCount();
|
||||
time.minute = t.GetMinutesCount();
|
||||
return time;
|
||||
return dateComponentsFromTime(isStart ? span.GetStart() : span.GetEnd());
|
||||
}
|
||||
|
||||
- (void)setTime:(NSDateComponents *)time isStart:(BOOL)isStart isClosed:(BOOL)isClosed
|
||||
|
|
Loading…
Add table
Reference in a new issue