Formatting of date and time is a localizable service. In addition to formatting standard date and time, Rosemary also introduces a framework for calendar display.A calendar determines how a given day corresponds to day-of-month, month, year, and day-of-week. The interface is defined by the abstract class Calendar. Currently, the single implementation of this class is GregorianCalendar.
A date-time formatter knows how to format a date or time into human readable text and is dependent on a calendar. The interface for formatting dates and times is provided by the DateTimeFormatter abstract class. Class SystemDateTimeFormatter implements the operations of this interface.
You should call DateAsTextWithFormat() to display formatted dates so that the date will show up in the proper format in a given locale. The indexicals iMonthNames, iShortMonthNames, iDayNames, iShortDayNames, iVeryShortDayNames, iTimeTextPieces, and iSpecialDateNames have been removed. The data that was contained in these indexicals have been moved into fields of the date/time formatters. This was done to discourage clients from doing date and time formatting themselves.
Attributes have been added to allow code to determine what format dates and times are presented in on screen. The attribute DateTimeFormatter_NumericDateFormat returns whether dates are in year/month/day, day/month/year, or month/day/year format. The attribute DateTimeFormatter_MinutesSeparator returns the text character that is used between hours and minutes.
The existing class DateTime contains operations that allow you to convert dates into different units of time as well as compare dates. DateTime also provides the high level interface for producing formatted date and time Text objects. These operations call through to the lower level formatter and calendar routines.
Different countries start the week on different days. This is specified by the firstDayOfFormattedWeek field in class DateTimeFormatter. The datebook and the date chooser respect this value. Replaced the DateTime_FirstDayOfWeek() intrinsic with two more convenient intrinsics, WeekDisplayIndexToDayOfWeek() and DayOfWeekToWeekDisplayIndex(). Added the attribute DateTimeFormatter_ShowEightDaysInWeek which is used by TaskView to decide whether to show seven or eight days in the week view. Eight days are handy in countries that split weekends between two weeks, but look odd if the week starts on Monday.
The Rosemary Magic Cap API tries to avoid having multiple operations have the same name but different interfaces. Since Magic Cap doesn't do polymorphism, this is just plain confusing. Many operations have been removed or renamed to avoid this problem. Removed operations that get and set various fields of class TimedEvent, ScheduledTime and BasicSchedule. Deleted the Adjust(), Interval(), Globalize() and Localize() operations. Removed class CalendarTime.
Moved System_Display24HourTime to a more logical home inside of DateTimeFormatter.
The old API that converted data and time values from strings has been replaced with methods that use text objects.
Old operation New operation DateStringFromDays DateTextFromDays SetTimeFromString SetTimeFromText StringToTime TextToTime StringToTimeRange TextToTimeRange TimeString TimeAsText
The datebook takes advantange of the revamped searching framework. Sniffy can find text in notes, viewables in notes, viewables on the task editor and viewables in the task view. The new class DatebookSearchResult knows how to display these four types of objects.The taskEditor field of Task objects must contain an indexical reference.
The attribute Task_Priority is now a signed short type.
Added the attribute Task_MakeAlternativeHoliday and a corresponding field. In Japan, if a Sunday is a holiday, the following Monday is also a holiday. This attribute tells the datebook to generate a holiday instance for these Mondays.
Removed task specific text mapping cases from TextMapping_ValueFromIndex into TaskTextMapping_ValueFromIndex. ValueFromIndex() uses iCurrentTask as the reference task if the parameter that it was passed isn't a task.
Removed the field TaskProxy_rsvpCard. The RSVP card used to be created and stored in this field during ICF encoding. The RSVP card is now created by TaskProxy_Confirmed.
Renamed Task_ShortSubjectAsText to ShortSubject().
The datebook supports two new repeating appointment types: repeating Tuesday/Thursday and repeating Monday/Wednesday/Friday.
The datebook supports tasks that have creative repeat intervals. These types of tasks cannot be created by the user because the repeat intervals don't show up in the repeat interval choice box. Created a new class, SpecialRepeatingTask, that determines the repeat intervals. Added a new repeat mode, repeatSpecial, to distinguish special repeating tasks from regular repeating tasks. The Task_NewTask method is now a normal operation instead of an intrinsic so that SpecialRepeatTask can override it. This means that it has a new operation number. Added the operation Task_NearestMatchingTaskDate. This operation should be used instead of DateTime_NearestMatchingDate. SpecialRepeatTask overrides this operation to find the correct dates for special repeating tasks.
Fixed a bug where scrolling through the repeat options in the choice box wouldn't always determine the correct default stop date. The old code wanted to make sure never to use the default stop date if the user has entered a stop date and was preventing the default stop date from being used once the stop date had been set once by either the user or from code.
Fixed a bug where the user could change the date of locked tasks by dropping the task on a different day view.
The Rosemary Magic Cap API tries to avoid having multiple operations have the same name but different interfaces. Since Magic Cap doesn't do polymorphism, this is just plain confusing. Many operations have been removed or renamed to avoid this problem. Removed the operations FindAvailableTime() and FindMatchinginstance().
The taskFlags field of class Task has been split into individual boolean attributes.
The CanDelete() operation in Magic Cap specifies whether or not an object is deletable. Rosemary adds another level of deletability that specifies that an object should only be deleted with the user's knowledge. This is implemented by the new attribute Object_CanDeleteAtWill. By default, CanDeleteAtWill() returns CanDelete(). If CanDelete() returns true, but CanDeleteAtWill() returns false, that means that the user should be told that the object is being deleted. The case of returning false for CanDelete() but true for CanDeleteAtWill() never arises. Class Task returns false for CanDeleteAtWill() so that user data will not be lost.
Removed many redundant attributes from class Task: ShortSubject(), ShortTaskDate(), ShortTaskStopDate(), ShortTaskSummary() and ShortTaskTime(). Merged TimeText() into TaskTime().
Added field to schedule bar that lets you specify whether the tick marks under the hours in the datebook are lined up on the hour or half hour. This field is ScheduleBar_tickExactHour.
Removed datebook specific text mappings from iStandardTextMapping.
Renamed Task_MatchText to Task_TaskContainsText. Renamed Task_MatchImage to Task_TaskDisplaysImage.
Tasks now have the capability of being undeletable. There is a new boolean field, Task_undeletableTask which specifies whether or not a task is deletable. The interface for this field is the Task_CanDelete attribute.
Add the macro FailWithMessage() that stops in the debugging with a Complain() before throwing the exception. This is incredibly useful in debug versions of software so you can figure out what's wrong before the exception is actually thrown. Most of the time, you would use this macro instead of calling Fail() directly.The system will now complain if you destroy an object that contains bad references. If you destroy a sub-object before you destroy the owning object, you now need to set the reference to the sub-object in the owning object to nilObject before destroying the sub-object.
Rosemary enforces the rule that you are not allowed to dispatch inside calls to BeginRead/EndRead and BeginModify/EndModify. If you dispatch to a Magic Cap method that might move memory while an object is locked, Magic Cap will stop in the debugger telling you what happened.
Many of the debug version calls for getting object names, and for spitting out literal strings of some data structures have been moved out of the Object class into a new class called DebugNamesDatabase. This is an abstract class that defines the interface to these calls. The class DebugNamesLibrarian implements the functionality of scanning debug packagse for names of classes, operations, etc. The single instance of DebugNamesLibrarian in the system is referenced by the new indexical iDebugNamesDatabase.
The concept of object dumping has been moved out of the system itself and into the inspector. A new class, ObjectDumper, is now the superclass for Inspector. The operation Object_Inspect was never used and has been removed.
The locale and numbering plan classes and operations have been renamed in Rosemary. All locale related names that relate to dialing have been changed to "DialingCountry". Similarly, number plan related names have been changed to "DialingLocation", which is what people called them anyway. The term "locale" is now used in only in relation to a specific localization of Magic Cap. The classes, fields, operations and indexicals that have been renamed are list here.
| Old class name | New class name | |
|---|---|---|
| Locale | DialingCountry | |
| LocaleListView | DialingCountryListView | |
| EditableLocale | EditableDialingCountr | |
| NumberingPlan | DialingLocation | |
| HotelNumberingPlan | HotelDialingLocation | |
| EditNumberingPlanScene | EditDialingLocationScene | |
| NumberingPlanStamp | DialingLocationStamp | |
| Old field names | New field names | |
| Locale_isSystemLocale | DialingCountry_isBuiltIn (this field has nothing to do with dialing or locales) |
|
| Locale_usDirect | DialingCountry_homeCountryDirectCode | |
| NumberingPlan_locale | DialingLocation_dialingCountry | |
| Old method names | New method names | |
| [Set]IsSystemLocale() | [Set]IsBuiltIn() | |
| [Set]CustomAccessNumberLocale() | [Set]CustomAccessNumberDialingCountry() | |
| EditNewLocale() | EditNewDialingCountry() | |
| [Set]USDirect() | [Set]HomeCountryDirect() | |
| EditNewNumberingPlan() | EditNewDialingLocation() | |
| [Set]NumberPlan() | [Set]DialingLocation() | |
| [Safe]DeleteCurrentNumberingPlan() | [Safe]DeleteCurrentDialingLocation() | |
| [Set]Country() | [Set]CountryCode() | |
| [Set]DialoutCode() | [Set]InternationalAccessCode() | |
| [Set]NationalAccess() | [Set]NationalAccessCode() | |
| HasMultipleDialoutCodes() | HasMultipleOutsideLineCodes() | |
| Old indexical names | New indexical names | |
| iLocales | iDialingCountries | |
| iCurrentLocale | iCurrentDialingCountry | |
| iPrototypeLocale | iPrototypeDialingCountry | |
| iLocaleEditSteps | iDialingCountryEditSteps | |
| iChangedLocales | iChangedDialingCountry | |
| iChangedToLocales | iChangedToDialingCountries | |
| iEditedNumberingPlan | iEditedDialingLocation | |
| iNumberingPlanImages | iDialingLocationImages | |
| iNumberingPlanStamp | iDialingLocationStamp | |
| iPrototypeNumberingPlan | iPrototypeDialingLocation | |
| iDeleteNumberingPlanPrompt | iDeleteDialingLocationPrompt | |
| iNumberingPlan | iDialingLocation |
Dialing countries know a lot more about the phone number formats they describe. New fields in the DialingCountry class describe: the last area code used on a per country basis, correct phone number normalization per country, arbitrary mapping from numbers to digits, lists of special numbers (411, 911) and special area codes (800, 900) for each country, lists for friendly countries that are treated as domestic long distance for dialing purposes (like the U.S. and Canada), a valid from date which can be used to update DialingCountry objects when dialing formats change, preferred dialing methods and speeds for each country, area code and local number sizes for phone number checking, and information about whether a country has area codes, whether it always requires the area code, whether it has local toll calls, whether it can have multiple outside line codes and whether or not the national access code is considered separate from the area code.To better support international dialing, a new phone number format that uses Text objects replaces Telenumbers for dialing purposes has been introduced. The CountryCode() attribute can contain disambiguous ISO3166 codes. This format is known as the global phone number.
Because dialing will no longer use Telenumbers, Dialing_CreateDialableNumber should be used instead of Telenumber_BuildDialableNumber. Class Dialing takes over the phone number formatting functionality that used to be implemented by Telenumber. The operation Dialing_GlobalPhoneNumber takes a telenumber or telephone address info object and returns a text object that is formatted correctly for the dialing code. The text object will be formatted as either "+country code\tdomestic number" or "+country code\tdomestic number\textension".
The mixin class HasPhoneNumber allows you to easily identify a class with a phone number by calling Implements(object, HasPhoneNumber_);.
You can call Dialing_IsInternational to determine if a global phone number is an international number given the current system dialing setup.
The phone setup interface has been completely redesigned in Rosemary, allowing for greater user customizability of how Magic Cap dials phone numbers. All editing is done from the new EditDialingLocationScene, which appears when you pick a new dialing location from the stamper. Each dialing location now has individual information about carrier codes, local tolls, dialing speed, etc. These attributes used to be global to all dialing locations. These preferences are all maintained in instances of class DialingLocation. Because of this, the classes CustomAccessDialingLocation, HotelCustomAccessDialingLocation, and DialingOrderCallingCard have been removed; parts of their functionality that are still required have been merged into DialingLocation, HotelDialingLocation and CallingCard respectively. Some of these preferences used to live in the dialing control panel, which no longer exists.
Rosemary supports a mode of dialing where an area code must be dialed, but the national access number should not be. In the phone setup scene, if the user checks "always dial area code", a new checkbox, "don't dial national access locally" appears. If this box is checked, the national access code (1 for USA) will not be added to numbers that are in the same area code as the same dialing location. Added the DialingLocation_dontDialNationalAccessLocally field and the corresponding attribute so that the user can specify whether or not the access code should be dialed for numbers in the same area code.
Some additional list view classes have been created to support the new user interface. EditableTargetedListView allows a list view to edit its selection with the attribute window's spout pointing to the center of the list view. DialingCountryListView is a subclass of EditableTargetedListView that allows users to add new locales from from the list view.
Class SystemLocale, which described locales which are built into the system, has been merged into the generic DialingCountry class. A new SystemLocale class has been created that maintains miscellaneous information about the location the system is localized for. Currently, there are names for the language and target country in both human readable and ISO-639 and ISO-3166 compliant versions, a flag specifying whether the locale uses the metric system, and information about the default page size and text orientation. The single instance of SystemLocale is referenced by the iSystemLocale indexical. The Telescript class LanguageSpecified now initializes its language information from this object, enabling agents to send back messages from the cloud in the correct language.
Added the indexical iDialingLocationSetupPlace. This is the place that lets the user sep up the dialing location. This indexical was added to separate the phone user interface from the dialing location interface.
The HasPhoneLabel_callee field no longer stores either an address card, a contact addresses object, or text. It will now only store address card-like objects. HasPhoneLabel_UpdateDescription no longer creates a new text object to store information in unless there actually is information to store. This means that you should no longer pass telenumbers to PhonePanel_StartPhoneCall.
Class PhoneCallCard was the only HasPhoneLabel subclass that stored text in the callee field. PhoneCallCard has a new field, dialedNumber, which stores the text now.
The numberingFlags field of class DialingLocation has been split into individual Boolean attributes.
PhonePanel_StartPhoneCall will localize a phone number before storing it in numberToDial. Text phone numbers are only localized when the dialLiterally bit is clear, so that numbers entered by the user on the phone pad aren't messed up. StartPhoneCall() now always sets up globalPhoneNumber. Nothing is done if the phone number has no digits.
Added a check in PhonePanel_StartPhoneCall to prevent dialing numbers longer than 100 digits. This is a limit of the software modem. (It's not as a big a deal as you think; the old Rockwell chip had a 62 digit limit.)
Rosemary uses true dynamic linking to support interpackage operations. Because the new runtime in Rosemary no longer requires context objects to distinguish between packages, the programming model for defining public package interfaces has changed. In source code, calling conventions have been simplified greatly; calling FindActiveSoftwarePackageByCitation() to get a package context object is no longer required. Instead, you simply use the operation of interest from the other package.A package defines the part of its interface it wishes to export within class definition files using the define interface keyword. Packages are allowed to export classes, operations, intrinsics and indexicals for use by other packages. Packages do not have to export all operations of an exported class, effectively allowing a package to keep certain operation interfaces private to the package itself. Here is an example exported interface:
define interface ArrangerInterface; class Arranger; operation InstallIntoDrawer; end interface;
This interface definition specifies that this package will allow other packages to create instances of its Arranger class, and to call its InstallIntoDrawer() operation. Notice that even though the Arranger class is exported for public instantiation, only the InstallIntoDrawer() operation can be called by other packages. Any other operations defined by Arranger are not externally visible.Developers that create packages with public interfaces are still required to supply a class definition file with public class, indexical and operation definitions and the interface definition that specifies these entities.
A package that wishes to use the interface published by another package does so by using the read and import keywords within class definition files. Use the read keyword to include the public interface information from another package:
read "ExportTest.cdef";
Use the import keyword to specify that a particular interface will be used in your package. There are two ways this keyword can be used. The first method defines a strong dependency between two packages; if the interface to be imported does not exist in the system, the importing package will not be activated, and a package-defined message is displayed:
import ArrangerInterface or say iCantFindArrangerInterface;
The second method defines a weak dependency between two packages. If the interface to be imported does not exist in the system, the importing package is still activated, but now it is responsible for making sure that the imported interface is present before it is used:
weakly import ArrangerInterface;