#import "Aprica.h"
// Aprica2
// copyright Pirmin Braun 1997-2007 - pirmin@pirmin.de
// all Rights reserved;
@implementation PBWOAsso
ACCESSm(boxId,setBoxId)
ACCESSm(assoID,setAssoID)
ACCESSm(onChange,setOnChange)
ACCESSm(refdTableName,setRefdTableName)
ACCESSm(targetModulName,setTargetModulName)
//dbName soll hier case-Sensitive sein;
ACCESSm(dbName, setDbName)
ACCESSm(doku,setDoku)
// keine retain-cycles:
- (PBWOEditor *)tvc;
{ return tvc;
}
- (void)setTvc:(PBWOEditor *)e;
{ tvc = e;
}
- (void)setGuiName:(NSString *)v;
{ if(guiName == v)return;
[guiName release];
guiName = [v retain];
}
- (BOOL)isAusgeblendet;
{ return !isCAsso && ([[tvc hiddenFieldNames]ofk:dbName]!=nil);
}
- (int)width;
{ //breite des gesamten controls f. Area return width;
}
- (void)setWidth:(int)v;
{ width=v;
}
- (int)height;
{ //hoehe des gesamten controls f. Area return height;
}
- (void)setHeight:(int)v;
{ height=v;
}
- (int)lines;
{ int l = height / LINEHEIGHT;
if(height%LINEHEIGHT > 0.0) l++; //aufrunden
return l;
}
- (int)editSize;
{ //size f. input-Element
// if(isDate)return 13; // 10 + Editierplatz
return (editWidthPixel - 24) / 6;
}
- (PBDDAttribute *)pba; {return pba;}- (NSString *)alignment;
{ return [pba alignment];
}
- (void)resetToOriginal;
{ [self setPba:pba];
[self cacheFlags];
}
- (void)setDataTypS:(NSString *)v;
{// convenience fuer scripting
if([v iE:SC_DT_CHAR]){dataTyp = DT_CHAR; return;} if([v iE:SC_DT_MONEY]){dataTyp = DT_MONEY; return;} if([v iE:SC_DT_INT]){dataTyp = DT_INT; return;} if([v iE:SC_DT_FLOAT]){dataTyp = DT_FLOAT; return;} if([v iE:SC_DT_DATE]){dataTyp = DT_DATE; return;} if([v iE:SC_DT_DATETIME]){dataTyp = DT_DATETIME; return;} if([v iE:SC_DT_BOOL]){dataTyp = DT_BOOL; return;}}
- (NSString *)dataTypS;
{ switch(dataTyp){ case DT_CHAR: return SC_DT_CHAR;
case DT_MONEY: return SC_DT_MONEY;
case DT_INT: return SC_DT_INT;
case DT_FLOAT: return SC_DT_FLOAT;
case DT_DATE: return SC_DT_DATE;
case DT_BOOL: return SC_DT_BOOL;
case DT_DATETIME: return SC_DT_DATETIME;
}
return SC_DT_CHAR;
}
- (BOOL)isPortlet;
{ return isPortlet;
}
- (void)setPba:(PBDDAttribute *)value;
{ int i = [_SESSION lang];
NSString *doku0;
if(value != pba){ [pba release];
pba = [value retain];
}
//wenn gleich, nur die Werte nochmal uebernehmen
isButton = ([pba targetTyp]==ATBU);
isPortlet = ([pba targetTyp]==ATPORTLET);
[self setDataTyp:[pba dataTyp]];
[self setDbName:[pba dbName]]; //evt. noch weitere haeufige Variablen redundant halten
[self cacheFlags]; //vorab, um textArea zu ermitteln
doku0 = [pba doku0];
if([doku0 hasSecurePrefix:@"onChange\n"]){ [self setOnChange:@"document.forms[0].submit();"];
doku0 = [doku0 substringFromIndex:[@"onChange\n" length]];
}
[vl release];
vl = nil;
if(i){ if(!isPortlet){ [self setGuiName:[pba guiNameForLang:i]];
}else{ [self setGuiName:[pba guiName]];
}
[self setDoku:[pba dokuForLang:i]];
}else{ [self setGuiName:[pba guiName]];
[self setDoku:[pba doku0]];
}
[self setRefdTableName:[pba refdTableName]];
[self setTargetModulName:[pba targetModulName]];
nak = [pba nak];
if(dataTyp == DT_MONEY)nak = 2; //falls bei money nicht gesetzt;
}
- (NSString *)formatOut:(NSString *)s; //bereitet s f. gui auf;
{ if(!s)s=@"";
switch(dataTyp){ case DT_DATE:
case DT_DATETIME:
if(!FILLED(s))return EON;
return [s guiDate];
case DT_MONEY:
return MONEYGUI(s);
case DT_FLOAT:
return [NSString dottedGuiFromDouble:[s doubleValue] nak:nak];
case DT_INT:
// Relationen blank wenn 0
if(isRelation && ![s intValue]){ return @"";
}
return NSS([s intValue]);
}
return s;
}
- initWith:(PBWOEditor *)tvcP andAttr:(PBDDAttribute *)attr;
{ if(![self init])return nil;
[self setTvc:tvcP];
[self setAssoID:[tvcP nextAssoID]];
[[tvcP fassos]addObject:self];
[self setPba:attr]; //bestimmt u.a. vl
[self cacheFlags];
if(isPortlet){ portletIndex = [tvc portletIndex];
}
return self;
}
- (NSString *)portletClassName;
{// die experssion eines portlet-Attribute enthaelt zeilen, die geparsed werden
// Zeile 1: optionaler ClassName
// Zeile 2: optionaler Event, fuer den sich Portlet registrieren will: registerForClear, registerForRefresh
if(FILLED([pba expression])){ NSArray *a = [[pba expression]componentsSeparatedByString:@"\n"];
NSString *s = [a firstObject];
if(FILLED(s))return s;
}
return [NSSWF @"PBWOPortlet%iA",portletIndex];
}
- (NSString *)registerFor;
{ if(FILLED([pba expression])){ NSArray *a = [[pba expression]componentsSeparatedByString:@"\n"];
if([a count]>1){ NSString *s = [a oai:1];
if(FILLED(s))return s;
}
}
return nil;
}
- (BOOL)isMemo;
{ return isPlainField && [pba length] > 255;
}
- (void)cacheFlags;
{ isRelation = FILLED(refdTableName);
hasVL = [pba hasVL];
isBool = (dataTyp==DT_BOOL);
isDate = (dataTyp==DT_DATE || dataTyp==DT_DATETIME);
isMandatory = [pba isMandatory];
shouldBeBold = [pba isPK]||isMandatory;
isPlainField = !hasVL && !isBool;
isTextArea = isPlainField && [pba length] > 255;
isButton = ([pba targetTyp]==ATBU);
isPortlet = ([pba targetTyp]==ATPORTLET);
isProtectedPba = [pba isProtected];
}
- (BOOL)isHTMLCarrier;{return isHTMLCarrier;}- (void)setIsHTMLCarrier:(BOOL)yn;{isHTMLCarrier=yn;}- (BOOL)escapeHTML;
{ return ![pba html];
}
- (BOOL)isMandatory;
{ return isMandatory;
}
- (void)setIsMandatory:(BOOL)yn;
{ isMandatory = yn;
}
- (void)dealloc
{ [val release];
[refdTableName release];
[targetModulName release];
[assoID release];
[dbName release];
[guiName release];
[vlo release];
[vl release];
[doku release];
[pba release];
[onChange release];
[super dealloc];
}
- (BOOL)onlyDescr;
{ return onlyDescr;
}
- (void)setOnlyDescr:(BOOL)yn;
{ onlyDescr = yn;
}
- (void)setPw:(BOOL)yn;
{ pw = yn;
}
- (BOOL)pw;
{ return pw;
}
- (BOOL)isBR;
{ return isBR;
}
- (void)setIsBR:(BOOL)yn;
{ isBR = yn;
}
- (BOOL)isImage;
{ return isImage;
}
- (BOOL)isNI;
{ return isNI; //namedIcon; Unterart von Image
}
- (NSString *)isImageS;
{ if(isImage){ return @"J";
}else{ return @"N";
}
}
- (NSString *)isTextAreaS;
{ if(isTextArea){ return @"J";
}else{ return @"N";
}
}
- (void)setIsImage:(BOOL)yn;
{ isImage=yn;
}
- (void)setIsNI:(BOOL)yn;
{ isNI=yn;
}
- (BOOL)isButton;
{ return isButton;
}
- (void)setIsButton:(BOOL)yn;
{ isButton = yn;
}
- (BOOL)isProtectedPba;
{ return isProtectedPba;
}
- (void)setIsProtectedPba:(BOOL)yn;
{ isProtectedPba = yn;
}
//zur pba-unabhaengigen Steuerung
- (BOOL)isProtected;
{ return isProtected;
}
- (void)setIsProtected:(BOOL)yn;
{ isProtected = yn;
}
- (NSString *)dbFromGui:(NSString *)s1 resultOK:(BOOL *)resultOK;
{//zusaetzl. 1000er punkte raus u. evt. komma in punkt
//von asso verwendet, um eingaben in val zu transferieren;
NSString *ts = @".";
NSString *s;
*resultOK = YES;
if(!s1)s1=EON;
if(dataTyp == DT_CHAR || dataTyp == DT_BOOL) return s1;
if(dataTyp == DT_DATE || dataTyp == DT_DATETIME){ PBDate *pbd;
if(!FILLED(s1))return EON;
pbd = [PBDate dateWithFreeString:s1];
if(!pbd){ [self markError];
*resultOK = NO;
return EON;
}
return [[pbd dateAsNSCD]descriptionWithCalendarFormat:ND_FORMAT];
}
s = [[s1 componentsSeparatedByString:ts]componentsJoinedByString:EON];
if([s hasSecurePrefix:@"="]){ s = [s substringFromIndex:1];
s = [[s componentsSeparatedByString:@","]componentsJoinedByString:@"."];
s = [NSSWF @"select %@;",s];
s = [_APP getSingleValueAsResultFrom:s]; //mysql rechnen lassen
}else{ s = [s point];
}
if(dataTyp == DT_MONEY)return [NSString dbFromDouble:[s doubleValue] nak:2];
return [NSString dbFromDouble:[s doubleValue] nak:nak];
}
- (NSString *)guiName;
{ if([self isAusgeblendet])return EON;
return guiName;
}
- (BOOL)buttonIsDisabled;
{ // die Buttons sollen immer gehen, auch bei inaktiven/archivierten und im Anzeigemodus; einzelne Buttons, die nicht gehen sollen, in Event selObjChanged ausschalten;
if([pba alwaysOn])return NO; // es gibt Buttons, die immer an sein sollen: Uebersichten, System-Buttons
if([tvc _fieldIsDisabled:dbName])return YES;
return NO;
}
- (BOOL)inputAllowed;
{ if(isCAsso || isButton || isImage || onlyDescr || isPortlet || [self isAusgeblendet])return NO;
if([pba targetTyp]==ATTVCPD)return (!isProtectedPba && !isProtected);
if([pba targetTyp]==ATTVCSELOBJ && ![tvc selObj])return NO;
if([pba isAutoPK] || [[pba dbName]iE:@"descri"] || [tvc _fieldIsDisabled:dbName] || [tvc anzeigemodus])return NO;
if([pba isPK]) return ((([tvc pendingAction]==pa_ins) && !isProtectedPba && !isProtected));
return ([tvc selObj] && !isProtectedPba && !isProtected);
}
- (NSString *)portletName;
{ return guiName;
}
- (void)targetToVal;
{// triggert Datenfluss vom datasource zur Asso
NSString *s;
if(isButton || onlyDescr || isPortlet)return;
if(isImage && !isNI)return; // damit wodVal funktioniert f. title bei namedIcon nur
switch([pba targetTyp]){ case ATTVCSELOBJ:
//der PBWOEditor i.allg.
[self setVal:[[tvc selObj]vfk:dbName]];
break;
case ATTVCPD:
s = [[tvc parmDict]ofk:dbName];
if(!s)s=EON;
[self setVal:s];
break;
}
}
- (void)valToTarget;
{// triggert Datenfluss von Asso zur Datasource
if(isCAsso)return;
switch([pba targetTyp]){ case ATTVCSELOBJ:
[[tvc selObj] tvfk(val,dbName)];
break;
case ATTVCPD:
if(!val)val=EON;
[[tvc parmDict]setObject:val forKey:dbName];
// didValToTarget macht sinn
break;
}
[tvc didValToTargetPba:pba];
}
- (int)descrWidthPixel;
{ if(noDescr)return 0;
if(onlyDescr || isTextArea)return width;
return descrWidthPixel;
}
- (void)determineSizeDwp:(int)dwp ewp:(int)ewp bwp:(int)bwp;
{// width u. height berechnen; wird benoetigt von singleFieldArea
// bei image erst gar nicht aufrufen
// kann erst erfolgen nachdem einige Flags gesetzt sind; nicht in init... oder setPba..
if(isImage || isPortlet){ return;
}
descrWidthPixel = dwp;
editWidthPixel = ewp;
bezWidthPixel = bwp;
height = LINEHEIGHT; //default
if(isBool){ width = [self descrWidthPixel] + editWidthPixel;
return;
}
if(hasVL){ width = [self descrWidthPixel] + editWidthPixel;
return;
}
if(isPlainField){ if(isTextArea){ width = descrWidthPixel + editWidthPixel + bezWidthPixel;
height = (([self taRows] + 1) * 16.5) + LINEHEIGHT + 4 + 1;
return;
}else{ width = [self descrWidthPixel] + editWidthPixel;
height = ([self fieldRows] * LINEHEIGHT);
if(isRelation){ //den Lookup-Button und Bez. dazurechnen width += bezWidthPixel;
}
return;
}
}
}
- (int)taHeight;
{ return height - LINEHEIGHT - 1;
}
- (void)setZeilen:(int)value;
{ zeilen = value;
}
- (int)zeilen;
{ return zeilen;
}
- (int)taCols;
{ return width / 9;
}
- (int)taRows;
{// fuer textareas
if(zeilen > 0)return zeilen; //abw. zeilen per lif
return 8;
}
- (int)fieldRows;
{// fuer alle anderen Oberflaechenelemente
if(zeilen > 0)return zeilen; //abw. zeilen per lif
return 1;
}
- (int)dataTyp;{return dataTyp;}- (void)setDataTyp:(int)value;{dataTyp = value;}- (int)classNo;{return classNo;}- (void)setClassNo:(int)value;{classNo = value;}- (int)nak;{return nak;}- (void)setNak:(int)value;{nak = value;}- init;
{ if(!(self = [super init]))return nil;
tvc = nil;
dataTyp = DT_CHAR;
isProtected = NO;
hasError = NO;
noDescr = NO;
isCAsso = NO;
onlyDescr = NO; //f. reine CustomText-Felder
isImage = NO; //f. reines bildchen anzeigen
isButton = NO;
isPortlet = NO;
isHTMLCarrier = NO;
isNI = NO; //NamedIcon
[self setBez:EON];
width=0; height=0; zeilen=0;
return self;
}
- (void)setBez:(NSString *)v;
{ if([v iE:bez])return;
[bez release];
bez = [v retain];
}
- (void)setNoDescr:(BOOL)value;
{ noDescr = value;
}
- (BOOL)noDescr;
{ return noDescr;
}
- (NSString *)heightS;
{ return NSS(height);
}
- (NSString *)widthS;
{ return NSS(width);
}
- (BOOL)isChecked;
{ if(!isBool)return NO;
return [val iE:SC_BOOL_TRUE];
}
- (void)setIsChecked:(BOOL)yn;
{ NSString *s;
if(!isBool)return;
if(yn){ s = SC_BOOL_TRUE;
}else{ s = SC_BOOL_FALSE;
}
if(![val iE:s]){ [self setValFromWod:s];
}
}
- (BOOL)isRelation;
{ return isRelation;
}
- (BOOL)hasVL;
{ return hasVL;
}
- (BOOL)isBool;
{ return isBool;
}
- (BOOL)isDate;
{ return isDate;
}
- (BOOL)shouldBeBold;
{ return shouldBeBold;
}
- (BOOL)isPlainField;
{ return isPlainField;
}
- (BOOL)isTextArea;
{ return isTextArea;
}
- (NSString *)bez;
{// bez nicht mehr in App cachen, sondern hier
if([self isAusgeblendet] || !FILLED(val)){ [self setBez:EON];
return bez;
}
if(FILLED(bez))return bez; // gecachten wert behalten
if(isRelation){ //lazy ermitteln; nicht alle assos muessen ihre bez anzeigen // nicht die bez des foreign EO holen, sondern selbst die werte der descri-Felder beschaffen
[self setBez:[_APP descriForEn:refdTableName pk:val]];
}
return bez;
}
- (BOOL)isCAsso;
{ return isCAsso;
}
- (void)setIsCAsso:(BOOL)yn;
{ isCAsso = yn;
}
- (NSString *)bezeichnungForValue:(NSString *)s;
{ if(!FILLED(s))return EON;
if(![self vl])return s;
{ int i,j;
for(i=0,j=[[self vl] count];i<j;i++){ PBVLO *pbvlo = [[self vl] oai:i];
if([[pbvlo value]iE:s]){ return [pbvlo bez]; // in richtiger Sprache
}
}
}
return EON;
}
- (NSString *)wodVal;
{// wenn man nil im response uebergibt, gilt das Feld als nicht geaendert, wenn es leer bleibt
// sonst wuerde es im takeValuesFromRequest versorgt werden
// ermittelt seinen Wert selbst bei Bedarf
if((![tvc selObj] && [pba targetTyp]==ATTVCSELOBJ && !(isCAsso)))return nil;
if(!FILLED(val))return nil;
if(isNI)return val;
if(hasVL)return [pba bezeichnungForValue:val];
return [self formatOut:val];
}
- (void)setWodVal:(NSString *)s;
{// wird von WO aufgerufen
NSString *dbVal1;
BOOL resultOK=NO;
if(![self inputAllowed])return; //es werden sehr wohl werte zurueckgeschickt! z.B. bei einer Textarea, die eigentlich gesperrt ist;
// wenn gar nicht in den formvalues enthalten, auch nix machen
if(![[[[_SESSION context]request] vfk:@"_formValues"]ofk:dbName])return;
if((dataTyp == DT_DATE || dataTyp == DT_DATETIME || isRelation) && ([s hasSecureSuffix:@"."] || [s hasSecureSuffix:@"*"])){// Kalender bzw. Lookup zum Nachschlagen aufrufen
s = [s stringWithoutLastChar];
if(isRelation){// foreign key nachschlagen;
PBWOLookup *pbe;
// mit generischem Lookup-Modul
PBSQLQualifier *cmq;
NSDictionary *rd;
NSString *soas;
pbe = (PBWOLookup *)MODUL(@"PBWOLookup");
if(!pbe){ LOGI(TRANSLATION(@"Modul PBWOLookup nicht bekommen"));
return;
}
[pbe setCallingModul:tvc]; //cleared auch callingMQ und uebernMode
[tvc setWaitingForName:self];
[pbe setNewCMQName:[tvc cmqName]];
[pbe setMyTable:[MYDD tableNamed:refdTableName]]; // loest neuzeichnen aus; dafuer muss waitingForName bereits gesetzt sein
[pbe setSuchFelderQ:nil];
//cmq per script ermitteln
[[tvc parmDict] setObject:refdTableName forKey:@"p_entityname"];
[[tvc parmDict] setObject:dbName forKey:@"p_dbName"];
[[tvc parmDict] setObject:[tvc cmqName] forKey:@"p_cmqName"];
rd = [_APP executeScriptNamed:@"getCMQForAssoFind" datasource:tvc parmDict:[tvc parmDict]];
if([[rd ofk:@"scriptRC"]iE:@"N"])return;
soas = [rd ofk:@"rp_soa"]; // sortOrderArray
if(FILLED(soas)){ [pbe setSoseq:soas];
}
cmq = [rd ofk:@"rp_cmq"];
[[pbe ma]removeAllObjects];
// Eingabe in currentAso interpretieren:
if(dataTyp == DT_INT && ([s iE:@"0"])){ s = @"";
}
[_SESSION clearErrors]; // unnoetige Meldung "artikelnr falsch..."
[pbe setCallingMQ:cmq];
[pbe setCombiSuchContent:s];
[pbe combiSucheActed];
if([[pbe ma]count]==1){ // genau 1 gefunden, direkt nehmen
[tvc takeString:[[[pbe ma]firstObject]primaryKey]];
[tvc executeDidTakeValuesFromRequest];
[pbe setCallingModul:nil]; //cleared auch callingMQ
return;
}
// sonst Trefferliste aufblenden
[tvc bringToFront:pbe];
return;
}else{ PBWOEditor *e = MODUL(@"akte");
if(e){ [[e parmDict]setObject:[_APP today] forKey:@"startingDate"];
if(FILLED(s)){ dbVal1 = [self dbFromGui:s resultOK:&resultOK];
if(resultOK){ [[e parmDict]setObject:dbVal1 forKey:@"startingDate"];
}
}
[[e parmDict]setObject:@"J" forKey:@"uebernehmen"];
[_APP kalender:e];
[e setSelectedBoxName:@"Kalender"]; // besser man aendert den Registertitel nicht...
[e minimize];
[tvc setWaitingForName:self];
[e setCallingModul:tvc]; // cleared auch callingMQ
[tvc bringToFront:e];
}else{ LOGI(TRANSLATION(@"keine Berechtigung."));
}
}
return;
}
if([self isTextArea]){ dbVal1 = [s stringWithoutTextareaCR];
if([dbVal1 rangeOfString:@"$$t"].length){ dbVal1 = [dbVal1 replace:@"$$t" with:[[NSCalendarDate date]descriptionWithCalendarFormat:ND_GUIDT_FORMAT]];
}
}else{ dbVal1 = [self dbFromGui:s resultOK:&resultOK];
if(!resultOK)return;
}
if(!FILLED(val) && !FILLED(dbVal1))return;
if([val iE:dbVal1])return;
[self setValFromWod:dbVal1];
}
- (void)setValFromWod:(NSString *)v;
{ [val release];
val = [v retain];
[self setBez:EON]; //cleared bez-cache; descri einer Relation;
[self valToTarget];
}
- (void)setVal:(NSString *)v;
{// von datasource aus
if(v==val)return;
if([v iE:val])return;
if(dataTyp == DT_MONEY || dataTyp == DT_INT || dataTyp == DT_FLOAT){ if([v doubleValue] == [val doubleValue])return;
}
if(isTextArea){ v = [v stringWithoutTextareaCR];
if([v iE:val])return;
}else{ if((dataTyp == DT_CHAR) && [v rangeOfString:@"\n"].length){ v = [[v replace:@"\n" with:@" "] replace:@"\r" with:@" "];
}
}
[val release];
val = [v retain];
[self setBez:EON]; // cleared bez-cache; descri einer Relation;
if(hasVL){// neues vlo setzen
int i,j;
for(i=0,j=[[self vl]count];i<j;i++){ PBVLO *pbvlo = [[self vl]oai:i];
if([[pbvlo value]iE:val]){ [self setSelectedPBVLO:pbvlo];
return;
}
}
[self setSelectedPBVLO:[vl firstObject]];
}
}
- (NSString *)val;
{ return val;
}
- (PBVLO *)selectedPBVLO;
{ return vlo;
}
- (void)setVlVal:(NSString *)s;
{ if(![self inputAllowed])return;
if(!FILLED(s)){ s = (NSString *)EON;
}
if(![val iE:s]){ [self setValFromWod:s];
}
}
- (void)setSelectedPBVLO:(PBVLO *)o;
{ if([vlo iE:o])return;
[vlo release];
vlo = [o retain];
[self setVlVal:[vlo value]];
}
- (NSMutableArray *)_vl;
{// um in Script zu manipulieren
if(!vl){ MA(vl);
[vl addObjectsFromArray:[pba vl]];
}
return vl;
}
- (NSArray *)vl;
{ if(vl)return vl; // dynamische haben eigene VL;
return [pba vl];
}
- (NSString *)vlVal;
{ if([self isAusgeblendet])return EON;
return val;
}
- (void)markError;
{ hasError = YES;
[[tvc errorAssos]addObjectUniq:self];
}
- (NSString *)descrAreaClass;
{ if(hasError)return @"descrAreaErr";
if(classNo)return [NSSWF @"descrArea%i",classNo];
if(shouldBeBold)return [NSSWF @"descrAreaBold",classNo];
return @"descrArea";
}
- (void)resetError;
{ hasError = NO;
}
- (NSString *)title;
{ if([self isAusgeblendet])return EON;
return [self guiName];
}
- (NSString *)nameNachschlagen;
{ return [NSSWF @"%@_nachschlagen",dbName];
}
- (NSString *)nameGotoLink;
{ return [NSSWF @"%@_GotoLink",dbName];
}
@end