/* proj.act --miscelaneous methods, initializations */ /* globals for application colors */ Actor[#CritColor]:=RED; Actor[#SlackColor]:=BLUE; !! /* globals for conditional compilation during debugging etc */ Actor[#Debug] := false; /* debugging enable/disable */ Actor[#Trace] := false; /* trace recalc calls */ Actor[#CurPos] := 0; /* text dump of network uses this */ !! /* methods for system classes */ now(Window)!! /* Set the current cursor position in client coords. This is useful when implementing a keyboard interface. */ Def setCursorPos(self, pos | scrnPos) { scrnPos := clientToScreen(self, pos); Call SetCursorPos(scrnPos.x, scrnPos.y); }!! /* Return a point of the current cursor position in client coords. This is useful when implementing a keyboard interface. */ Def getCursorPos(self | struct, scrnPos, lpr) { struct := new(Struct,4); /* to store the point */ lpr := lP(struct); /* long pointer */ Call GetCursorPos(lpr); /* device coords */ scrnPos := pointAt(lpr); /* get the data */ freeHandle(struct); /* free up memory */ ^screenToClient(self, scrnPos); /* screen coords */ }!! /* Return a point giving the text width and height in the given display context. e.g. for system font the return value might be 8@15 for 8 pixels wide, 15 high, depending on the Windows drivers. */ Def textSize(self, hDC | tm1, tm2) { tm1 := new(Struct, 31); /* to hold the info */ Call GetTextMetrics(hDC, lP(tm1)); /* call Windows fn */ tm2 := getData(tm1); /* get the data back */ freeHandle(tm1); /* free up memory */ ^point(low(tm2[10]), low(tm2[0])); /* width@height */ }!! now(TextWindow)!! /* Print a line in a TextWindow. */ Def printLine(self, str) { printString(self, str); eol(self); }!! now(Dialog);!! /* Run the dialog with the appropriate resource and parent. Display a warning if it fails. */ Def checkRunModal(self, res, parent | retValue) { retValue := runModal(self, res, parent); if retValue == NOMEM beep(); errorBox(loadString(PW_WARNING), loadString(PW_ERRMEM1) + CR_LF + loadString(PW_ERRMEM2)); endif; ^retValue; }!! now(String);!! /* Return the string in a field of fieldSize. Truncate or pad with blanks as necessary. */ Def field(self, fieldSize | size) { if fieldSize < size := size(self) ^subString(self, 0, fieldSize) /* truncate */ else ^self + stringOf(' ', fieldSize - size); /* pad */ endif; }!! /* Convert to decimal. Safe if length = 0. */ Def asDec(self) { if size(self) = 0 ^ 0; else ^asInt(self,10); endif; }!! /* Show a yesNoBox with self as the caption, str as message. Return value of 6 = IDYES, 7 = IDNO. */ Def yesNoBox(self, str) { ^new(ErrorBox, ThePort, str, self, 4); }!! /* Convert a string into a Date object. Use the international string format. Return nil if not a valid date. */ Def asIntlDate(self | sep, format, ints, posn, pos1, pos2, mm, dd, yy) { sep := getProfileString(System, "intl", "sDate"); if sep = "" then sep := "/"; endif; format := getProfileString(System, "intl", "iDate"); select case format = "2" posn := #(2 0 1); /* YYMMDD */ endCase case format = "1" posn := #(1 0 2); /* DDMMYY */ endCase default posn := #(0 1 2); /* MMDDYY */ endSelect; ints := new(Array, 3); pos1 := find(self, sep, 0); if not(pos1) ^nil; endif; ints[0] := asDec(subString(self, 0, pos1)); pos2 := find(self, sep, pos1+1); if not(pos2) ^nil; endif; ints[1] := asDec(subString(self, pos1+1, pos2)); ints[2] := asDec(subString(self, pos2+1, size(self))); mm := ints[posn[0]]; dd := ints[posn[1]]; yy := ints[posn[2]]; if not(mm) cor mm > 12 cor mm < 1 ^nil; endif; if not(dd) cor dd > 31 cor dd < 1 ^nil; endif; if not(yy) cor yy < 0 ^nil; endif; if yy < 100 yy := yy + 1900; endif; ^date(mm, dd, yy); }!! /* Report an error if the date string is invalid, otherwise return the Date object. Ignore empty strings. Report the error according to international date format. */ Def checkDate(self | retValue, iDate, format) { if self <> "" cand not(retValue := asIntlDate(self)) beep(); iDate := getProfileString(System, "intl", "iDate"); select case iDate = "2" format := loadString(PW_YYMMDD); endCase case iDate = "1" format := loadString(PW_DDMMYY); endCase default /* "0" or unspecified */ format := loadString(PW_MMDDYY); endSelect; errorBox(loadString(PW_ERRDATE1), asString(self) + loadString(PW_ERRDATE2) + format + loadString(PW_ERRDATE3)); endif; ^retValue; }!! now(Date)!! /* Modify the asString method to use intl format. */ Def asString(self) { ^asIntlString(self); }!! /* Convert a date to a string. NilClass:checkString returns an empty string. */ Def checkString(self) { ^asString(self); }!! /* Return date in international string format. Abbreviate the year. */ Def asIntlString(self | sep, form, da, yr) { sep := getProfileString(System, "intl", "sDate"); if sep = "" sep := "/"; endif; form := getProfileString(System, "intl", "iDate"); da := asDateArray(self); if da[2] > 1900 yr := subString(asString(da[2]), 2, 4); else yr := asString(da[2]); endif; select case form = "2" /* YYMMDD */ ^yr+sep+asString(da[1])+sep+asString(da[0]); endCase case form = "1" /* DDMMYY */ ^asString(da[1])+sep+asString(da[0])+sep+yr; endCase default /* MMDDYY */ ^asString(da[0])+sep+asString(da[1])+sep+yr; endSelect; }!! now(Int)!! /* Create a date object with a starting value. */ Def date(self, dd, yy) { ^date(new(Date), self, dd, yy); }!! now(NilObject)!! /* Return an empty string. For compatibility with the Date class so you can checkString(nil) or checkString(aDate) and get a string. */ Def checkString(self) { ^""; }!! now(Collection)!! /* Returns true (the position) if the elem is in the collection. Uses a sequential search. Descendent classes redefine this using more efficient means where possible. */ Def in(self, elem) { do(size(self), {using(i) if self[i] = elem ^i; endif; /* found */ }); ^false; /* not found */ }!! now(Dictionary)!! /* Returns the value (true) if the key is in the Dictionary. */ Def in(self, key | assoc) { assoc := assocAt(self, key); if assoc ^assoc.value; else ^false; endif; }!! now(Object)!! /* This method overrides the default case of objects not being storable so that Project, Milestone, Task etc are all storable. */ Def notStorable(self) { ^nil; }!!