1/* UIxCalDayTable.m - this file is part of SOGo 2 * 3 * Copyright (C) 2006-2016 Inverse inc. 4 * 5 * This file is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2, or (at your option) 8 * any later version. 9 * 10 * This file is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; see the file COPYING. If not, write to 17 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 * Boston, MA 02111-1307, USA. 19 */ 20 21#import <Foundation/NSDictionary.h> 22#import <Foundation/NSUserDefaults.h> /* for locale string constants */ 23#import <Foundation/NSValue.h> 24 25#import <NGExtensions/NSCalendarDate+misc.h> 26 27#import <SOPE/NGCards/iCalRecurrenceRule.h> 28 29#import <SOGo/NSCalendarDate+SOGo.h> 30#import <SOGo/SOGoDateFormatter.h> 31#import <SOGo/SOGoUser.h> 32#import <SOGo/SOGoUserDefaults.h> 33#import <SOGo/WOResourceManager+SOGo.h> 34 35#import <SoObjects/Appointments/SOGoAppointmentFolder.h> 36#import <SoObjects/Appointments/SOGoAppointmentFolders.h> 37 38#import "UIxCalDayTable.h" 39 40@class SOGoAppointment; 41 42@implementation UIxCalDayTable 43 44- (id) init 45{ 46 SOGoUser *user; 47 SOGoUserDefaults *ud; 48 49 if ((self = [super init])) 50 { 51 user = [context activeUser]; 52 ud = [user userDefaults]; 53 ASSIGN (timeFormat, [ud timeFormat]); 54 55 daysToDisplay = nil; 56 calendarsToDisplay = nil; 57 hoursToDisplay = nil; 58 numberOfDays = 1; 59 startDate = nil; 60 currentView = nil; 61 currentCalendar = nil; 62 currentTableDay = nil; 63 currentTableHour = nil; 64 weekDays = [locale objectForKey: NSWeekDayNameArray]; 65 [weekDays retain]; 66 dateFormatter = [user dateFormatterInContext: context]; 67 [dateFormatter retain]; 68 } 69 70 return self; 71} 72 73- (void) dealloc 74{ 75// if (allAppointments) 76// [allAppointments release]; 77 [weekDays release]; 78 [daysToDisplay release]; 79 [calendarsToDisplay release]; 80 [currentView release]; 81 [hoursToDisplay release]; 82 [dateFormatter release]; 83 [timeFormat release]; 84 free(daysNumbersToDisplay); 85 [super dealloc]; 86} 87 88- (void) setNumberOfDays: (NSNumber *) aNumber 89{ 90 numberOfDays = [aNumber intValue]; 91 [daysToDisplay release]; 92 daysToDisplay = nil; 93} 94 95- (NSNumber *) numberOfDays 96{ 97 return [NSNumber numberWithUnsignedInt: numberOfDays]; 98} 99 100- (void) setStartDate: (NSCalendarDate *) aStartDate 101{ 102 startDate = [aStartDate beginOfDay]; 103 [daysToDisplay release]; 104 daysToDisplay = nil; 105} 106 107- (NSCalendarDate *) startDate 108{ 109 if (!startDate) 110 startDate = [[super startDate] beginOfDay]; 111 112 return startDate; 113} 114 115- (NSCalendarDate *) endDate 116{ 117 NSCalendarDate *endDate; 118 119 endDate = [[self startDate] dateByAddingYears: 0 120 months: 0 121 days: numberOfDays - 1]; 122 123 return [endDate endOfDay]; 124} 125 126- (void) setCurrentView: (NSString *) aView 127{ 128 ASSIGN(currentView, aView); 129} 130 131- (NSString *) currentView 132{ 133 return currentView; 134} 135 136- (NSArray *) hoursToDisplay 137{ 138 unsigned int currentHour, lastHour; 139 140 if (!hoursToDisplay) 141 { 142 hoursToDisplay = [NSMutableArray new]; 143 currentHour = [self dayStartHour]; 144 lastHour = [self dayEndHour]; 145 while (currentHour < lastHour) 146 { 147 [hoursToDisplay addObject: [NSNumber numberWithInt: currentHour]]; 148 currentHour++; 149 } 150 [hoursToDisplay addObject: [NSNumber numberWithInt: currentHour]]; 151 } 152 153 return hoursToDisplay; 154} 155 156- (NSString *) currentHourId 157{ 158 return [NSString stringWithFormat: @"hour%d", [currentTableHour intValue]]; 159} 160 161/** 162 * Return an array of NSCalendarDate instances matching the requested time period 163 * and the week days enabled in the user's defaults. 164 */ 165- (NSArray *) daysToDisplay 166{ 167 NSCalendarDate *currentDate; 168 NSString *weekDay; 169 int count, enabledCount; 170 171 if (!daysToDisplay) 172 { 173 daysToDisplay = [NSMutableArray new]; 174 daysNumbersToDisplay = malloc (numberOfDays * sizeof (unsigned int)); 175 currentDate = [[self startDate] hour: [self dayStartHour] 176 minute: 0]; 177 178 for (count = 0, enabledCount = 0; count < numberOfDays; count++) 179 { 180 weekDay = iCalWeekDayString[[currentDate dayOfWeek]]; 181 if ([enabledWeekDays count] == 0 || [enabledWeekDays containsObject: weekDay]) 182 { 183 [daysToDisplay addObject: currentDate]; 184 daysNumbersToDisplay[enabledCount] = count; 185 enabledCount++; 186 } 187 currentDate = [currentDate tomorrow]; 188 } 189 } 190 191 return daysToDisplay; 192} 193 194- (NSArray *) calendarsToDisplay 195{ 196 if (!calendarsToDisplay) 197 { 198 NSArray *folders; 199 SOGoAppointmentFolders *co; 200 SOGoAppointmentFolder *folder; 201 NSMutableDictionary *calendar; 202 unsigned int count, foldersCount; 203 NSString *folderName, *fDisplayName; 204 BOOL isActive; 205 206 co = [self clientObject]; 207 folders = [co subFolders]; 208 foldersCount = [folders count]; 209 calendarsToDisplay = [[NSMutableArray alloc] initWithCapacity: foldersCount]; 210 for (count = 0; count < foldersCount; count++) 211 { 212 folder = [folders objectAtIndex: count]; 213 isActive = [folder isActive]; 214 if (isActive != NO) { 215 calendar = [NSMutableDictionary dictionary]; 216 folderName = [folder nameInContainer]; 217 fDisplayName = [folder displayName]; 218 if (fDisplayName == nil) 219 fDisplayName = @""; 220 if ([fDisplayName isEqualToString: [co defaultFolderName]]) 221 fDisplayName = [self labelForKey: fDisplayName]; 222 [calendar setObject: [NSString stringWithFormat: @"/%@", folderName] 223 forKey: @"id"]; 224 [calendar setObject: fDisplayName forKey: @"displayName"]; 225 [calendar setObject: folderName forKey: @"folder"]; 226 [calendar setObject: [folder calendarColor] forKey: @"color"]; 227 [calendar setObject: [NSNumber numberWithBool:isActive] forKey: @"active"]; 228 [calendar setObject: [folder ownerInContext: context] 229 forKey: @"owner"]; 230 [calendarsToDisplay addObject: calendar]; 231 } 232 } 233 } 234 235 return calendarsToDisplay; 236} 237 238- (void) setCurrentTableDay: (NSCalendarDate *) aTableDay 239{ 240 currentTableDay = aTableDay; 241} 242 243- (NSCalendarDate *) currentTableDay 244{ 245 return currentTableDay; 246} 247 248- (void) setCurrentCalendar: (NSMutableDictionary *) aCalendar 249{ 250 ASSIGN(currentCalendar, aCalendar); 251} 252 253- (NSMutableDictionary *) currentCalendar 254{ 255 return currentCalendar; 256} 257 258- (void) setCurrentTableHour: (NSNumber *) aTableHour 259{ 260 ASSIGN(currentTableHour, aTableHour); 261} 262 263- (NSNumber *) currentTableHour 264{ 265 return currentTableHour; 266} 267 268- (NSString *) currentFormattedHour 269{ 270 int hour; 271 NSCalendarDate *tmp; 272 NSString *formatted = [NSString stringWithFormat: @"%d", [currentTableHour intValue]], *parse; 273 274 hour = [currentTableHour intValue]; 275 parse = [NSString stringWithFormat: @"2000-01-01 %02d:00", hour]; 276 277 tmp = [NSCalendarDate dateWithString: parse 278 calendarFormat: @"%Y-%m-%d %H:%M"]; 279 if (tmp) 280 formatted = [tmp descriptionWithCalendarFormat: timeFormat 281 locale: locale]; 282 283 return formatted; 284} 285 286- (NSString *) currentAllDayId 287{ 288 return [NSString stringWithFormat: @"allDay%@", [currentTableDay shortDateString]]; 289} 290 291- (NSString *) currentDayId 292{ 293 return [NSString stringWithFormat: @"day%@", [currentTableDay shortDateString]]; 294} 295 296- (int) currentDayNumber 297{ 298 int i = [daysToDisplay indexOfObject: currentTableDay]; 299 300 return daysNumbersToDisplay[i]; 301} 302 303- (NSNumber *) currentAppointmentHour 304{ 305 return [NSNumber numberWithInt: [currentTableHour intValue]]; 306} 307 308- (NSString *) currentYear 309{ 310 if (([currentTableDay dayOfMonth] == 1 && [currentTableDay monthOfYear] == 1) || 311 [daysToDisplay indexOfObject: currentTableDay] == 0) 312 return [NSString stringWithFormat: @"%i", [currentTableDay yearOfCommonEra]]; 313 314 return nil; 315} 316 317- (NSString *) labelForDay 318{ 319 return [weekDays objectAtIndex: [currentTableDay dayOfWeek]]; 320} 321 322- (NSString *) labelForMonth 323{ 324 NSString *calendarFormat; 325 BOOL isFirstDay; 326 327 isFirstDay = NO; 328 calendarFormat = @"%b"; 329 330 if ([currentView hasSuffix: @"dayview"]) 331 { 332 isFirstDay = YES; 333 calendarFormat = @"%B"; 334 } 335 else if ([currentTableDay dayOfMonth] == 1 || [daysToDisplay indexOfObject: currentTableDay] == 0) 336 { 337 isFirstDay = YES; 338 } 339 340 return isFirstDay? [currentTableDay descriptionWithCalendarFormat: calendarFormat locale: locale] : nil; 341} 342 343- (NSString *) labelForDate 344{ 345 return [dateFormatter shortFormattedDate: currentTableDay]; 346} 347 348- (NSString *) labelForCalendar 349{ 350 return [currentCalendar objectForKey: @"displayName"]; 351} 352 353- (NSString *) colorForCalendar 354{ 355 return [currentCalendar objectForKey:@"color"]; 356} 357 358// - (NSDictionary *) _adjustedAppointment: (NSDictionary *) anAppointment 359// forStart: (NSCalendarDate *) start 360// andEnd: (NSCalendarDate *) end 361// { 362// NSMutableDictionary *newMutableAppointment; 363// NSDictionary *newAppointment; 364// BOOL startIsEarlier, endIsLater; 365 366// startIsEarlier 367// = ([[anAppointment objectForKey: @"startDate"] laterDate: start] == start); 368// endIsLater 369// = ([[anAppointment objectForKey: @"endDate"] earlierDate: end] == end); 370 371// if (startIsEarlier || endIsLater) 372// { 373// newMutableAppointment 374// = [NSMutableDictionary dictionaryWithDictionary: anAppointment]; 375 376// if (startIsEarlier) 377// [newMutableAppointment setObject: start 378// forKey: @"startDate"]; 379// if (endIsLater) 380// [newMutableAppointment setObject: end 381// forKey: @"endDate"]; 382 383// newAppointment = newMutableAppointment; 384// } 385// else 386// newAppointment = anAppointment; 387 388// return newAppointment; 389// } 390 391// - (NSArray *) appointmentsForCurrentDay 392// { 393// NSMutableArray *filteredAppointments; 394// NSEnumerator *aptsEnumerator; 395// NSDictionary *currentDayAppointment; 396// NSCalendarDate *start, *end; 397// int endHour; 398 399// if (!allAppointments) 400// { 401// allAppointments = [self fetchCoreAppointmentsInfos]; 402// [allAppointments retain]; 403// } 404 405// filteredAppointments = [NSMutableArray new]; 406// [filteredAppointments autorelease]; 407 408// start = [currentTableDay hour: [self dayStartHour] minute: 0]; 409// endHour = [self dayEndHour]; 410// if (endHour < 24) 411// end = [currentTableDay hour: [self dayEndHour] minute: 59]; 412// else 413// end = [[currentTableDay tomorrow] hour: 0 minute: 0]; 414 415// aptsEnumerator = [allAppointments objectEnumerator]; 416// currentDayAppointment = [aptsEnumerator nextObject]; 417// while (currentDayAppointment) 418// { 419// if (([end laterDate: [currentDayAppointment 420// valueForKey: @"startDate"]] == end) 421// && ([start earlierDate: [currentDayAppointment 422// valueForKey: @"endDate"]] == start)) 423// [filteredAppointments 424// addObject: [self _adjustedAppointment: currentDayAppointment 425// forStart: start andEnd: end]]; 426// currentDayAppointment = [aptsEnumerator nextObject]; 427// } 428 429// return filteredAppointments; 430// } 431 432// - (void) setCurrentAppointment: (NSDictionary *) newCurrentAppointment 433// { 434// currentAppointment = newCurrentAppointment; 435// } 436 437// - (NSDictionary *) currentAppointment 438// { 439// return currentAppointment; 440// } 441 442- (NSString *) appointmentsClasses 443{ 444 return [NSString stringWithFormat: @"appointments appointmentsFor%dDays", 445 numberOfDays]; 446} 447 448// - (NSString *) daysViewClasses 449// { 450// NSString *daysView; 451 452// if ([currentView isEqualToString:@"multicolumndayview"]) 453// daysView = @"daysView daysViewForMultipleDays"; 454 455// else 456// daysView = [NSString stringWithFormat: @"daysView daysViewFor%dDays", numberOfDays]; 457 458// return daysView; 459//} 460 461// - (NSString *) daysViewHeaderClasses 462// { 463// return [NSString stringWithFormat: @"%@ daysHeader", [self daysViewClasses]]; 464// } 465 466- (NSString *) dayClasses 467{ 468 NSMutableString *classes; 469 unsigned int realDayOfWeek; 470 471 classes = [NSMutableString stringWithString: @"day"]; 472 realDayOfWeek = [currentTableDay dayOfWeek]; 473 474 if (numberOfDays > 1) 475 { 476 if (realDayOfWeek == 0 || realDayOfWeek == 6) 477 [classes appendString: @" weekEndDay"]; 478 if ([currentTableDay isToday]) 479 [classes appendString: @" dayOfToday"]; 480 } 481 482 return classes; 483} 484 485- (NSString *) clickableHourCellClass 486{ 487 NSMutableString *cellClass; 488 int hour; 489 SOGoUserDefaults *ud; 490 491 cellClass = [NSMutableString string]; 492 hour = [currentTableHour intValue]; 493 ud = [[context activeUser] userDefaults]; 494 [cellClass appendFormat: @"clickableHourCell clickableHourCell%d", hour]; 495 if (hour < [ud dayStartHour] || hour > [ud dayEndHour] - 1) 496 [cellClass appendString: @" outOfDay"]; 497 498 return cellClass; 499} 500 501- (BOOL) isMultiColumnView 502{ 503 if ([currentView isEqualToString:@"multicolumndayview"]) 504 return YES; 505 506 return NO; 507} 508 509- (BOOL) isNotMultiColumnView 510{ 511 if ([currentView isEqualToString:@"dayview"] || [currentView isEqualToString:@"weekview"]) 512 return YES; 513 514 return NO; 515} 516 517- (BOOL) isWeekView 518{ 519 return [currentView isEqualToString:@"weekview"]; 520} 521 522@end 523